Skip to content

Commit

Permalink
Add support for graph serialisation / deserialisation and abstract th…
Browse files Browse the repository at this point in the history
…e TFG cache as an injectable interface
  • Loading branch information
jankjr committed Feb 12, 2025
1 parent 2bc6831 commit 64255cb
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 163 deletions.
95 changes: 62 additions & 33 deletions src.ts/Universe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ import { PerformanceMonitor } from './searcher/PerformanceMonitor'
import { SwapPath } from './searcher/Swap'
import { ToTransactionArgs } from './searcher/ToTransactionArgs'
import { Contract } from './tx-gen/Planner'
import { TxGen } from './searcher/TxGen'
import { TokenFlowGraphRegistry, TokenFlowGraphSearcher } from './searcher/TokenFlowGraph'
import { TxGen, TxGenOptions } from './searcher/TxGen'
import { ITokenFlowGraphRegistry, InMemoryTokenFlowGraphRegistry, TokenFlowGraph, TokenFlowGraphSearcher } from './searcher/TokenFlowGraph'
import { FolioContext } from './action/Folio'
import { DeployFolioConfig, DeployFolioConfigJson } from './action/DeployFolioConfig'
import { optimiseTrades } from './searcher/optimiseTrades'
Expand Down Expand Up @@ -493,12 +493,12 @@ export class Universe<const UniverseConf extends Config = Config> {
if (stopSearch.signal.aborted || opts.abort.aborted) {
return;
}
// console.log(`${venue.name} ok: ${res.steps[0].action.toString()}`)
// this.logger.info(`${venue.name} ok: ${res.steps[0].action.toString()}`)
await onResult(res)

} catch (e: any) {
// console.log(`${venue.name} failed for case: ${tradeName}`)
// console.log(e.message)
// this.logger.info(`${venue.name} failed for case: ${tradeName}`)
// this.logger.info(e.message)
}
})
)
Expand Down Expand Up @@ -697,7 +697,25 @@ export class Universe<const UniverseConf extends Config = Config> {
return token
}

