From e2817875f48efb3e1d896dc2e92c81c15603a7c6 Mon Sep 17 00:00:00 2001 From: Eugene Chybisov Date: Sat, 6 Aug 2022 15:34:14 +0100 Subject: [PATCH] fix: gas sufficiency message appears after reloading while executing the route --- .../src/components/TokenList/TokenList.tsx | 10 ++++- .../widget/src/hooks/useGasSufficiency.ts | 31 ++++++++------ packages/widget/src/hooks/useTokenBalance.ts | 2 +- packages/widget/src/hooks/useTokenBalances.ts | 42 +++++++++++++------ 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/packages/widget/src/components/TokenList/TokenList.tsx b/packages/widget/src/components/TokenList/TokenList.tsx index 608505791..0961946fb 100644 --- a/packages/widget/src/components/TokenList/TokenList.tsx +++ b/packages/widget/src/components/TokenList/TokenList.tsx @@ -30,8 +30,14 @@ export const TokenList: FC = ({ 250, ); - const { tokens, isLoading, isBalanceLoading } = - useTokenBalances(selectedChainId); + const { + tokens: tokensWithoutBalance, + tokensWithBalance, + isLoading, + isBalanceLoading, + } = useTokenBalances(selectedChainId); + + const tokens = tokensWithBalance ?? tokensWithoutBalance; const chainTokens = useMemo(() => { let chainTokens = tokens ?? []; diff --git a/packages/widget/src/hooks/useGasSufficiency.ts b/packages/widget/src/hooks/useGasSufficiency.ts index 3c0eaf9d1..f67fd4984 100644 --- a/packages/widget/src/hooks/useGasSufficiency.ts +++ b/packages/widget/src/hooks/useGasSufficiency.ts @@ -26,14 +26,22 @@ export const useGasSufficiency = (route?: Route) => { SwapFormKey.FromToken, ], }); + const fromAmount = useDebouncedWatch(SwapFormKey.FromAmount, 250); - const { tokens: fromChainTokenBalances, isBalanceFetched } = - useTokenBalances(fromChainId); - const { tokens: toChainTokenBalances } = useTokenBalances(toChainId); const { getChainById } = useChains(); + const { tokensWithBalance: fromChainTokenBalances } = + useTokenBalances(fromChainId); + const { tokensWithBalance: toChainTokenBalances } = + useTokenBalances(toChainId); const insufficientGas = useMemo(() => { - if (!account.isActive || !route || !fromAmount) { + if ( + !account.isActive || + !route || + !fromAmount || + !fromChainTokenBalances || + !toChainTokenBalances + ) { return []; } @@ -118,20 +126,19 @@ export const useGasSufficiency = (route?: Route) => { ]); const insufficientFunds = useMemo(() => { - if (!account.isActive || !fromToken || !fromAmount || !isBalanceFetched) { + if ( + !account.isActive || + !fromToken || + !fromAmount || + !fromChainTokenBalances + ) { return false; } const balance = Big( fromChainTokenBalances?.find((t) => t.address === fromToken)?.amount ?? 0, ); return Big(fromAmount).gt(balance); - }, [ - account.isActive, - fromAmount, - fromChainTokenBalances, - fromToken, - isBalanceFetched, - ]); + }, [account.isActive, fromAmount, fromChainTokenBalances, fromToken]); return { insufficientGas, diff --git a/packages/widget/src/hooks/useTokenBalance.ts b/packages/widget/src/hooks/useTokenBalance.ts index deca69fa9..71c81ee93 100644 --- a/packages/widget/src/hooks/useTokenBalance.ts +++ b/packages/widget/src/hooks/useTokenBalance.ts @@ -17,7 +17,7 @@ export const useTokenBalance = (chainId: number, tokenAddress: string) => { isFetching, refetch, } = useQuery( - ['token', account.address, chainId, tokenAddress], + ['token-balance', account.address, chainId, tokenAddress], async ({ queryKey: [, address] }) => { if (!address || !token) { return null; diff --git a/packages/widget/src/hooks/useTokenBalances.ts b/packages/widget/src/hooks/useTokenBalances.ts index 9c8532fd2..d7da8f5f8 100644 --- a/packages/widget/src/hooks/useTokenBalances.ts +++ b/packages/widget/src/hooks/useTokenBalances.ts @@ -1,18 +1,23 @@ +/* eslint-disable consistent-return */ import { TokenAmount } from '@lifi/sdk'; import { useQuery } from '@tanstack/react-query'; +import { useState } from 'react'; import { LiFi } from '../config/lifi'; import { useWallet } from '../providers/WalletProvider'; import { formatTokenAmount } from '../utils'; -import { useChains } from './useChains'; import { useTokens } from './useTokens'; +const defaultRefetchInterval = 60_000; +const minRefetchInterval = 1000; + export const useTokenBalances = (selectedChainId: number) => { const { account } = useWallet(); - const { chains, isLoading: isChainsLoading } = useChains(); const { tokens, isLoading } = useTokens(selectedChainId); + const [refetchInterval, setRefetchInterval] = useState( + defaultRefetchInterval, + ); - const isBalanceLoadingEnabled = - Boolean(account.address) && Boolean(tokens) && Boolean(chains); + const isBalanceLoadingEnabled = Boolean(account.address) && Boolean(tokens); const { data: tokensWithBalance, @@ -21,14 +26,26 @@ export const useTokenBalances = (selectedChainId: number) => { refetch, } = useQuery( ['token-balances', selectedChainId, account.address], - async ({ queryKey: [_, chainId, account] }) => { - if (!account || !tokens) { - return []; + async ({ queryKey: [, , accountAddress] }) => { + if (!accountAddress || !tokens) { + return; } const tokenBalances = await LiFi.getTokenBalances( - account as string, + accountAddress as string, tokens, ); + + if (!tokenBalances?.length) { + // Sometimes RPCs (e.g. Arbitrum) don't return balances on first call + // TODO: fix and remove backplane + setRefetchInterval((interval) => + interval === defaultRefetchInterval + ? minRefetchInterval + : interval * 2, + ); + return; + } + const formatedTokens = ( tokenBalances.length === 0 ? (tokens as TokenAmount[]) : tokenBalances ).map((token) => { @@ -49,14 +66,15 @@ export const useTokenBalances = (selectedChainId: number) => { { enabled: isBalanceLoadingEnabled, refetchIntervalInBackground: true, - refetchInterval: 60_000, - staleTime: 60_000, + refetchInterval, + staleTime: refetchInterval, }, ); return { - tokens: tokensWithBalance ?? (tokens as TokenAmount[] | undefined), - isLoading: isLoading || isChainsLoading, + tokens, + tokensWithBalance, + isLoading, isBalanceLoading: isBalanceLoading && isBalanceLoadingEnabled, isBalanceFetched, updateBalances: refetch,