packages/synapse-interface/utils/actions/getPoolData.ts
import { multicall } from '@wagmi/core'
import { erc20Abi } from 'viem'
import { Token, PoolData } from '@types'
import { formatBigIntToString } from '@utils/bigint/format'
import { getPoolTokenInfoArr, getTokenBalanceInfo } from '@utils/poolDataFuncs'
import { getEthPrice, getAvaxPrice } from '@utils/actions/getPrices'
import lpTokenABI from '@/constants/abis/lpToken.json'
import { SWAP_ABI } from '@/constants/abis/swap'
import { wagmiConfig } from '@/wagmiConfig'
export const getBalanceData = async ({
pool,
chainId,
address,
lpTokenAddress,
}: {
pool: Token
chainId: number
address: string
lpTokenAddress: string
}) => {
const tokens: Token[] = [...pool?.poolTokens, pool]
const tokenBalances = []
let poolTokenSum = 0n
let lpTokenBalance = 1n
const multicallInputs = []
const one = {
address: lpTokenAddress,
abi: lpTokenABI,
functionName: 'totalSupply',
chainId,
}
multicallInputs.push(one)
tokens?.forEach((token, index) => {
const isLP = token.addresses[chainId] === lpTokenAddress
// Use pool's getTokenBalance for pool tokens, if the address is the pool itself
// to exclude the unclaimed admin fees
if (address === pool.swapAddresses[chainId] && !isLP) {
multicallInputs.push({
address: pool.swapAddresses[chainId],
abi: SWAP_ABI,
functionName: 'getTokenBalance',
chainId,
args: [index],
})
} else {
multicallInputs.push({
address: token.addresses[chainId],
abi: erc20Abi,
functionName: 'balanceOf',
chainId,
args: [address],
})
}
})
const two = {
address: pool.swapAddresses[chainId],
abi: SWAP_ABI,
functionName: 'swapStorage',
chainId,
}
const three = {
address: pool.swapAddresses[chainId],
abi: SWAP_ABI,
functionName: 'getVirtualPrice',
chainId,
}
multicallInputs.push(two)
multicallInputs.push(three)
// @ts-ignore
const multicallData: any[] = await multicall(wagmiConfig, {
contracts: multicallInputs,
chainId,
}).catch((error) => {
console.error('Multicall failed:', error)
return []
})
const lpTotalSupply = multicallData[0].result ?? 0n
tokens.forEach((token, index) => {
const isLP = token.addresses[chainId] === lpTokenAddress
tokenBalances.push({
rawBalance: multicallData[index + 1].result ?? 0n,
balance: formatBigIntToString(
multicallData[index + 1].result,
token.decimals[chainId]
),
token,
isLP,
})
if (isLP) {
lpTokenBalance = multicallData[index + 1].result
}
poolTokenSum = poolTokenSum + multicallData[index + 1].result
})
return {
tokenBalances,
poolTokenSum,
lpTokenBalance,
lpTotalSupply,
}
}
export const getSinglePoolData = async (
chainId: number,
pool: Token,
prices?: any
): Promise<PoolData> => {
const poolAddress = pool?.swapAddresses[chainId]
if (!pool || !poolAddress) {
return null
}
const lpTokenAddress = pool?.addresses[chainId]
const { tokenBalances } = await getBalanceData({
pool,
chainId,
address: poolAddress,
lpTokenAddress,
})
const ethPrice = prices?.ethPrice ?? (await getEthPrice())
const avaxPrice = prices?.avaxPrice ?? (await getAvaxPrice())
const {
tokenBalancesSum,
tokenBalancesUSD,
}: { tokenBalancesSum: number; tokenBalancesUSD: number } =
getTokenBalanceInfo({
tokenBalances: tokenBalances.filter((t) => !t.isLP).map((t) => t.balance),
prices: {
ethPrice,
avaxPrice,
},
poolType: pool?.poolType,
})
const poolTokensMatured = getPoolTokenInfoArr({
tokenBalances: tokenBalances.filter((t) => !t.isLP),
tokenBalancesSum,
})
return {
name: pool.name,
tokens: poolTokensMatured,
totalLocked: tokenBalancesSum,
totalLockedUSD: tokenBalancesUSD,
}
}