Skip to content

Commit

Permalink
Merge pull request #10 from rainlanguage/2024-04-27-data-fetcher-options
Browse files Browse the repository at this point in the history
data fetcher options
  • Loading branch information
thedavidmeister authored May 6, 2024
2 parents 95316ac + 1f3530d commit 6c79a92
Show file tree
Hide file tree
Showing 7 changed files with 468 additions and 212 deletions.
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

0 comments on commit 6c79a92

Please sign in to comment.