private actionById = new Map<string, Action>()
public actionExists(id: string) {
return this.actionById.has(id)
}
public getAction(id: string) {
const action = this.actionById.get(id)
if (action == null) {
throw new Error(`Action ${id} not found`)
}
return action
}
public addAction(action: Action, actionAddress?: Address) {
const id = action.actionId;
if (this.actionById.has(id)) {
this.logger.warn(`Duplicate action: ${id}`)
return
} else {
this.actionById.set(id, action)
}
if (this.allActions.has(action)) {
return this
}
Expand Down Expand Up @@ -862,8 +880,10 @@ export class Universe<const UniverseConf extends Config = Config> {
)
})
]
})
}),
private readonly tfgReg: ITokenFlowGraphRegistry = new InMemoryTokenFlowGraphRegistry(this)
) {
this.tfgSearcher = new TokenFlowGraphSearcher(this, this.tfgReg)
this.folioContext = new FolioContext(this)
const nativeToken = config.nativeToken
this.nativeToken = Token.createToken(
Expand All @@ -884,7 +904,7 @@ export class Universe<const UniverseConf extends Config = Config> {
const outputSize = (await edge.quote([inputToken.one.scalarMul(10n)]))[0]
return outputToken.from(outputSize.asNumber() / 10)
} catch (e) {
console.log(`Error finding mid price for ${edge}: ${e}`)
this.logger.info(`Error finding mid price for ${edge}: ${e}`)
throw e
}
}, 12000)
Expand Down Expand Up @@ -1013,6 +1033,7 @@ export class Universe<const UniverseConf extends Config = Config> {
logger?: winston.Logger
tokenLoader?: TokenLoader
approvalsStore?: ApprovalsStore
tokenFlowGraphCache?: ITokenFlowGraphRegistry
simulateZapFn?: SimulateZapTransactionFunction
}> = {}
) {
Expand All @@ -1030,7 +1051,8 @@ export class Universe<const UniverseConf extends Config = Config> {
opts.approvalsStore ?? new ApprovalsStore(provider),
opts.tokenLoader ?? makeTokenLoader(provider),
simulateZapFunction!,
opts.logger
opts.logger,
opts.tokenFlowGraphCache
)
// universe.oracles.push(new LPTokenPriceOracle(universe))
await Promise.all(
Expand Down Expand Up @@ -1068,8 +1090,7 @@ export class Universe<const UniverseConf extends Config = Config> {
}
}

private readonly tfgReg = new TokenFlowGraphRegistry(this)
public readonly tfgSearcher = new TokenFlowGraphSearcher(this, this.tfgReg)
public readonly tfgSearcher;


/**
Expand Down Expand Up @@ -1099,31 +1120,31 @@ export class Universe<const UniverseConf extends Config = Config> {

const isNative = userInput.token === this.nativeToken
userInput = isNative ? userInput.into(this.wrappedNativeToken) : userInput
console.log(`Building DAG for ${userInput} -> ${config.basicDetails.basket[0].token}`)
this.logger.info(`Building DAG for ${userInput} -> ${config.basicDetails.basket[0].token}`)

const userOption: TxGenOptions = Object.assign({
caller: Address.from(caller),
ethereumInput: isNative,
deployFolio: config,
slippage: opts?.slippage ?? 0.001,
recipient: Address.from(recipient),
dustRecipient: Address.from(dustRecipient),
}, opts)

const deployTFG = await this.tfgSearcher.searchZapDeploy1ToFolio(
userInput,
config,
this.config
this.config,
userOption
)

const userOption = Object.assign({
caller: Address.from(caller),
isNative,
recipient: Address.from(recipient),
dustRecipient: Address.from(dustRecipient),
}, opts)



const expectedOutput = await deployTFG.evaluate(this, [userInput])
this.logger.info(`expected zap: ${userInput} -> ${expectedOutput.result.outputs.join(', ')} fee=${expectedOutput.result.txFee}`)

return await new TxGen(this, expectedOutput).generate({
...userOption,
ethereumInput: isNative,
slippage: opts?.slippage ?? 0.001,
deployFolio: config,
})
return await new TxGen(this, expectedOutput).generate(userOption)
}

public async supportedTokens() {
Expand Down Expand Up @@ -1153,26 +1174,34 @@ export class Universe<const UniverseConf extends Config = Config> {
try {
const isNative = userInput.token === this.nativeToken
userInput = isNative ? userInput.into(this.wrappedNativeToken) : userInput
console.log(`Building DAG for ${userInput} -> ${outputToken}`)
this.logger.info(`Building DAG for ${userInput} -> ${outputToken}`)

const txGenOptions: TxGenOptions = {
...options,
ethereumInput: isNative,
slippage: opts?.slippage ?? 0.001
}
const tfg = await this.tfgSearcher.search1To1(
userInput,
outputToken,
this.config
this.config,
txGenOptions
)
const serialized = tfg.serialize()
console.log(tfg.toDot().join("\n"))
const deserializedTfg = await TokenFlowGraph.deserialize(this, serialized)
console.log(deserializedTfg.toDot().join("\n"))

const res = await tfg.evaluate(this, [userInput])
console.log(`Expected output: ${res.result.inputs.join(', ')} -> ${res.result.outputs.filter(i => i.amount >10n).join(', ')}`)
this.logger.info(`Expected output: ${res.result.inputs.join(', ')} -> ${res.result.outputs.filter(i => i.amount >10n).join(', ')}`)
try {
return await new TxGen(this, res).generate({
...options,
ethereumInput: isNative,
slippage: opts?.slippage ?? 0.001
})
return await new TxGen(this, res).generate(txGenOptions)
} catch (e) {
this.tfgReg.purgeResult(userInput, outputToken)
throw e
}
} catch (e) {
console.log(`Error zapping: ${e}`)
this.logger.info(`Error zapping: ${e}`)
throw e
}
}
Expand Down
8 changes: 8 additions & 0 deletions src.ts/action/Action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ export abstract class BaseAction {
public readonly gen = gen
public readonly genUtils = plannerUtils

public get actionId() {
return `${this.constructor.name}[${this.protocol}.${this.actionName}@${
this.address
}](${this.inputToken.map((i) => i.address).join(',')}->${this.outputToken
.map((i) => i.address)
.join(',')})`
}

public allTokens_ = new Set<Token>()
public allBalances_: TokenQuantity[] = []
public allBalancesBlock_: number = 0
Expand Down
36 changes: 36 additions & 0 deletions src.ts/configuration/data/base/tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
"name": "USD Dollar",
"decimals": 8
},
{
"address": "0x000000000000012def132e61759048be5b5c6033",
"symbol": "CX",
"name": "CX",
"decimals": 18
},
{
"address": "0x00000000000007c8612ba63df8ddefd9e6077c97",
"symbol": "",
Expand Down Expand Up @@ -1397,6 +1403,12 @@
"name": "Mizuki",
"decimals": 9
},
{
"address": "0x067ae75628177fd257c2b1e500993e1a0babcbd1",
"symbol": "aBasGHO",
"name": "aBasGHO",
"decimals": 18
},
{
"address": "0x0683c6f71525157242c6483876179081e7849bff",
"symbol": "CARINA",
Expand Down Expand Up @@ -12413,6 +12425,12 @@
"name": "IDLY",
"decimals": 18
},
{
"address": "0x38e59ade183bbeb94583d44213c8f3297e9933e9",
"symbol": "variableDebtBasGHO",
"name": "variableDebtBasGHO",
"decimals": 18
},
{
"address": "0x38f9bf9dce51833ec7f03c9dc218197999999999",
"symbol": "NYA",
Expand Down Expand Up @@ -21863,6 +21881,12 @@
"name": "PAID",
"decimals": 18
},
{
"address": "0x655db36d44dae7bf1fcd1fcacb23b4912de62634",
"symbol": "NEXISAI",
"name": "NEXISAI",
"decimals": 18
},
{
"address": "0x655e1cb3f2c81c76856302679648df698a5f1989",
"symbol": "GLI",
Expand Down Expand Up @@ -23141,6 +23165,12 @@
"name": "vAMM-USDC/BONKE",
"decimals": 18
},
{
"address": "0x6bb7a212910682dcfdbd5bcbb3e28fb4e8da10ee",
"symbol": "GHO",
"name": "GHO",
"decimals": 18
},
{
"address": "0x6bc2b59e103fdb35444eda1444e04cc556c8748d",
"symbol": "SHIB",
Expand Down Expand Up @@ -32891,6 +32921,12 @@
"name": "JESSIE",
"decimals": 18
},
{
"address": "0x9f85def7dcd1db5d369eaa4338b04e70d7045d77",
"symbol": "hui",
"name": "hui",
"decimals": 18
},
{
"address": "0x9f9594cdf2aa78f5f7ef80a0fef44d157f507fc6",
"symbol": "vAMM-WETH/BALD",
Expand Down
13 changes: 6 additions & 7 deletions src.ts/configuration/setupAaveV3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export class AaveV3Reserve {
return (
await this.aave.poolInst.callStatic.getReserveNormalizedIncome(
this.reserveToken.address.address,
{ blockTag: "pending" }
{ blockTag: 'pending' }
)
).toBigInt()
}
Expand Down Expand Up @@ -213,8 +213,6 @@ export class AaveV3Deployment {
)
this.reserves.push(reserve)
this.tokenToReserve.set(reserve.aToken, reserve)
this.universe.addAction(reserve.supply)
this.universe.addAction(reserve.withdraw)
return reserve
}

Expand Down Expand Up @@ -265,10 +263,11 @@ export class AaveV3Deployment {

private wrappers: AaveV3Wrapper[] = []
private wrapperTokens = new DefaultMap<Token, Promise<AaveV3Wrapper>>(
(wrapper) => AaveV3Wrapper.create(this, wrapper).then((w) => {
this.wrappers.push(w)
return w
})
(wrapper) =>
AaveV3Wrapper.create(this, wrapper).then((w) => {
this.wrappers.push(w)
return w
})
)
public async addWrapper(wrapper: Token) {
return await this.wrapperTokens.get(wrapper)
Expand Down
3 changes: 3 additions & 0 deletions src.ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import { setupBaseZapper } from './configuration/setupBaseZapper'
import { EthereumUniverse, ethereumConfig } from './configuration/ethereum'
import { setupEthereumZapper } from './configuration/setupEthereumZapper'

export { TokenFlowGraph, TokenFlowGraphSearcher, TokenFlowGraphBuilder, ITokenFlowGraphRegistry } from './searcher/TokenFlowGraph'
export { ZapTransaction } from './searcher/ZapTransaction'

import { loadTokens } from './configuration/loadTokens'
import { makeConfig } from './configuration/ChainConfiguration'
import { JsonRpcProvider } from '@ethersproject/providers'
Expand Down
Loading

0 comments on commit 64255cb

Please sign in to comment.