Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

data fetcher options #10

Merged
merged 4 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions packages/sushi/src/router/data-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ import { UniswapV2Provider } from './liquidity-providers/UniswapV2.js'
import { UniswapV3Provider } from './liquidity-providers/UniswapV3.js'
import type { PoolCode } from './pool-codes/index.js'

// options for data fetching, such as pinning block number and memoize
export type DataFetcherOptions = {
/**
* The pinned block number when getting onchain data
* this option is usefull for reproducing the route,
* price, etc of a certain block
*/
blockNumber?: bigint
/** Determines if memoizer should be used or not */
memoize?: boolean
}

// TODO: Should be a mode on the config for DataFetcher
const isTest =
process.env['APP_ENV'] === 'test' ||
Expand Down Expand Up @@ -169,6 +181,7 @@ export class DataFetcher {
currency0: Type,
currency1: Type,
excludePools?: Set<string>,
options?: DataFetcherOptions,
): Promise<void> {
// console.log('PROVIDER COUNT', this.providers.length)
// ensure that we only fetch the native wrap pools if the token is the native currency and wrapped native currency
Expand All @@ -177,21 +190,26 @@ export class DataFetcher {
(p) => p.getType() === LiquidityProviders.NativeWrap,
)
if (provider) {
await provider.fetchPoolsForToken(
currency0.wrapped,
currency1.wrapped,
excludePools,
)
try {
await provider.fetchPoolsForToken(
currency0.wrapped,
currency1.wrapped,
excludePools,
options,
)
} catch {
/**/
}
}
} else {
const [token0, token1] =
currency0.wrapped.equals(currency1.wrapped) ||
currency0.wrapped.sortsBefore(currency1.wrapped)
? [currency0.wrapped, currency1.wrapped]
: [currency1.wrapped, currency0.wrapped]
await Promise.all(
await Promise.allSettled(
this.providers.map((p) =>
p.fetchPoolsForToken(token0, token1, excludePools),
p.fetchPoolsForToken(token0, token1, excludePools, options),
),
)
}
Expand Down
55 changes: 46 additions & 9 deletions packages/sushi/src/router/liquidity-providers/CurveProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import {
} from '../../currency/index.js'
import { Native, Token, Type } from '../../currency/index.js'
import { RToken, createCurvePoolsForMultipool } from '../../tines/index.js'
import { DataFetcherOptions } from '../data-fetcher.js'
import { getCurrencyCombinations } from '../get-currency-combinations.js'
import { memoizer } from '../memoizer.js'
import { CurvePoolCode } from '../pool-codes/CurvePool.js'
import { PoolCode } from '../pool-codes/PoolCode.js'
import { LiquidityProvider, LiquidityProviders } from './LiquidityProvider.js'
Expand Down Expand Up @@ -379,9 +381,13 @@ export class CurveProvider extends LiquidityProvider {
t0: Token,
t1: Token,
excludePools?: Set<string>,
options?: DataFetcherOptions,
): Promise<Map<Address, [CurvePoolType, Type[]]>> {
const pools: Map<Address, [CurvePoolType, Type[]]> = new Map()
let currencyCombinations = getCurrencyCombinations(this.chainId, t0, t1)

const multicallMemoize = await memoizer.fn(this.client.multicall)

for (let i = 0; currencyCombinations.length > 0; ++i) {
const calls = (CURVE_FACTORY_ADDRESSES[this.chainId] ?? []).flatMap(
(factory) =>
Expand All @@ -397,12 +403,28 @@ export class CurveProvider extends LiquidityProvider {
] as const,
})),
)
const newFoundPools = await this.client.multicall({
const newfoundPoolsData = {
multicallAddress: this.client.chain?.contracts?.multicall3
?.address as '0x${string}',
allowFailure: true,
blockNumber: options?.blockNumber,
contracts: calls,
})
}
const newFoundPools: (
| {
error?: undefined
result: `0x${string}`
status: 'success'
}
| {
error: Error
result?: undefined
status: 'failure'
}
)[] = options?.memoize
? ((await multicallMemoize(newfoundPoolsData)) as any)
: await this.client.multicall(newfoundPoolsData)

