@lifi/widget
Version:
LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.
91 lines (77 loc) • 2.89 kB
text/typescript
import type { RouteExtended } from '@lifi/sdk'
import { useAccount } from '@lifi/wallet-management'
import { keepPreviousData, useQuery } from '@tanstack/react-query'
import { parseUnits } from 'viem'
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
import { useFieldValues } from '../stores/form/useFieldValues.js'
import { isRouteDone } from '../stores/routes/utils.js'
import { getQueryKey } from '../utils/queries.js'
import { useTokenAddressBalance } from './useTokenAddressBalance.js'
import { getTokenBalancesWithRetry } from './useTokenBalance.js'
const refetchInterval = 30_000
export const useFromTokenSufficiency = (route?: RouteExtended) => {
const [fromChainId, fromTokenAddress, fromAmount] = useFieldValues(
'fromChain',
'fromToken',
'fromAmount'
)
const { keyPrefix } = useWidgetConfig()
let chainId = fromChainId
let tokenAddress = fromTokenAddress
if (route) {
chainId = route.fromToken.chainId
tokenAddress = route.fromToken.address
}
const {
token,
chain,
isLoading: isTokenAddressBalanceLoading,
} = useTokenAddressBalance(chainId, tokenAddress)
const { account } = useAccount({ chainType: chain?.chainType })
const { data: insufficientFromToken, isLoading } = useQuery({
queryKey: [
getQueryKey('from-token-sufficiency-check', keyPrefix),
account.address,
chainId,
tokenAddress,
route?.id ?? fromAmount,
] as const,
queryFn: async ({ queryKey: [, accountAddress] }) => {
if (!accountAddress || !token) {
return
}
const parsedFromAmount = parseUnits(fromAmount, token.decimals)
let currentTokenBalance = token.amount ?? 0n
if (!route || isRouteDone(route)) {
const insufficientFunds = currentTokenBalance < parsedFromAmount
return insufficientFunds
}
const currentAction = route.steps.filter(
(step) => !step.execution || step.execution.status !== 'DONE'
)[0]?.action
if (
token.chainId === currentAction.fromToken.chainId &&
token.address === currentAction.fromToken.address &&
currentTokenBalance > 0
) {
const insufficientFunds = BigInt(route.fromAmount) > currentTokenBalance
return insufficientFunds
}
const tokenBalances = await getTokenBalancesWithRetry(accountAddress, [
currentAction.fromToken,
])
currentTokenBalance = tokenBalances?.[0]?.amount ?? 0n
const insufficientFunds =
BigInt(currentAction.fromAmount) > currentTokenBalance
return insufficientFunds
},
enabled: Boolean(account.address && token && !isTokenAddressBalanceLoading),
refetchInterval,
staleTime: refetchInterval,
placeholderData: account.address ? keepPreviousData : undefined,
})
return {
insufficientFromToken,
isLoading,
}
}