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

perf: Dont fetch v2 expired pools data and make price fetcher unique #10869

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
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
105 changes: 59 additions & 46 deletions apps/web/src/state/farmsV4/state/poolApr/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,23 +389,56 @@ const getV2PoolsCakeAprByChainId = async (
} as const
})

const totalSupplyCalls = validPools.map((pool) => {
const endTimestampCalls = validPools.map((pool) => {
return {
address: pool.bCakeWrapperAddress!,
functionName: 'endTimestamp',
abi: v2BCakeWrapperABI,
} as const
})

const [rewardPerSecondResults, endTimestamps] = await Promise.all([
client.multicall({
contracts: rewardPerSecondCalls,
allowFailure: false,
}),
client.multicall({
contracts: endTimestampCalls,
allowFailure: false,
}),
])

const activeRewardPerSecondResults: bigint[] = []

const now = dayjs().unix()

const activeValidPools = validPools.filter((pool, index) => {
const rewardPerSecond = rewardPerSecondResults[index]
if (!rewardPerSecond) return false
const endTimestamp = endTimestamps[index]
const expired = endTimestamp && Number(endTimestamp) < now
if (expired) return false
activeRewardPerSecondResults.push(rewardPerSecond)
return true
})

const totalSupplyCalls = activeValidPools.map((pool) => {
return {
address: pool.lpAddress,
functionName: 'totalSupply',
abi: erc20Abi,
} as const
})

const reserve0Calls = validPools.map((pool) => {
const reserve0Calls = activeValidPools.map((pool) => {
return {
address: pool.token0.wrapped.address,
functionName: 'balanceOf',
abi: erc20Abi,
args: [pool.stableSwapAddress ?? pool.lpAddress],
} as const
})
const reserve1Calls = validPools.map((pool) => {
const reserve1Calls = activeValidPools.map((pool) => {
return {
address: pool.token1.wrapped.address,
functionName: 'balanceOf',
Expand All @@ -414,64 +447,44 @@ const getV2PoolsCakeAprByChainId = async (
} as const
})

const totalBoostedShareCalls = validPools.map((pool) => {
const totalBoostedShareCalls = activeValidPools.map((pool) => {
return {
address: pool.bCakeWrapperAddress!,
functionName: 'totalBoostedShare',
abi: v2BCakeWrapperABI,
} as const
})

const endTimestampCalls = validPools.map((pool) => {
return {
address: pool.bCakeWrapperAddress!,
functionName: 'endTimestamp',
abi: v2BCakeWrapperABI,
} as const
})

const priceCalls = validPools.map(async (pool) => {
const priceCalls = activeValidPools.map(async (pool) => {
return Promise.all([usdPriceBatcher.fetch(pool.token0), usdPriceBatcher.fetch(pool.token1)])
})

const [rewardPerSecondResults, totalBoostedShareResults, totalSupplies, reserve0s, reserve1s, endTimestamps, prices] =
await Promise.all([
client.multicall({
contracts: rewardPerSecondCalls,
allowFailure: false,
}),
client.multicall({
contracts: totalBoostedShareCalls,
allowFailure: false,
}),
client.multicall({
contracts: totalSupplyCalls,
allowFailure: false,
}),
client.multicall({
contracts: reserve0Calls,
allowFailure: false,
}),
client.multicall({
contracts: reserve1Calls,
allowFailure: false,
}),
client.multicall({
contracts: endTimestampCalls,
allowFailure: false,
}),
Promise.all(priceCalls),
])
const [totalBoostedShareResults, totalSupplies, reserve0s, reserve1s, prices] = await Promise.all([
client.multicall({
contracts: totalBoostedShareCalls,
allowFailure: false,
}),
client.multicall({
contracts: totalSupplyCalls,
allowFailure: false,
}),
client.multicall({
contracts: reserve0Calls,
allowFailure: false,
}),
client.multicall({
contracts: reserve1Calls,
allowFailure: false,
}),
Promise.all(priceCalls),
])

return validPools.reduce((acc, pool, index) => {
const rewardPerSecond = rewardPerSecondResults[index]
return activeValidPools.reduce((acc, pool, index) => {
const rewardPerSecond = activeRewardPerSecondResults[index]
const totalBoostShare = totalBoostedShareResults[index]
const endTimestamp = endTimestamps[index]
const expired = endTimestamp && Number(endTimestamp) < dayjs().unix()
const [token0PriceUsd, token1PriceUsd] = prices[index]
const token0Reserve = reserve0s[index]
const token1Reserve = reserve1s[index]
if (!rewardPerSecond || expired) return acc
const key = `${chainId}:${safeGetAddress(pool.lpAddress)}`
set(
acc,
Expand Down
6 changes: 5 additions & 1 deletion apps/web/src/utils/batcher.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { CurrencyParams, CurrencyUsdResult, getCurrencyKey, getCurrencyListUsdPrice } from '@pancakeswap/price-api-sdk'
import { create, windowedFiniteBatchScheduler } from '@yornaath/batshit'
import uniqBy from 'lodash/uniqBy'

export const usdPriceBatcher = create<CurrencyUsdResult, CurrencyParams, number>({
// The fetcher resolves the list of queries to one single api call.
fetcher: async (params: CurrencyParams[]) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

batcher shallowly compares currencyparams (which are tokens where it is called) and if same tokens are different objects it can be double fetched because of that

return getCurrencyListUsdPrice(params)
const uniqueParams = uniqBy(params, (p) => {
return p.isNative ? `${p.chainId}-native` : `${p.chainId}-${p.address}`
})
return getCurrencyListUsdPrice(uniqueParams)
},
// when we call usdPriceBatcher.fetch, this will resolve the correct currency from the result.
resolver(items, query) {
Expand Down
Loading