diff --git a/.changeset/tall-cameras-sniff.md b/.changeset/tall-cameras-sniff.md new file mode 100644 index 00000000..6f3fad0e --- /dev/null +++ b/.changeset/tall-cameras-sniff.md @@ -0,0 +1,5 @@ +--- +'@reservoir0x/relay-kit-ui': patch +--- + +Fix solana balance cached after swapping diff --git a/packages/ui/src/components/widgets/SwapWidgetRenderer.tsx b/packages/ui/src/components/widgets/SwapWidgetRenderer.tsx index 87a35591..85f247cb 100644 --- a/packages/ui/src/components/widgets/SwapWidgetRenderer.tsx +++ b/packages/ui/src/components/widgets/SwapWidgetRenderer.tsx @@ -241,7 +241,8 @@ const SwapWidgetRenderer: FC = ({ value: fromBalance, queryKey: fromBalanceQueryKey, isLoading: isLoadingFromBalance, - isError: fromBalanceErrorFetching + isError: fromBalanceErrorFetching, + isDuneBalance: fromBalanceIsDune } = useCurrencyBalance({ chain: fromChain, address: address, @@ -252,7 +253,8 @@ const SwapWidgetRenderer: FC = ({ const { value: toBalance, queryKey: toBalanceQueryKey, - isLoading: isLoadingToBalance + isLoading: isLoadingToBalance, + isDuneBalance: toBalanceIsDune } = useCurrencyBalance({ chain: toChain, address: recipient, @@ -261,10 +263,45 @@ const SwapWidgetRenderer: FC = ({ }) const invalidateBalanceQueries = useCallback(() => { - queryClient.invalidateQueries({ queryKey: fromBalanceQueryKey }) - queryClient.invalidateQueries({ queryKey: toBalanceQueryKey }) + const invalidatePeriodically = (invalidateFn: () => void) => { + let maxRefreshes = 5 + let refreshCount = 0 + const timer = setInterval(() => { + refreshCount++ + if (maxRefreshes === refreshCount) { + clearInterval(timer) + return + } + invalidateFn() + }, 1000) + } + queryClient.invalidateQueries({ queryKey: ['useDuneBalances'] }) - }, [queryClient, fromBalanceQueryKey, toBalanceQueryKey, address]) + + // Dune balances are sometimes stale, because of this we need to aggressively fetch them + // for a predetermined period to make sure we get back a fresh response + if (fromBalanceIsDune) { + invalidatePeriodically(() => { + queryClient.invalidateQueries({ queryKey: fromBalanceQueryKey }) + }) + } else { + queryClient.invalidateQueries({ queryKey: fromBalanceQueryKey }) + } + if (toBalanceIsDune) { + invalidatePeriodically(() => { + queryClient.invalidateQueries({ queryKey: toBalanceQueryKey }) + }) + } else { + queryClient.invalidateQueries({ queryKey: toBalanceQueryKey }) + } + }, [ + queryClient, + fromBalanceQueryKey, + toBalanceQueryKey, + toBalanceIsDune, + fromBalanceIsDune, + address + ]) const { data: capabilities } = useCapabilities({ query: { enabled: diff --git a/packages/ui/src/hooks/useCurrencyBalance.ts b/packages/ui/src/hooks/useCurrencyBalance.ts index cc1911b2..240d62fb 100644 --- a/packages/ui/src/hooks/useCurrencyBalance.ts +++ b/packages/ui/src/hooks/useCurrencyBalance.ts @@ -26,6 +26,7 @@ type UseCurrencyBalanceData = { isLoading: boolean isError: boolean | GetBalanceErrorType | null error: boolean | ReadContractErrorType | Error | null + isDuneBalance: boolean } // Handle fetching the balance of both native eth and erc20s @@ -99,7 +100,7 @@ const useCurrencyBalance = ({ const isLoading = isErc20Currency ? erc20BalanceIsLoading : ethBalanceIsLoading - return { value, queryKey, isLoading, isError, error } + return { value, queryKey, isLoading, isError, error, isDuneBalance: false } } else if (chain?.vmType === 'svm') { if (isValidSvmAddress) { return { @@ -114,7 +115,8 @@ const useCurrencyBalance = ({ queryKey: duneBalances.queryKey, isLoading: duneBalances.isLoading, isError: duneBalances.isError, - error: duneBalances.error + error: duneBalances.error, + isDuneBalance: true } } else { return { @@ -122,7 +124,8 @@ const useCurrencyBalance = ({ queryKey: duneBalances.queryKey, isLoading: duneBalances.isLoading, isError: duneBalances.isError, - error: duneBalances.error + error: duneBalances.error, + isDuneBalance: true } } } else { @@ -131,7 +134,8 @@ const useCurrencyBalance = ({ queryKey: duneBalances.queryKey, isLoading: duneBalances.isLoading, isError: duneBalances.isError, - error: duneBalances.error + error: duneBalances.error, + isDuneBalance: false } } }