From 7364408081823910c062b61f680288bc6aac2114 Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 29 Oct 2024 09:35:23 -0400 Subject: [PATCH 01/14] Remove unused useUserAssetsByChain hook --- .../screens/Swap/resources/assets/index.ts | 1 - .../resources/assets/userAssetsByChain.ts | 24 ------------------- 2 files changed, 25 deletions(-) diff --git a/src/__swaps__/screens/Swap/resources/assets/index.ts b/src/__swaps__/screens/Swap/resources/assets/index.ts index ae84cfa4ecc..37014e65e00 100644 --- a/src/__swaps__/screens/Swap/resources/assets/index.ts +++ b/src/__swaps__/screens/Swap/resources/assets/index.ts @@ -1,4 +1,3 @@ export { useUserAssets } from './userAssets'; export type { UserAssetsArgs } from './userAssets'; -export { useUserAssetsByChain } from './userAssetsByChain'; export type { UserAssetsByChainArgs } from './userAssetsByChain'; diff --git a/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts b/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts index 7c73e8a5a09..276355f73f8 100644 --- a/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts +++ b/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts @@ -1,4 +1,3 @@ -import { useQuery } from '@tanstack/react-query'; import { Address } from 'viem'; import { QueryConfigWithSelect, QueryFunctionArgs, QueryFunctionResult, createQueryKey, queryClient } from '@/react-query'; @@ -12,8 +11,6 @@ import { parseUserAssets, userAssetsQueryKey } from './userAssets'; import { RainbowFetchClient } from '@/rainbow-fetch'; import { ADDYS_API_KEY } from 'react-native-dotenv'; -const USER_ASSETS_REFETCH_INTERVAL = 60000; - const addysHttp = new RainbowFetchClient({ baseURL: 'https://addys.p.rainbow.me/v3', headers: { @@ -90,24 +87,3 @@ export async function userAssetsByChainQueryFunction({ } type UserAssetsByChainResult = QueryFunctionResult; - -// /////////////////////////////////////////////// -// Query Hook - -export function useUserAssetsByChain( - { address, chainId, currency }: UserAssetsByChainArgs, - config: QueryConfigWithSelect = {} -) { - return useQuery( - userAssetsByChainQueryKey({ - address, - chainId, - currency, - }), - userAssetsByChainQueryFunction, - { - ...config, - refetchInterval: USER_ASSETS_REFETCH_INTERVAL, - } - ); -} From c82a9d7341dc91f14ccbd199714fc2db6fe3a391 Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 29 Oct 2024 09:36:51 -0400 Subject: [PATCH 02/14] Only trigger retry logic if there are chainIdsWithErrorsInResponse --- .../screens/Swap/resources/assets/userAssets.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/__swaps__/screens/Swap/resources/assets/userAssets.ts b/src/__swaps__/screens/Swap/resources/assets/userAssets.ts index 3feb82a433e..e044c0b4dec 100644 --- a/src/__swaps__/screens/Swap/resources/assets/userAssets.ts +++ b/src/__swaps__/screens/Swap/resources/assets/userAssets.ts @@ -124,12 +124,14 @@ async function userAssetsQueryFunction({ const chainIdsWithErrorsInResponse = res?.data?.meta?.chain_ids_with_errors || []; const assets = res?.data?.payload?.assets || []; if (address) { - userAssetsQueryFunctionRetryByChain({ - address, - chainIds: chainIdsWithErrorsInResponse, - currency, - testnetMode, - }); + if (chainIdsWithErrorsInResponse.length) { + userAssetsQueryFunctionRetryByChain({ + address, + chainIds: chainIdsWithErrorsInResponse, + currency, + testnetMode, + }); + } if (assets.length && chainIdsInResponse.length) { const parsedAssetsDict = await parseUserAssets({ assets, From d55271aa8cdb68895e46402b39e113d5fffa1b87 Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 29 Oct 2024 09:55:22 -0400 Subject: [PATCH 03/14] Remove unnecessary export of userAssetsByChainQueryFunction --- .../screens/Swap/resources/assets/userAssetsByChain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts b/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts index 276355f73f8..3c143a281d5 100644 --- a/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts +++ b/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts @@ -56,7 +56,7 @@ export async function fetchUserAssetsByChain): Promise> { const cache = queryClient.getQueryCache(); From 855abad91c0fe46b016addf606176f6190ea0f09 Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 29 Oct 2024 09:56:24 -0400 Subject: [PATCH 04/14] Update default for empty cache for userAssetsByChainQueryFunction --- .../screens/Swap/resources/assets/userAssetsByChain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts b/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts index 3c143a281d5..d01f17be718 100644 --- a/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts +++ b/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts @@ -61,7 +61,7 @@ async function userAssetsByChainQueryFunction({ }: QueryFunctionArgs): Promise> { const cache = queryClient.getQueryCache(); const cachedUserAssets = (cache.find(userAssetsQueryKey({ address, currency }))?.state?.data || {}) as ParsedAssetsDictByChain; - const cachedDataForChain = cachedUserAssets?.[chainId]; + const cachedDataForChain = cachedUserAssets?.[chainId] || {}; try { const url = `/${chainId}/${address}/assets/?currency=${currency.toLowerCase()}`; const res = await addysHttp.get(url); From 544135b077fd3740ad4e1800f770436d19c34d4e Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 29 Oct 2024 09:59:48 -0400 Subject: [PATCH 05/14] Results from retry can be undefined, so check before using Object.values on the results --- src/__swaps__/screens/Swap/resources/assets/userAssets.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/__swaps__/screens/Swap/resources/assets/userAssets.ts b/src/__swaps__/screens/Swap/resources/assets/userAssets.ts index e044c0b4dec..f583ce2e4f9 100644 --- a/src/__swaps__/screens/Swap/resources/assets/userAssets.ts +++ b/src/__swaps__/screens/Swap/resources/assets/userAssets.ts @@ -188,9 +188,11 @@ async function userAssetsQueryFunctionRetryByChain({ } const parsedRetries = await Promise.all(retries); for (const parsedAssets of parsedRetries) { - const values = Object.values(parsedAssets); - if (values[0]) { - cachedUserAssets[values[0].chainId] = parsedAssets; + if (parsedAssets) { + const values = Object.values(parsedAssets); + if (values[0]) { + cachedUserAssets[values[0].chainId] = parsedAssets; + } } } queryClient.setQueryData(userAssetsQueryKey({ address, currency, testnetMode }), cachedUserAssets); From 2fcfc171ac4b401064f13964d96fb676068e64a4 Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 29 Oct 2024 10:40:11 -0400 Subject: [PATCH 06/14] Fix endpoint we were hitting on retry logic which was causing NO AUTH error --- .../screens/Swap/resources/assets/userAssetsByChain.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts b/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts index d01f17be718..8a3260fa188 100644 --- a/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts +++ b/src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts @@ -63,8 +63,12 @@ async function userAssetsByChainQueryFunction({ const cachedUserAssets = (cache.find(userAssetsQueryKey({ address, currency }))?.state?.data || {}) as ParsedAssetsDictByChain; const cachedDataForChain = cachedUserAssets?.[chainId] || {}; try { - const url = `/${chainId}/${address}/assets/?currency=${currency.toLowerCase()}`; - const res = await addysHttp.get(url); + const url = `/${chainId}/${address}/assets`; + const res = await addysHttp.get(url, { + params: { + currency: currency.toLowerCase(), + }, + }); const chainIdsInResponse = res?.data?.meta?.chain_ids || []; const assets = res?.data?.payload?.assets || []; if (assets.length && chainIdsInResponse.length) { From f0193523bbe6402bf8a646c205154df10cfd5bf6 Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 29 Oct 2024 11:52:07 -0400 Subject: [PATCH 07/14] Fix userAssets query to only be enabled when both address and currency are available --- src/__swaps__/screens/Swap/resources/assets/userAssets.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/__swaps__/screens/Swap/resources/assets/userAssets.ts b/src/__swaps__/screens/Swap/resources/assets/userAssets.ts index f583ce2e4f9..24ac7fd232a 100644 --- a/src/__swaps__/screens/Swap/resources/assets/userAssets.ts +++ b/src/__swaps__/screens/Swap/resources/assets/userAssets.ts @@ -86,9 +86,6 @@ export const userAssetsSetQueryData = ({ address, currency, userAssets, testnetM async function userAssetsQueryFunction({ queryKey: [{ address, currency, testnetMode }], }: QueryFunctionArgs): Promise { - if (!address) { - return {}; - } if (testnetMode) { const { assets, chainIdsInResponse } = await fetchHardhatBalancesByChainId(address); const parsedAssets: Array<{ @@ -240,9 +237,9 @@ export function useUserAssets( config: QueryConfigWithSelect = {} ) { const { connectedToHardhat } = useConnectedToHardhatStore(); - return useQuery(userAssetsQueryKey({ address, currency, testnetMode: connectedToHardhat }), userAssetsQueryFunction, { ...config, + enabled: !!address && !!currency, refetchInterval: USER_ASSETS_REFETCH_INTERVAL, staleTime: process.env.IS_TESTING === 'true' ? 0 : 1000, }); From eb4e8c5848a78adf185f41c761c280babbd80395 Mon Sep 17 00:00:00 2001 From: jinchung Date: Wed, 30 Oct 2024 10:15:00 -0400 Subject: [PATCH 08/14] Remove isSwapsOpen check when keeping user assets store in sync --- src/state/sync/UserAssetsSync.tsx | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/state/sync/UserAssetsSync.tsx b/src/state/sync/UserAssetsSync.tsx index 0eb9dff87be..2f92df12464 100644 --- a/src/state/sync/UserAssetsSync.tsx +++ b/src/state/sync/UserAssetsSync.tsx @@ -9,30 +9,25 @@ import { ChainId } from '@/chains/types'; export const UserAssetsSync = function UserAssetsSync() { const { accountAddress, nativeCurrency: currentCurrency } = useAccountSettings(); - const isSwapsOpen = useSwapsStore(state => state.isSwapsOpen); - useUserAssets( { address: accountAddress, currency: currentCurrency, }, { - enabled: !isSwapsOpen, select: data => selectorFilterByUserChains({ data, selector: selectUserAssetsList, }), onSuccess: data => { - if (!isSwapsOpen) { - userAssetsStore.getState().setUserAssets(data as ParsedSearchAsset[]); + userAssetsStore.getState().setUserAssets(data as ParsedSearchAsset[]); - const inputAsset = userAssetsStore.getState().getHighestValueEth(); - useSwapsStore.setState({ - inputAsset, - selectedOutputChainId: inputAsset?.chainId ?? ChainId.mainnet, - }); - } + const inputAsset = userAssetsStore.getState().getHighestValueEth(); + useSwapsStore.setState({ + inputAsset, + selectedOutputChainId: inputAsset?.chainId ?? ChainId.mainnet, + }); }, } ); From 06c6797dcb1bde9216b392d2283f8182b0b32224 Mon Sep 17 00:00:00 2001 From: jinchung Date: Wed, 30 Oct 2024 10:19:09 -0400 Subject: [PATCH 09/14] Current search cache can sometimes be an empty object instead of a Map and fails when trying to index get function --- src/state/assets/userAssets.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/state/assets/userAssets.ts b/src/state/assets/userAssets.ts index 1ac63f8e1de..c6166640178 100644 --- a/src/state/assets/userAssets.ts +++ b/src/state/assets/userAssets.ts @@ -1,5 +1,6 @@ import { ParsedSearchAsset, UniqueId, UserAssetFilter } from '@/__swaps__/types/assets'; import { Address } from 'viem'; +import { isEmpty } from 'lodash'; import { RainbowError, logger } from '@/logger'; import reduxStore, { AppState } from '@/redux/store'; import { ETH_ADDRESS, supportedNativeCurrencies } from '@/references'; @@ -156,7 +157,8 @@ export const createUserAssetsStore = (address: Address | string) => const queryKey = getSearchQueryKey({ filter, searchQuery: inputSearchQuery }); // Use an external function to get the cache to prevent updates in response to changes in the cache - const cachedData = getCurrentSearchCache()?.get(queryKey); + const currentSearchCache = getCurrentSearchCache(); + const cachedData = !isEmpty(currentSearchCache) ? getCurrentSearchCache()?.get(queryKey) : []; // Check if the search results are already cached if (cachedData) { @@ -375,6 +377,6 @@ export function useUserAssetsStore(selector: (state: UserAssetsState) => T) { return useStore(store, useCallback(selector, [])); } -function getCurrentSearchCache(): Map | undefined { +function getCurrentSearchCache(): Map { return getOrCreateStore().getState().searchCache; } From 08e54681d9e0377d49346fa778b1286acaba783c Mon Sep 17 00:00:00 2001 From: jinchung Date: Thu, 31 Oct 2024 11:08:01 -0400 Subject: [PATCH 10/14] Ignore persistence serialization and deserialization of searchCache in userAssets store --- src/state/assets/userAssets.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/state/assets/userAssets.ts b/src/state/assets/userAssets.ts index c6166640178..480a7b65045 100644 --- a/src/state/assets/userAssets.ts +++ b/src/state/assets/userAssets.ts @@ -1,6 +1,5 @@ import { ParsedSearchAsset, UniqueId, UserAssetFilter } from '@/__swaps__/types/assets'; import { Address } from 'viem'; -import { isEmpty } from 'lodash'; import { RainbowError, logger } from '@/logger'; import reduxStore, { AppState } from '@/redux/store'; import { ETH_ADDRESS, supportedNativeCurrencies } from '@/references'; @@ -64,6 +63,7 @@ function serializeUserAssetsState(state: Partial, version?: num chainBalances: state.chainBalances ? Array.from(state.chainBalances.entries()) : [], idsByChain: state.idsByChain ? Array.from(state.idsByChain.entries()) : [], userAssets: state.userAssets ? Array.from(state.userAssets.entries()) : [], + searchCache: undefined, }; return JSON.stringify({ @@ -114,11 +114,14 @@ function deserializeUserAssetsState(serializedState: string) { logger.error(new RainbowError(`[userAssetsStore]: Failed to convert userAssets from user assets storage`), { error }); } + const searchCache = new Map(); + return { state: { ...state, chainBalances, idsByChain, + searchCache, userAssets: userAssetsData, }, version, @@ -157,8 +160,7 @@ export const createUserAssetsStore = (address: Address | string) => const queryKey = getSearchQueryKey({ filter, searchQuery: inputSearchQuery }); // Use an external function to get the cache to prevent updates in response to changes in the cache - const currentSearchCache = getCurrentSearchCache(); - const cachedData = !isEmpty(currentSearchCache) ? getCurrentSearchCache()?.get(queryKey) : []; + const cachedData = getCurrentSearchCache()?.get(queryKey); // Check if the search results are already cached if (cachedData) { From 0aa676d6480ec30e2bbb0b5cf00f576187463300 Mon Sep 17 00:00:00 2001 From: jinchung Date: Thu, 31 Oct 2024 11:16:57 -0400 Subject: [PATCH 11/14] Only update the user assets store when swaps is not open or if it is open but missing user assets data --- src/state/sync/UserAssetsSync.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/state/sync/UserAssetsSync.tsx b/src/state/sync/UserAssetsSync.tsx index 2f92df12464..b5368fa1cb0 100644 --- a/src/state/sync/UserAssetsSync.tsx +++ b/src/state/sync/UserAssetsSync.tsx @@ -8,6 +8,7 @@ import { ChainId } from '@/chains/types'; export const UserAssetsSync = function UserAssetsSync() { const { accountAddress, nativeCurrency: currentCurrency } = useAccountSettings(); + const isSwapsOpen = useSwapsStore(state => state.isSwapsOpen); useUserAssets( { @@ -21,13 +22,16 @@ export const UserAssetsSync = function UserAssetsSync() { selector: selectUserAssetsList, }), onSuccess: data => { - userAssetsStore.getState().setUserAssets(data as ParsedSearchAsset[]); + const isUserAssetsStoreMissingData = userAssetsStore.getState().getUserAssets()?.length === 0; + if (!isSwapsOpen || isUserAssetsStoreMissingData) { + userAssetsStore.getState().setUserAssets(data as ParsedSearchAsset[]); - const inputAsset = userAssetsStore.getState().getHighestValueEth(); - useSwapsStore.setState({ - inputAsset, - selectedOutputChainId: inputAsset?.chainId ?? ChainId.mainnet, - }); + const inputAsset = userAssetsStore.getState().getHighestValueEth(); + useSwapsStore.setState({ + inputAsset, + selectedOutputChainId: inputAsset?.chainId ?? ChainId.mainnet, + }); + } }, } ); From 095aa518d4bfa4c96e1d0a53c2cacb892f2c93f7 Mon Sep 17 00:00:00 2001 From: jinchung Date: Thu, 31 Oct 2024 11:57:51 -0400 Subject: [PATCH 12/14] Update enabled logic for userAssetsQuery from userAssetsSync --- src/state/sync/UserAssetsSync.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/state/sync/UserAssetsSync.tsx b/src/state/sync/UserAssetsSync.tsx index b5368fa1cb0..697c01f68fd 100644 --- a/src/state/sync/UserAssetsSync.tsx +++ b/src/state/sync/UserAssetsSync.tsx @@ -9,6 +9,8 @@ import { ChainId } from '@/chains/types'; export const UserAssetsSync = function UserAssetsSync() { const { accountAddress, nativeCurrency: currentCurrency } = useAccountSettings(); const isSwapsOpen = useSwapsStore(state => state.isSwapsOpen); + const isUserAssetsStoreMissingData = userAssetsStore.getState().getUserAssets()?.length === 0; + const enabled = (!isSwapsOpen || isUserAssetsStoreMissingData) && !!accountAddress && !!currentCurrency; useUserAssets( { @@ -16,13 +18,13 @@ export const UserAssetsSync = function UserAssetsSync() { currency: currentCurrency, }, { + enabled, select: data => selectorFilterByUserChains({ data, selector: selectUserAssetsList, }), onSuccess: data => { - const isUserAssetsStoreMissingData = userAssetsStore.getState().getUserAssets()?.length === 0; if (!isSwapsOpen || isUserAssetsStoreMissingData) { userAssetsStore.getState().setUserAssets(data as ParsedSearchAsset[]); From 0e8830c635fefa9f418d9c609fb83e84522eab65 Mon Sep 17 00:00:00 2001 From: jinchung Date: Thu, 31 Oct 2024 12:43:07 -0400 Subject: [PATCH 13/14] Use partialize for userAssets store --- src/state/assets/userAssets.ts | 38 ++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/state/assets/userAssets.ts b/src/state/assets/userAssets.ts index 480a7b65045..5c62c49a88b 100644 --- a/src/state/assets/userAssets.ts +++ b/src/state/assets/userAssets.ts @@ -49,21 +49,38 @@ export interface UserAssetsState { setUserAssets: (userAssets: Map | ParsedSearchAsset[]) => void; } +type UserAssetsStateToPersist = Omit< + Partial, + | 'currentAbortController' + | 'inputSearchQuery' + | 'searchCache' + | 'getBalanceSortedChainList' + | 'getChainsWithBalance' + | 'getFilteredUserAssetIds' + | 'getHighestValueEth' + | 'getUserAsset' + | 'getUserAssets' + | 'selectUserAssetIds' + | 'selectUserAssets' + | 'setSearchCache' + | 'setSearchQuery' + | 'setUserAssets' +>; + // NOTE: We are serializing Map as an Array<[UniqueId, ParsedSearchAsset]> -type UserAssetsStateWithTransforms = Omit, 'chainBalances' | 'idsByChain' | 'userAssets'> & { +type UserAssetsStateToPersistWithTransforms = Omit & { chainBalances: Array<[ChainId, number]>; idsByChain: Array<[UserAssetFilter, UniqueId[]]>; userAssets: Array<[UniqueId, ParsedSearchAsset]>; }; -function serializeUserAssetsState(state: Partial, version?: number) { +function serializeUserAssetsState(state: UserAssetsStateToPersist, version?: number) { try { - const transformedStateToPersist: UserAssetsStateWithTransforms = { + const transformedStateToPersist: UserAssetsStateToPersistWithTransforms = { ...state, chainBalances: state.chainBalances ? Array.from(state.chainBalances.entries()) : [], idsByChain: state.idsByChain ? Array.from(state.idsByChain.entries()) : [], userAssets: state.userAssets ? Array.from(state.userAssets.entries()) : [], - searchCache: undefined, }; return JSON.stringify({ @@ -77,7 +94,7 @@ function serializeUserAssetsState(state: Partial, version?: num } function deserializeUserAssetsState(serializedState: string) { - let parsedState: { state: UserAssetsStateWithTransforms; version: number }; + let parsedState: { state: UserAssetsStateToPersistWithTransforms; version: number }; try { parsedState = JSON.parse(serializedState); } catch (error) { @@ -114,14 +131,11 @@ function deserializeUserAssetsState(serializedState: string) { logger.error(new RainbowError(`[userAssetsStore]: Failed to convert userAssets from user assets storage`), { error }); } - const searchCache = new Map(); - return { state: { ...state, chainBalances, idsByChain, - searchCache, userAssets: userAssetsData, }, version, @@ -336,7 +350,13 @@ export const createUserAssetsStore = (address: Address | string) => }), { storageKey: `userAssets_${address}`, - version: 0, + partialize: state => ({ + chainBalances: state.chainBalances, + filter: state.filter, + idsByChain: state.idsByChain, + userAssets: state.userAssets, + }), + version: 1, serializer: serializeUserAssetsState, deserializer: deserializeUserAssetsState, } From 12f5711a3be409465193adc038ee69a6ad48fcac Mon Sep 17 00:00:00 2001 From: jinchung Date: Thu, 31 Oct 2024 13:12:58 -0400 Subject: [PATCH 14/14] Re-add address check in user assets query --- src/__swaps__/screens/Swap/resources/assets/userAssets.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/__swaps__/screens/Swap/resources/assets/userAssets.ts b/src/__swaps__/screens/Swap/resources/assets/userAssets.ts index 24ac7fd232a..5eecd6bf551 100644 --- a/src/__swaps__/screens/Swap/resources/assets/userAssets.ts +++ b/src/__swaps__/screens/Swap/resources/assets/userAssets.ts @@ -86,6 +86,9 @@ export const userAssetsSetQueryData = ({ address, currency, userAssets, testnetM async function userAssetsQueryFunction({ queryKey: [{ address, currency, testnetMode }], }: QueryFunctionArgs): Promise { + if (!address) { + return {}; + } if (testnetMode) { const { assets, chainIdsInResponse } = await fetchHardhatBalancesByChainId(address); const parsedAssets: Array<{