newFoundPools.forEach((pool, i) => {
if (
pool.status === 'success' &&
Expand All @@ -429,12 +451,16 @@ export class CurveProvider extends LiquidityProvider {

async getPoolRatio(
pools: [string, [CurvePoolType, Type[]]][],
options?: DataFetcherOptions,
): Promise<(number[] | undefined)[]> {
if (this.chainId === ChainId.ETHEREUM) {
const ratios = await this.client.multicall({
const multicallMemoize = await memoizer.fn(this.client.multicall)

const ratiosData = {
multicallAddress: this.client.chain?.contracts?.multicall3
?.address as '0x${string}',
allowFailure: true,
blockNumber: options?.blockNumber,
contracts: [
{
address: '0xE95A203B1a91a908F9B9CE46459d101078c2c3cb', // ankr
Expand Down Expand Up @@ -467,7 +493,11 @@ export class CurveProvider extends LiquidityProvider {
functionName: 'exchangeRateCurrent',
},
],
})
} as any
const ratios = options?.memoize
? ((await multicallMemoize(ratiosData)) as any)
: await this.client.multicall(ratiosData)

return pools.map(([poolAddress]) => {
// collection of freaks
switch (poolAddress.toLowerCase()) {
Expand Down Expand Up @@ -498,9 +528,10 @@ export class CurveProvider extends LiquidityProvider {

async getCurvePoolCodes(
pools: Map<Address, [CurvePoolType, Type[]]>,
options?: DataFetcherOptions,
): Promise<PoolCode[]> {
const poolArray = Array.from(pools.entries())
const poolsMulticall = <
const poolsMulticall = async <
T extends ContractFunctionParameters<
(typeof curvePoolABI)[keyof typeof curvePoolABI]
>['functionName'],
Expand All @@ -512,18 +543,23 @@ export class CurveProvider extends LiquidityProvider {
T
>['args'],
) => {
return this.client.multicall({
const multicallMemoize = await memoizer.fn(this.client.multicall)
const data = {
multicallAddress: this.client.chain?.contracts?.multicall3
?.address as '0x${string}',
allowFailure: true,
blockNumber: options?.blockNumber,
contracts: poolArray.map(([address, [poolType]]) => ({
address: address as Address,
// //chainId: this.chainId,
abi: curvePoolABI[poolType],
functionName: functionName,
args,
})) as any,
})
} as any
return options?.memoize
? (multicallMemoize(data) as any)
: this.client.multicall(data)
}
// const poolContract = getContract({
// address: poolAddress as '0x${string}',
Expand Down Expand Up @@ -581,9 +617,10 @@ export class CurveProvider extends LiquidityProvider {
t0: Token,
t1: Token,
excludePools?: Set<string>,
options?: DataFetcherOptions,
): Promise<void> {
const pools = await this.getPoolsForTokens(t0, t1, excludePools)
this.foundPools = await this.getCurvePoolCodes(pools)
const pools = await this.getPoolsForTokens(t0, t1, excludePools, options)
this.foundPools = await this.getCurvePoolCodes(pools, options)
//console.log(JSON.stringify(this.foundPools, undefined, ' '))
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PublicClient } from 'viem'
import { ChainId, chainShortName } from '../../chain/index.js'
import type { Token } from '../../currency/index.js'
import { DataFetcherOptions } from '../data-fetcher.js'
import type { PoolCode } from '../pool-codes/index.js'

export enum LiquidityProviders {
Expand Down Expand Up @@ -79,6 +80,7 @@ export abstract class LiquidityProvider {
t0: Token,
t1: Token,
excludePools?: Set<string>,
options?: DataFetcherOptions,
): Promise<void>

/**
Expand Down
Loading
Loading