From 415e8004ea36126b8c70ec8518a09db85fae3e4e Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Fri, 26 Jul 2024 12:20:34 -0400 Subject: [PATCH 01/36] fix balance discrepency between bx and app and app and change wallet sheet --- src/components/change-wallet/AddressRow.tsx | 21 +++++------ src/helpers/buildWalletSections.tsx | 36 +++++++++---------- src/hooks/useAssetsBalanceForAddress.ts | 40 +++++++++++++++++++++ src/hooks/useUserAssetsBalance.ts | 18 ++++++++++ src/hooks/useWalletSectionsData.ts | 9 +++++ src/languages/en_US.json | 1 + src/screens/WalletScreen/index.tsx | 8 ++--- 7 files changed, 99 insertions(+), 34 deletions(-) create mode 100644 src/hooks/useAssetsBalanceForAddress.ts create mode 100644 src/hooks/useUserAssetsBalance.ts diff --git a/src/components/change-wallet/AddressRow.tsx b/src/components/change-wallet/AddressRow.tsx index 3b638cbf248..d6cbffa1129 100644 --- a/src/components/change-wallet/AddressRow.tsx +++ b/src/components/change-wallet/AddressRow.tsx @@ -22,10 +22,8 @@ import { EditWalletContextMenuActions } from '@/screens/ChangeWalletSheet'; import { toChecksumAddress } from '@/handlers/web3'; import { IS_IOS, IS_ANDROID } from '@/env'; import { ContextMenu } from '../context-menu'; -import { convertAmountToNativeDisplay } from '@/helpers/utilities'; -import { useSelector } from 'react-redux'; -import { AppState } from '@/redux/store'; import { useForegroundColor } from '@/design-system'; +import { useAssetsBalanceForAddress } from '@/hooks/useAssetsBalanceForAddress'; const maxAccountLabelWidth = deviceUtils.dimensions.width - 88; const NOOP = () => undefined; @@ -121,22 +119,25 @@ interface AddressRowProps { } export default function AddressRow({ contextMenuActions, data, editMode, onPress }: AddressRowProps) { - const nativeCurrency = useSelector((state: AppState) => state.settings.nativeCurrency); const notificationsEnabled = useExperimentalFlag(NOTIFICATIONS); - const { address, balance, color: accountColor, ens, image: accountImage, isSelected, isReadOnly, isLedger, label, walletId } = data; + const { address, color: accountColor, ens, image: accountImage, isSelected, isReadOnly, isLedger, label, walletId } = data; + + const { display, isLoading } = useAssetsBalanceForAddress(address); const { colors, isDarkMode } = useTheme(); const labelQuaternary = useForegroundColor('labelQuaternary'); - const cleanedUpBalance = useMemo(() => { - if (balance) { - return convertAmountToNativeDisplay(balance, nativeCurrency); + const balanceOrNoBalance = useMemo(() => { + if (display) { + return display; + } else if (isLoading) { + return lang.t('wallet.change_wallet.loading'); } else { return lang.t('wallet.change_wallet.no_balance'); } - }, [balance, nativeCurrency]); + }, [isLoading, display]); const cleanedUpLabel = useMemo(() => removeFirstEmojiFromString(label), [label]); @@ -254,7 +255,7 @@ export default function AddressRow({ contextMenuActions, data, editMode, onPress {walletName} - {cleanedUpBalance} + {balanceOrNoBalance} diff --git a/src/helpers/buildWalletSections.tsx b/src/helpers/buildWalletSections.tsx index 2557bf80487..2957acad317 100644 --- a/src/helpers/buildWalletSections.tsx +++ b/src/helpers/buildWalletSections.tsx @@ -1,13 +1,13 @@ import { createSelector } from 'reselect'; import { buildBriefCoinsList, buildBriefUniqueTokenList } from './assets'; -import { add, convertAmountToNativeDisplay } from './utilities'; -import { NativeCurrencyKey, ParsedAddressAsset } from '@/entities'; +import { NativeCurrencyKey } from '@/entities'; import { queryClient } from '@/react-query'; import { positionsQueryKey } from '@/resources/defi/PositionsQuery'; import store from '@/redux/store'; import { PositionExtraData } from '@/components/asset-list/RecyclerAssetList2/core/ViewTypes'; import { getExperimetalFlag, DEFI_POSITIONS } from '@/config/experimental'; import { RainbowPositions } from '@/resources/defi/types'; +import { ParsedSearchAsset } from '@/__swaps__/types/assets'; const CONTENT_PLACEHOLDER = [ { type: 'LOADING_ASSETS', uid: 'loadings-asset-1' }, @@ -39,6 +39,8 @@ const EMPTY_WALLET_CONTENT = [ const ONLY_NFTS_CONTENT = [{ type: 'ETH_CARD', uid: 'eth-card' }]; const sortedAssetsSelector = (state: any) => state.sortedAssets; +const accountBalanceSelector = (state: any) => state.accountBalance; +const isLoadingBalanceSelector = (state: any) => state.isLoadingBalance; const hiddenCoinsSelector = (state: any) => state.hiddenCoins; const isCoinListEditedSelector = (state: any) => state.isCoinListEdited; const isLoadingUserAssetsSelector = (state: any) => state.isLoadingUserAssets; @@ -103,25 +105,17 @@ const withPositionsSection = (isLoadingUserAssets: boolean) => { }; const withBriefBalanceSection = ( - sortedAssets: ParsedAddressAsset[], + sortedAssets: ParsedSearchAsset[], isLoadingUserAssets: boolean, + accountBalance: string | undefined, + isLoadingBalance: boolean, nativeCurrency: NativeCurrencyKey, isCoinListEdited: boolean, pinnedCoins: any, hiddenCoins: any, - collectibles: any, - nftSort: string + collectibles: any ) => { - const { briefAssets, totalBalancesValue } = buildBriefCoinsList(sortedAssets, nativeCurrency, isCoinListEdited, pinnedCoins, hiddenCoins); - - const { accountAddress: address } = store.getState().settings; - const positionsObj: RainbowPositions | undefined = queryClient.getQueryData(positionsQueryKey({ address, currency: nativeCurrency })); - - const positionsTotal = positionsObj?.totals?.total?.amount || '0'; - - const totalBalanceWithPositionsValue = add(totalBalancesValue, positionsTotal); - - const totalValue = convertAmountToNativeDisplay(totalBalanceWithPositionsValue, nativeCurrency); + const { briefAssets } = buildBriefCoinsList(sortedAssets, nativeCurrency, isCoinListEdited, pinnedCoins, hiddenCoins); const hasTokens = briefAssets?.length; const hasNFTs = collectibles?.length; @@ -133,8 +127,8 @@ const withBriefBalanceSection = ( { type: 'PROFILE_STICKY_HEADER', uid: 'assets-profile-header-compact', - value: totalValue, - isLoadingUserAssets, + value: accountBalance, + isLoadingUserAssets: isLoadingBalance, }, { type: 'PROFILE_AVATAR_ROW_SPACE_BEFORE', @@ -162,7 +156,7 @@ const withBriefBalanceSection = ( { type: 'PROFILE_BALANCE_ROW', uid: 'profile-balance', - value: totalValue, + value: accountBalance, }, { type: 'PROFILE_BALANCE_ROW_SPACE_AFTER', @@ -172,13 +166,13 @@ const withBriefBalanceSection = ( { type: 'PROFILE_ACTION_BUTTONS_ROW', uid: 'profile-action-buttons', - value: totalValue, + value: accountBalance, }, hasTokens ? { type: 'PROFILE_ACTION_BUTTONS_ROW_SPACE_AFTER', uid: 'profile-action-buttons-space-after', - value: totalValue, + value: accountBalance, } : { type: 'BIG_EMPTY_WALLET_SPACER', uid: 'big-empty-wallet-spacer-1' }, ]; @@ -226,6 +220,8 @@ const briefBalanceSectionSelector = createSelector( [ sortedAssetsSelector, isLoadingUserAssetsSelector, + accountBalanceSelector, + isLoadingBalanceSelector, nativeCurrencySelector, isCoinListEditedSelector, pinnedCoinsSelector, diff --git a/src/hooks/useAssetsBalanceForAddress.ts b/src/hooks/useAssetsBalanceForAddress.ts new file mode 100644 index 00000000000..58ad6d64f61 --- /dev/null +++ b/src/hooks/useAssetsBalanceForAddress.ts @@ -0,0 +1,40 @@ +import { useCallback } from 'react'; +import { Address } from 'viem'; + +import { selectUserAssetsBalance, selectorFilterByUserChains } from '@/__swaps__/screens/Swap/resources/_selectors/assets'; +import { useUserAssets } from '@/__swaps__/screens/Swap/resources/assets'; +import { EthereumAddress, ParsedAddressAsset } from '@/entities'; +import useAccountSettings from './useAccountSettings'; +import { convertAmountToNativeDisplay } from '@/helpers/utilities'; +import useCoinListEditOptions from './useCoinListEditOptions'; + +export function useAssetsBalanceForAddress(address: EthereumAddress) { + const { nativeCurrency } = useAccountSettings(); + const { hiddenCoinsObj: hidden } = useCoinListEditOptions(); + const isHidden = useCallback( + (asset: ParsedAddressAsset) => { + return !!hidden[asset.address]; + }, + [hidden] + ); + + const { data: totalAssetsBalance, isLoading } = useUserAssets( + { + address: address as Address, + currency: nativeCurrency, + }, + { + select: data => + selectorFilterByUserChains({ + data, + selector: data => selectUserAssetsBalance(data, asset => isHidden(asset as unknown as ParsedAddressAsset)), + }), + } + ); + + return { + amount: totalAssetsBalance, + display: totalAssetsBalance ? convertAmountToNativeDisplay(totalAssetsBalance, nativeCurrency) : undefined, + isLoading, + }; +} diff --git a/src/hooks/useUserAssetsBalance.ts b/src/hooks/useUserAssetsBalance.ts new file mode 100644 index 00000000000..e7b581ea089 --- /dev/null +++ b/src/hooks/useUserAssetsBalance.ts @@ -0,0 +1,18 @@ +import { useMemo } from 'react'; +import { add, convertAmountToNativeDisplay } from '@/helpers/utilities'; +import useAccountSettings from './useAccountSettings'; +import { userAssetsStore } from '@/state/assets/userAssets'; + +export function useUserAssetsBalance() { + const { nativeCurrency } = useAccountSettings(); + const getUserAssets = userAssetsStore(state => state.getUserAssets); + + const amount = useMemo(() => { + return getUserAssets().reduce((prev, curr) => add(prev, curr.balance.amount), '0'); + }, [getUserAssets]); + + return { + amount, + display: convertAmountToNativeDisplay(amount, nativeCurrency), + }; +} diff --git a/src/hooks/useWalletSectionsData.ts b/src/hooks/useWalletSectionsData.ts index 9b2b60c9c4c..885b48c6bcc 100644 --- a/src/hooks/useWalletSectionsData.ts +++ b/src/hooks/useWalletSectionsData.ts @@ -11,6 +11,7 @@ import { buildBriefWalletSectionsSelector } from '@/helpers/buildWalletSections' import { useSortedUserAssets } from '@/resources/assets/useSortedUserAssets'; import { useLegacyNFTs } from '@/resources/nfts'; import useNftSort from './useNFTsSortBy'; +import { useAssetsBalanceForAddress } from './useAssetsBalanceForAddress'; export default function useWalletSectionsData({ type, @@ -27,6 +28,9 @@ export default function useWalletSectionsData({ } = useLegacyNFTs({ address: accountAddress, }); + + const { display: accountBalance, isLoading: isLoadingBalance } = useAssetsBalanceForAddress(accountAddress); + const { showcaseTokens } = useShowcaseTokens(); const { hiddenTokens } = useHiddenTokens(); const { isReadOnlyWallet } = useWallets(); @@ -48,6 +52,8 @@ export default function useWalletSectionsData({ pinnedCoins, sendableUniqueTokens, sortedAssets, + accountBalance, + isLoadingBalance, // @ts-expect-error ts-migrate(2698) FIXME: Spread types may only be created from object types... Remove this comment to see the full error message ...isWalletEthZero, hiddenTokens, @@ -65,6 +71,7 @@ export default function useWalletSectionsData({ hasNFTs, isEmpty, isLoadingUserAssets, + isLoadingBalance, isWalletEthZero, briefSectionsData, }; @@ -78,6 +85,8 @@ export default function useWalletSectionsData({ pinnedCoins, sendableUniqueTokens, sortedAssets, + accountBalance, + isLoadingBalance, isWalletEthZero, hiddenTokens, isReadOnlyWallet, diff --git a/src/languages/en_US.json b/src/languages/en_US.json index 7e3cec0b12e..5ed0596b315 100644 --- a/src/languages/en_US.json +++ b/src/languages/en_US.json @@ -2482,6 +2482,7 @@ "buy": "Buy", "change_wallet": { "no_balance": "No Balance", + "loading": "Loading balance", "balance_eth": "%{balanceEth} ETH", "watching": "Watching", "ledger": "Ledger" diff --git a/src/screens/WalletScreen/index.tsx b/src/screens/WalletScreen/index.tsx index c4c4a647676..02ea352ec5c 100644 --- a/src/screens/WalletScreen/index.tsx +++ b/src/screens/WalletScreen/index.tsx @@ -74,7 +74,7 @@ const WalletScreen: React.FC = ({ navigation, route }) => { }, [currentNetwork, revertToMainnet]); const walletReady = useSelector(({ appState: { walletReady } }: AppState) => walletReady); - const { isWalletEthZero, isLoadingUserAssets, briefSectionsData: walletBriefSectionsData } = useWalletSectionsData(); + const { isWalletEthZero, isLoadingUserAssets, isLoadingBalance, briefSectionsData: walletBriefSectionsData } = useWalletSectionsData(); useEffect(() => { // This is the fix for Android wallet creation problem. @@ -86,7 +86,7 @@ const WalletScreen: React.FC = ({ navigation, route }) => { if (isWelcomeScreen) { removeFirst(); } - }, [dangerouslyGetState, removeFirst]); + }, [dangerouslyGetParent, dangerouslyGetState, removeFirst]); useEffect(() => { const initializeAndSetParams = async () => { @@ -132,8 +132,8 @@ const WalletScreen: React.FC = ({ navigation, route }) => { {/* @ts-expect-error JavaScript component */} Date: Fri, 26 Jul 2024 12:23:53 -0400 Subject: [PATCH 02/36] Update src/helpers/buildWalletSections.tsx --- src/helpers/buildWalletSections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/buildWalletSections.tsx b/src/helpers/buildWalletSections.tsx index 2957acad317..9ce9d4a3fba 100644 --- a/src/helpers/buildWalletSections.tsx +++ b/src/helpers/buildWalletSections.tsx @@ -105,7 +105,7 @@ const withPositionsSection = (isLoadingUserAssets: boolean) => { }; const withBriefBalanceSection = ( - sortedAssets: ParsedSearchAsset[], + sortedAssets: ParsedAddressAsset[], isLoadingUserAssets: boolean, accountBalance: string | undefined, isLoadingBalance: boolean, From 4ff91ef5f053830459173e632db4bfc4a3fcfe30 Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Fri, 26 Jul 2024 12:24:28 -0400 Subject: [PATCH 03/36] fix missing import from commit --- src/helpers/buildWalletSections.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/helpers/buildWalletSections.tsx b/src/helpers/buildWalletSections.tsx index 9ce9d4a3fba..fdcc55236a5 100644 --- a/src/helpers/buildWalletSections.tsx +++ b/src/helpers/buildWalletSections.tsx @@ -1,13 +1,12 @@ import { createSelector } from 'reselect'; import { buildBriefCoinsList, buildBriefUniqueTokenList } from './assets'; -import { NativeCurrencyKey } from '@/entities'; +import { NativeCurrencyKey, ParsedAddressAsset } from '@/entities'; import { queryClient } from '@/react-query'; import { positionsQueryKey } from '@/resources/defi/PositionsQuery'; import store from '@/redux/store'; import { PositionExtraData } from '@/components/asset-list/RecyclerAssetList2/core/ViewTypes'; import { getExperimetalFlag, DEFI_POSITIONS } from '@/config/experimental'; import { RainbowPositions } from '@/resources/defi/types'; -import { ParsedSearchAsset } from '@/__swaps__/types/assets'; const CONTENT_PLACEHOLDER = [ { type: 'LOADING_ASSETS', uid: 'loadings-asset-1' }, From d010309d1895483c0fe1b467ea9d6aa83b50ce15 Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Fri, 26 Jul 2024 12:35:41 -0400 Subject: [PATCH 04/36] also fix send sheet balance discrepancy --- src/components/contacts/ContactRow.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/contacts/ContactRow.js b/src/components/contacts/ContactRow.js index f1a22d53236..a448141d020 100644 --- a/src/components/contacts/ContactRow.js +++ b/src/components/contacts/ContactRow.js @@ -17,6 +17,7 @@ import { margin } from '@/styles'; import { addressHashedColorIndex, addressHashedEmoji } from '@/utils/profileUtils'; import * as i18n from '@/languages'; import { convertAmountToNativeDisplay } from '@/helpers/utilities'; +import { useAssetsBalanceForAddress } from '@/hooks/useAssetsBalanceForAddress'; const ContactAddress = styled(TruncatedAddress).attrs(({ theme: { colors }, lite }) => ({ align: 'left', @@ -58,17 +59,20 @@ const ContactRow = ({ address, color, nickname, symmetricalMargins, ...props }, const profilesEnabled = useExperimentalFlag(PROFILES); const { width: deviceWidth } = useDimensions(); const { onAddOrUpdateContacts } = useContacts(); - const { nativeCurrency } = useAccountSettings(); const { colors } = useTheme(); - const { accountType, balance, ens, image, label, network, onPress, showcaseItem, testID } = props; + const { accountType, ens, image, label, network, onPress, showcaseItem, testID } = props; + + const { display, isLoading } = useAssetsBalanceForAddress(address); const cleanedUpBalance = useMemo(() => { - if (balance) { - return convertAmountToNativeDisplay(balance, nativeCurrency); + if (display) { + return display; + } else if (isLoading) { + return i18n.t(i18n.l.wallet.change_wallet.loading); } else { return i18n.t(i18n.l.wallet.change_wallet.no_balance); } - }, [balance, nativeCurrency]); + }, [display, isLoading]); // show avatar for contact rows that are accounts, not contacts const avatar = accountType !== 'contacts' ? returnStringFirstEmoji(label) || profileUtils.addressHashedEmoji(address) : null; From 50df200eb2bbe690cf25bf584a0bc29c6a5fc179 Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Wed, 31 Jul 2024 13:40:32 -0400 Subject: [PATCH 05/36] fix swap user assets not refetching on pending txn resolution and PTR --- .../screens/Swap/providers/swap-provider.tsx | 2 +- src/graphql/config.js | 2 +- src/hooks/useRefreshAccountData.ts | 45 ++++++++++++------- src/hooks/useWatchPendingTxs.ts | 43 +++++++++++------- 4 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/__swaps__/screens/Swap/providers/swap-provider.tsx b/src/__swaps__/screens/Swap/providers/swap-provider.tsx index e1b345727b4..7fe0c399e89 100644 --- a/src/__swaps__/screens/Swap/providers/swap-provider.tsx +++ b/src/__swaps__/screens/Swap/providers/swap-provider.tsx @@ -265,7 +265,7 @@ export const SwapProvider = ({ children }: SwapProviderProps) => { } queryClient.invalidateQueries([ - // old user assets invalidation (will cause a re-fetch) + // old user assets invalidation { queryKey: userAssetsQueryKey({ address: parameters.quote.from, diff --git a/src/graphql/config.js b/src/graphql/config.js index 8b809049e5b..690a437f009 100644 --- a/src/graphql/config.js +++ b/src/graphql/config.js @@ -4,7 +4,7 @@ exports.config = { document: './queries/ens.graphql', schema: { method: 'POST', - url: 'https://api.thegraph.com/subgraphs/name/ensdomains/ens', + url: 'https://gateway-arbitrum.network.thegraph.com/api/35a75cae48aab2b771d1e53543a37a0f/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH', }, }, metadata: { diff --git a/src/hooks/useRefreshAccountData.ts b/src/hooks/useRefreshAccountData.ts index 4de563b7108..81c6b255254 100644 --- a/src/hooks/useRefreshAccountData.ts +++ b/src/hooks/useRefreshAccountData.ts @@ -10,8 +10,10 @@ import { PROFILES, useExperimentalFlag } from '@/config'; import logger from '@/utils/logger'; import { queryClient } from '@/react-query'; import { userAssetsQueryKey } from '@/resources/assets/UserAssetsQuery'; +import { userAssetsQueryKey as swapsUserAssetsQueryKey } from '@/__swaps__/screens/Swap/resources/assets/userAssets'; import { nftsQueryKey } from '@/resources/nfts'; import { positionsQueryKey } from '@/resources/defi/PositionsQuery'; +import { Address } from 'viem'; export default function useRefreshAccountData() { const dispatch = useDispatch(); @@ -22,22 +24,33 @@ export default function useRefreshAccountData() { const fetchAccountData = useCallback(async () => { const connectedToHardhat = getIsHardhatConnected(); - queryClient.invalidateQueries({ - queryKey: nftsQueryKey({ address: accountAddress }), - }); - queryClient.invalidateQueries({ - queryKey: positionsQueryKey({ - address: accountAddress, - currency: nativeCurrency, - }), - }); - queryClient.invalidateQueries({ - queryKey: userAssetsQueryKey({ - address: accountAddress, - currency: nativeCurrency, - connectedToHardhat, - }), - }); + queryClient.invalidateQueries([ + { + queryKey: nftsQueryKey({ address: accountAddress }), + }, + { + queryKey: positionsQueryKey({ + address: accountAddress, + currency: nativeCurrency, + }), + }, + // old user assets invalidation + { + queryKey: userAssetsQueryKey({ + address: accountAddress, + currency: nativeCurrency, + connectedToHardhat, + }), + }, + // new swaps user assets invalidations + { + queryKey: swapsUserAssetsQueryKey({ + address: accountAddress as Address, + currency: nativeCurrency, + testnetMode: !!connectedToHardhat, + }), + }, + ]); try { const getWalletNames = dispatch(fetchWalletNames()); diff --git a/src/hooks/useWatchPendingTxs.ts b/src/hooks/useWatchPendingTxs.ts index 777a45aac9b..ce012e60f30 100644 --- a/src/hooks/useWatchPendingTxs.ts +++ b/src/hooks/useWatchPendingTxs.ts @@ -1,21 +1,21 @@ import { useCallback, useMemo } from 'react'; import useAccountSettings from './useAccountSettings'; import { RainbowTransaction, MinedTransaction } from '@/entities/transactions/transaction'; -import { fetchUserAssets } from '@/resources/assets/UserAssetsQuery'; +import { fetchUserAssets, userAssetsQueryKey } from '@/resources/assets/UserAssetsQuery'; +import { userAssetsQueryKey as swapsUserAssetsQueryKey } from '@/__swaps__/screens/Swap/resources/assets/userAssets'; import { transactionFetchQuery } from '@/resources/transactions/transaction'; import { RainbowError, logger } from '@/logger'; import { Network } from '@/networks/types'; -import { getProviderForNetwork } from '@/handlers/web3'; +import { getIsHardhatConnected, getProviderForNetwork } from '@/handlers/web3'; import { consolidatedTransactionsQueryKey } from '@/resources/transactions/consolidatedTransactions'; import { RainbowNetworks } from '@/networks'; import { queryClient } from '@/react-query/queryClient'; import { getTransactionFlashbotStatus } from '@/handlers/transactions'; import { usePendingTransactionsStore } from '@/state/pendingTransactions'; import { useNonceStore } from '@/state/nonces'; +import { Address } from 'viem'; export const useWatchPendingTransactions = ({ address }: { address: string }) => { - //const { swapRefreshAssets } = useSwapRefreshAssets(); - const { storePendingTransactions, setPendingTransactions } = usePendingTransactionsStore(state => ({ storePendingTransactions: state.pendingTransactions, setPendingTransactions: state.setPendingTransactions, @@ -28,20 +28,29 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => const { nativeCurrency, accountAddress } = useAccountSettings(); const refreshAssets = useCallback( - (tx: RainbowTransaction) => { - if (tx.type === 'swap') { - // update swap assets - //swapRefreshAssets(tx.nonce); - } else { - // fetch assets again - fetchUserAssets({ - address: accountAddress, - currency: nativeCurrency, - connectedToHardhat: false, - }); - } + (_: RainbowTransaction) => { + // NOTE: We have two user assets stores right now, so let's invalidate both queries and trigger a refetch + const connectedToHardhat = getIsHardhatConnected(); + queryClient.invalidateQueries([ + // old user assets invalidation + { + queryKey: userAssetsQueryKey({ + address, + currency: nativeCurrency, + connectedToHardhat, + }), + }, + // new swaps user assets invalidations + { + queryKey: swapsUserAssetsQueryKey({ + address: address as Address, + currency: nativeCurrency, + testnetMode: !!connectedToHardhat, + }), + }, + ]); }, - [accountAddress, nativeCurrency] + [address, nativeCurrency] ); const processFlashbotsTransaction = useCallback(async (tx: RainbowTransaction): Promise => { From cf6a796822e8b76002571b94e789e3192cfde7ca Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Wed, 31 Jul 2024 13:46:11 -0400 Subject: [PATCH 06/36] . --- src/graphql/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphql/config.js b/src/graphql/config.js index 690a437f009..8b809049e5b 100644 --- a/src/graphql/config.js +++ b/src/graphql/config.js @@ -4,7 +4,7 @@ exports.config = { document: './queries/ens.graphql', schema: { method: 'POST', - url: 'https://gateway-arbitrum.network.thegraph.com/api/35a75cae48aab2b771d1e53543a37a0f/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH', + url: 'https://api.thegraph.com/subgraphs/name/ensdomains/ens', }, }, metadata: { From 2605a2176106c63b2731b0a122df5338cfbfaa19 Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Fri, 2 Aug 2024 21:04:29 -0400 Subject: [PATCH 07/36] update en_US key --- src/components/change-wallet/AddressRow.tsx | 2 +- src/components/contacts/ContactRow.js | 2 +- src/languages/en_US.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/change-wallet/AddressRow.tsx b/src/components/change-wallet/AddressRow.tsx index d6cbffa1129..05d43557987 100644 --- a/src/components/change-wallet/AddressRow.tsx +++ b/src/components/change-wallet/AddressRow.tsx @@ -133,7 +133,7 @@ export default function AddressRow({ contextMenuActions, data, editMode, onPress if (display) { return display; } else if (isLoading) { - return lang.t('wallet.change_wallet.loading'); + return lang.t('wallet.change_wallet.loading_balance'); } else { return lang.t('wallet.change_wallet.no_balance'); } diff --git a/src/components/contacts/ContactRow.js b/src/components/contacts/ContactRow.js index a448141d020..fb7bbedb4a2 100644 --- a/src/components/contacts/ContactRow.js +++ b/src/components/contacts/ContactRow.js @@ -68,7 +68,7 @@ const ContactRow = ({ address, color, nickname, symmetricalMargins, ...props }, if (display) { return display; } else if (isLoading) { - return i18n.t(i18n.l.wallet.change_wallet.loading); + return i18n.t(i18n.l.wallet.change_wallet.loading_balance); } else { return i18n.t(i18n.l.wallet.change_wallet.no_balance); } diff --git a/src/languages/en_US.json b/src/languages/en_US.json index 5ed0596b315..312075b84c6 100644 --- a/src/languages/en_US.json +++ b/src/languages/en_US.json @@ -2482,7 +2482,7 @@ "buy": "Buy", "change_wallet": { "no_balance": "No Balance", - "loading": "Loading balance", + "loading_balance": "Loading balance", "balance_eth": "%{balanceEth} ETH", "watching": "Watching", "ledger": "Ledger" From eb8bbe257e41ec948eec95eecea599479d91369d Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Mon, 5 Aug 2024 12:10:58 -0400 Subject: [PATCH 08/36] rmeove unused hook and bake it into the user assets store --- src/hooks/useUserAssetsBalance.ts | 18 ------------------ src/state/assets/userAssets.ts | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 18 deletions(-) delete mode 100644 src/hooks/useUserAssetsBalance.ts diff --git a/src/hooks/useUserAssetsBalance.ts b/src/hooks/useUserAssetsBalance.ts deleted file mode 100644 index e7b581ea089..00000000000 --- a/src/hooks/useUserAssetsBalance.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useMemo } from 'react'; -import { add, convertAmountToNativeDisplay } from '@/helpers/utilities'; -import useAccountSettings from './useAccountSettings'; -import { userAssetsStore } from '@/state/assets/userAssets'; - -export function useUserAssetsBalance() { - const { nativeCurrency } = useAccountSettings(); - const getUserAssets = userAssetsStore(state => state.getUserAssets); - - const amount = useMemo(() => { - return getUserAssets().reduce((prev, curr) => add(prev, curr.balance.amount), '0'); - }, [getUserAssets]); - - return { - amount, - display: convertAmountToNativeDisplay(amount, nativeCurrency), - }; -} diff --git a/src/state/assets/userAssets.ts b/src/state/assets/userAssets.ts index 4a9e00df6db..65aa14aabd6 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 { ChainId } from '@/__swaps__/types/chains'; +import { add, convertAmountToNativeDisplayWorklet } from '@/__swaps__/utils/numbers'; import { RainbowError, logger } from '@/logger'; import store from '@/redux/store'; import { SUPPORTED_CHAIN_IDS, supportedNativeCurrencies } from '@/references'; @@ -26,6 +27,12 @@ export interface UserAssetsState { associatedWalletAddress: Address | undefined; chainBalances: Map; currentAbortController: AbortController; + totalAssetNativeBalance: + | { + amount: string; + display: string; + } + | undefined; filter: UserAssetFilter; idsByChain: Map; inputSearchQuery: string; @@ -37,6 +44,10 @@ export interface UserAssetsState { getHighestValueAsset: () => ParsedSearchAsset | null; getUserAsset: (uniqueId: UniqueId) => ParsedSearchAsset | null; getUserAssets: () => ParsedSearchAsset[]; + getTotalAssetNativeBalance: () => { + amount: string; + display: string; + }; selectUserAssetIds: (selector: (asset: ParsedSearchAsset) => boolean, filter?: UserAssetFilter) => Generator; selectUserAssets: (selector: (asset: ParsedSearchAsset) => boolean) => Generator<[UniqueId, ParsedSearchAsset], void, unknown>; setSearchCache: (queryKey: string, filteredIds: UniqueId[]) => void; @@ -129,6 +140,7 @@ export const userAssetsStore = createRainbowStore( inputSearchQuery: '', searchCache: new Map(), userAssets: new Map(), + totalAssetNativeBalance: undefined, getBalanceSortedChainList: () => { const chainBalances = [...get().chainBalances.entries()]; @@ -185,6 +197,17 @@ export const userAssetsStore = createRainbowStore( getUserAssets: () => Array.from(get().userAssets.values()) || [], + getTotalAssetNativeBalance: () => { + const { getUserAssets } = get(); + + const amount = getUserAssets().reduce((prev, curr) => add(prev, curr.native.balance.amount), '0'); + + return { + amount, + display: convertAmountToNativeDisplayWorklet(amount, store.getState().settings.nativeCurrency), + }; + }, + selectUserAssetIds: function* (selector: (asset: ParsedSearchAsset) => boolean, filter?: UserAssetFilter) { const { currentAbortController, idsByChain, userAssets } = get(); From bc4c6e8c95f76ab5c681b200ce678bbc2379e23e Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Mon, 5 Aug 2024 16:48:15 -0400 Subject: [PATCH 09/36] good lord --- .../control-panel/ControlPanel.tsx | 4 +- src/components/change-wallet/AddressRow.tsx | 13 +--- src/components/contacts/ContactRow.js | 16 ++-- src/helpers/buildWalletSections.tsx | 3 +- src/hooks/useAccountBalance.ts | 30 ++++++++ src/hooks/useRefreshAccountData.ts | 45 ++++------- src/hooks/useWalletBalances.ts | 77 ++++++++++++++++++- src/hooks/useWalletSectionsData.ts | 18 +++-- src/hooks/useWalletsWithBalancesAndNames.ts | 6 +- src/resources/summary/summary.ts | 2 +- 10 files changed, 148 insertions(+), 66 deletions(-) create mode 100644 src/hooks/useAccountBalance.ts diff --git a/src/components/DappBrowser/control-panel/ControlPanel.tsx b/src/components/DappBrowser/control-panel/ControlPanel.tsx index 4498a2bb4d8..eedeb85f069 100644 --- a/src/components/DappBrowser/control-panel/ControlPanel.tsx +++ b/src/components/DappBrowser/control-panel/ControlPanel.tsx @@ -158,7 +158,7 @@ export const ControlPanel = () => { wallet.type === WalletTypes.readOnly ? i18n.t(i18n.l.wallet.change_wallet.watching) : account.balance - ? convertAmountToNativeDisplay(account.balance, nativeCurrency) + ? account.balance : i18n.t(i18n.l.wallet.change_wallet.no_balance), uniqueId: account.address, color: colors.avatarBackgrounds[account.color], @@ -472,7 +472,7 @@ const HomePanel = ({ }, screen: Routes.MAIN_EXCHANGE_SCREEN, }); - }, [runWalletChecksBeforeSwapOrBridge, selectedWallet?.uniqueId]); + }, [navigate, runWalletChecksBeforeSwapOrBridge, selectedWallet?.uniqueId, swapsV2Enabled]); const handleOnPressBridge = useCallback(async () => { const valid = await runWalletChecksBeforeSwapOrBridge(); diff --git a/src/components/change-wallet/AddressRow.tsx b/src/components/change-wallet/AddressRow.tsx index 05d43557987..fab128e11e2 100644 --- a/src/components/change-wallet/AddressRow.tsx +++ b/src/components/change-wallet/AddressRow.tsx @@ -23,7 +23,6 @@ import { toChecksumAddress } from '@/handlers/web3'; import { IS_IOS, IS_ANDROID } from '@/env'; import { ContextMenu } from '../context-menu'; import { useForegroundColor } from '@/design-system'; -import { useAssetsBalanceForAddress } from '@/hooks/useAssetsBalanceForAddress'; const maxAccountLabelWidth = deviceUtils.dimensions.width - 88; const NOOP = () => undefined; @@ -121,23 +120,19 @@ interface AddressRowProps { export default function AddressRow({ contextMenuActions, data, editMode, onPress }: AddressRowProps) { const notificationsEnabled = useExperimentalFlag(NOTIFICATIONS); - const { address, color: accountColor, ens, image: accountImage, isSelected, isReadOnly, isLedger, label, walletId } = data; - - const { display, isLoading } = useAssetsBalanceForAddress(address); + const { address, balance, color: accountColor, ens, image: accountImage, isSelected, isReadOnly, isLedger, label, walletId } = data; const { colors, isDarkMode } = useTheme(); const labelQuaternary = useForegroundColor('labelQuaternary'); const balanceOrNoBalance = useMemo(() => { - if (display) { - return display; - } else if (isLoading) { - return lang.t('wallet.change_wallet.loading_balance'); + if (balance) { + return balance; } else { return lang.t('wallet.change_wallet.no_balance'); } - }, [isLoading, display]); + }, [balance]); const cleanedUpLabel = useMemo(() => removeFirstEmojiFromString(label), [label]); diff --git a/src/components/contacts/ContactRow.js b/src/components/contacts/ContactRow.js index fb7bbedb4a2..11b67df1d40 100644 --- a/src/components/contacts/ContactRow.js +++ b/src/components/contacts/ContactRow.js @@ -11,13 +11,11 @@ import useExperimentalFlag, { PROFILES } from '@/config/experimentalHooks'; import { fetchReverseRecord } from '@/handlers/ens'; import { ENS_DOMAIN } from '@/helpers/ens'; import { isENSAddressFormat, isValidDomainFormat } from '@/helpers/validators'; -import { useAccountSettings, useContacts, useDimensions, useENSAvatar } from '@/hooks'; +import { useContacts, useDimensions, useENSAvatar } from '@/hooks'; import styled from '@/styled-thing'; import { margin } from '@/styles'; import { addressHashedColorIndex, addressHashedEmoji } from '@/utils/profileUtils'; import * as i18n from '@/languages'; -import { convertAmountToNativeDisplay } from '@/helpers/utilities'; -import { useAssetsBalanceForAddress } from '@/hooks/useAssetsBalanceForAddress'; const ContactAddress = styled(TruncatedAddress).attrs(({ theme: { colors }, lite }) => ({ align: 'left', @@ -60,19 +58,15 @@ const ContactRow = ({ address, color, nickname, symmetricalMargins, ...props }, const { width: deviceWidth } = useDimensions(); const { onAddOrUpdateContacts } = useContacts(); const { colors } = useTheme(); - const { accountType, ens, image, label, network, onPress, showcaseItem, testID } = props; - - const { display, isLoading } = useAssetsBalanceForAddress(address); + const { accountType, balance, ens, image, label, network, onPress, showcaseItem, testID } = props; const cleanedUpBalance = useMemo(() => { - if (display) { - return display; - } else if (isLoading) { - return i18n.t(i18n.l.wallet.change_wallet.loading_balance); + if (balance) { + return balance; } else { return i18n.t(i18n.l.wallet.change_wallet.no_balance); } - }, [display, isLoading]); + }, [balance]); // show avatar for contact rows that are accounts, not contacts const avatar = accountType !== 'contacts' ? returnStringFirstEmoji(label) || profileUtils.addressHashedEmoji(address) : null; diff --git a/src/helpers/buildWalletSections.tsx b/src/helpers/buildWalletSections.tsx index fdcc55236a5..f18aff6e5a0 100644 --- a/src/helpers/buildWalletSections.tsx +++ b/src/helpers/buildWalletSections.tsx @@ -7,6 +7,7 @@ import store from '@/redux/store'; import { PositionExtraData } from '@/components/asset-list/RecyclerAssetList2/core/ViewTypes'; import { getExperimetalFlag, DEFI_POSITIONS } from '@/config/experimental'; import { RainbowPositions } from '@/resources/defi/types'; +import { add, convertAmountToNativeDisplay } from './utilities'; const CONTENT_PLACEHOLDER = [ { type: 'LOADING_ASSETS', uid: 'loadings-asset-1' }, @@ -106,7 +107,7 @@ const withPositionsSection = (isLoadingUserAssets: boolean) => { const withBriefBalanceSection = ( sortedAssets: ParsedAddressAsset[], isLoadingUserAssets: boolean, - accountBalance: string | undefined, + accountBalance: number | undefined, isLoadingBalance: boolean, nativeCurrency: NativeCurrencyKey, isCoinListEdited: boolean, diff --git a/src/hooks/useAccountBalance.ts b/src/hooks/useAccountBalance.ts new file mode 100644 index 00000000000..71257341cf8 --- /dev/null +++ b/src/hooks/useAccountBalance.ts @@ -0,0 +1,30 @@ +import { Address } from 'viem'; +import useAccountSettings from './useAccountSettings'; +import { useAddysSummary } from '@/resources/summary/summary'; +import { usePositions } from '@/resources/defi/PositionsQuery'; +import { add, convertAmountToNativeDisplay } from '@/helpers/utilities'; + +const useAccountBalance = (address: Address) => { + const { nativeCurrency } = useAccountSettings(); + + const lowerCaseAddress = address.toLowerCase() as Address; + + const { data: summaryData, isLoading: isSummaryLoading } = useAddysSummary({ addresses: [lowerCaseAddress], currency: nativeCurrency }); + const { data: positionsData, isLoading: isPositionsLoading } = usePositions({ address: lowerCaseAddress, currency: nativeCurrency }); + + const assetBalance = summaryData?.data?.addresses?.[lowerCaseAddress]?.summary?.asset_value || 0; + const positionsBalance = positionsData?.totals?.total?.amount || '0'; + const totalBalance = add(assetBalance, positionsBalance); + + return { + assetBalanceAmount: assetBalance, + assetBalanceDisplay: convertAmountToNativeDisplay(assetBalance, nativeCurrency), + positionsBalanceAmount: positionsBalance, + positionsBalanceDisplay: convertAmountToNativeDisplay(positionsBalance, nativeCurrency), + totalBalanceAmount: totalBalance, + totalBalanceDisplay: convertAmountToNativeDisplay(totalBalance, nativeCurrency), + isLoading: isSummaryLoading || isPositionsLoading, + }; +}; + +export default useAccountBalance; diff --git a/src/hooks/useRefreshAccountData.ts b/src/hooks/useRefreshAccountData.ts index 81c6b255254..df30a1a18e6 100644 --- a/src/hooks/useRefreshAccountData.ts +++ b/src/hooks/useRefreshAccountData.ts @@ -1,6 +1,6 @@ import { captureException } from '@sentry/react-native'; import delay from 'delay'; -import { useCallback, useState } from 'react'; +import { useCallback, useMemo, useState } from 'react'; import { useDispatch } from 'react-redux'; import { getIsHardhatConnected } from '@/handlers/web3'; import { walletConnectLoadState } from '../redux/walletconnect'; @@ -14,6 +14,8 @@ import { userAssetsQueryKey as swapsUserAssetsQueryKey } from '@/__swaps__/scree import { nftsQueryKey } from '@/resources/nfts'; import { positionsQueryKey } from '@/resources/defi/PositionsQuery'; import { Address } from 'viem'; +import { addysSummaryQueryKey } from '@/resources/summary/summary'; +import useWallets from './useWallets'; export default function useRefreshAccountData() { const dispatch = useDispatch(); @@ -21,36 +23,23 @@ export default function useRefreshAccountData() { const [isRefreshing, setIsRefreshing] = useState(false); const profilesEnabled = useExperimentalFlag(PROFILES); + const { wallets } = useWallets(); + + const allAddresses = useMemo( + () => Object.values(wallets || {}).flatMap(wallet => wallet.addresses.map(account => account.address as Address)), + [wallets] + ); + const fetchAccountData = useCallback(async () => { const connectedToHardhat = getIsHardhatConnected(); - queryClient.invalidateQueries([ - { - queryKey: nftsQueryKey({ address: accountAddress }), - }, - { - queryKey: positionsQueryKey({ - address: accountAddress, - currency: nativeCurrency, - }), - }, - // old user assets invalidation - { - queryKey: userAssetsQueryKey({ - address: accountAddress, - currency: nativeCurrency, - connectedToHardhat, - }), - }, - // new swaps user assets invalidations - { - queryKey: swapsUserAssetsQueryKey({ - address: accountAddress as Address, - currency: nativeCurrency, - testnetMode: !!connectedToHardhat, - }), - }, - ]); + queryClient.invalidateQueries(nftsQueryKey({ address: accountAddress })); + queryClient.invalidateQueries(positionsQueryKey({ address: accountAddress as Address, currency: nativeCurrency })); + queryClient.invalidateQueries(addysSummaryQueryKey({ addresses: allAddresses, currency: nativeCurrency })); + queryClient.invalidateQueries(userAssetsQueryKey({ address: accountAddress, currency: nativeCurrency, connectedToHardhat })); + queryClient.invalidateQueries( + swapsUserAssetsQueryKey({ address: accountAddress as Address, currency: nativeCurrency, testnetMode: !!connectedToHardhat }) + ); try { const getWalletNames = dispatch(fetchWalletNames()); diff --git a/src/hooks/useWalletBalances.ts b/src/hooks/useWalletBalances.ts index bd368aa3042..b65cd756d9b 100644 --- a/src/hooks/useWalletBalances.ts +++ b/src/hooks/useWalletBalances.ts @@ -3,19 +3,88 @@ import { useMemo } from 'react'; import { Address } from 'viem'; import useAccountSettings from './useAccountSettings'; import { useAddysSummary } from '@/resources/summary/summary'; +import { useQueries } from '@tanstack/react-query'; +import { fetchPositions, positionsQueryKey } from '@/resources/defi/PositionsQuery'; +import { RainbowPositions } from '@/resources/defi/types'; +import { add, convertAmountToNativeDisplay } from '@/helpers/utilities'; +import { queryClient } from '@/react-query'; -const useWalletBalances = (wallets: AllRainbowWallets) => { +type WalletBalanceWithPositions = { + assetBalanceAmount: number; + assetBalanceDisplay: string; + positionsBalanceAmount: string | number; + positionsBalanceDisplay: string; + totalBalanceAmount: string | number; + totalBalanceDisplay: string; +}; + +type WalletBalanceWithoutPositions = Omit; + +type WalletBalanceResult = { + balances: Record; + isLoading: boolean; +}; + +const useWalletBalances = (wallets: AllRainbowWallets, withPositions: T = true as T): WalletBalanceResult => { const { nativeCurrency } = useAccountSettings(); - const walletAddresses: Address[] = useMemo( + const allAddresses = useMemo( () => Object.values(wallets).flatMap(wallet => wallet.addresses.map(account => account.address as Address)), [wallets] ); - const { data, isLoading } = useAddysSummary({ addresses: walletAddresses, currency: nativeCurrency }); + const { data: summaryData, isLoading: isSummaryLoading } = useAddysSummary({ + addresses: allAddresses, + currency: nativeCurrency, + }); + + const positionQueries = useQueries({ + queries: allAddresses.map(address => ({ + queryKey: positionsQueryKey({ address, currency: nativeCurrency }), + queryFn: () => fetchPositions({ address, currency: nativeCurrency }), + enabled: !!address && (withPositions as boolean), + })), + }); + + const balancesWithPositions = useMemo(() => { + const result: Record = {}; + + for (const address of allAddresses) { + const lowerCaseAddress = address.toLowerCase() as Address; + const assetBalance = summaryData?.data?.addresses?.[lowerCaseAddress]?.summary?.asset_value || 0; + + if (!withPositions) { + result[lowerCaseAddress] = { + assetBalanceAmount: assetBalance, + assetBalanceDisplay: convertAmountToNativeDisplay(assetBalance, nativeCurrency), + totalBalanceAmount: assetBalance, + totalBalanceDisplay: convertAmountToNativeDisplay(assetBalance, nativeCurrency), + }; + } else { + const positionData = queryClient.getQueryData( + positionsQueryKey({ address, currency: nativeCurrency }) + ); + const positionsBalance = positionData?.totals?.total?.amount || '0'; + const totalAccountBalance = add(assetBalance, positionsBalance); + + result[lowerCaseAddress] = { + assetBalanceAmount: assetBalance, + assetBalanceDisplay: convertAmountToNativeDisplay(assetBalance, nativeCurrency), + positionsBalanceAmount: positionsBalance, + positionsBalanceDisplay: convertAmountToNativeDisplay(positionsBalance, nativeCurrency), + totalBalanceAmount: totalAccountBalance, + totalBalanceDisplay: convertAmountToNativeDisplay(totalAccountBalance, nativeCurrency), + }; + } + } + + return result; + }, [allAddresses, summaryData, withPositions, nativeCurrency]); + + const isLoading = isSummaryLoading || positionQueries.some(query => query.isLoading); return { - balances: data?.data?.addresses, + balances: balancesWithPositions as WalletBalanceResult['balances'], isLoading, }; }; diff --git a/src/hooks/useWalletSectionsData.ts b/src/hooks/useWalletSectionsData.ts index 885b48c6bcc..656d68815fa 100644 --- a/src/hooks/useWalletSectionsData.ts +++ b/src/hooks/useWalletSectionsData.ts @@ -11,13 +11,14 @@ import { buildBriefWalletSectionsSelector } from '@/helpers/buildWalletSections' import { useSortedUserAssets } from '@/resources/assets/useSortedUserAssets'; import { useLegacyNFTs } from '@/resources/nfts'; import useNftSort from './useNFTsSortBy'; -import { useAssetsBalanceForAddress } from './useAssetsBalanceForAddress'; +import useWalletsWithBalancesAndNames from './useWalletsWithBalancesAndNames'; export default function useWalletSectionsData({ type, }: { type?: string; } = {}) { + const { selectedWallet } = useWallets(); const { isLoading: isLoadingUserAssets, data: sortedAssets = [] } = useSortedUserAssets(); const isWalletEthZero = useIsWalletEthZero(); @@ -29,7 +30,11 @@ export default function useWalletSectionsData({ address: accountAddress, }); - const { display: accountBalance, isLoading: isLoadingBalance } = useAssetsBalanceForAddress(accountAddress); + const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); + + const accountWithBalance = walletsWithBalancesAndNames[selectedWallet.id]?.addresses.find( + address => address.address.toLowerCase() === accountAddress.toLowerCase() + ); const { showcaseTokens } = useShowcaseTokens(); const { hiddenTokens } = useHiddenTokens(); @@ -52,8 +57,8 @@ export default function useWalletSectionsData({ pinnedCoins, sendableUniqueTokens, sortedAssets, - accountBalance, - isLoadingBalance, + accountBalance: accountWithBalance?.balance, + isLoadingBalance: !accountWithBalance, // @ts-expect-error ts-migrate(2698) FIXME: Spread types may only be created from object types... Remove this comment to see the full error message ...isWalletEthZero, hiddenTokens, @@ -70,8 +75,8 @@ export default function useWalletSectionsData({ return { hasNFTs, isEmpty, + isLoadingBalance: !accountWithBalance, isLoadingUserAssets, - isLoadingBalance, isWalletEthZero, briefSectionsData, }; @@ -85,8 +90,7 @@ export default function useWalletSectionsData({ pinnedCoins, sendableUniqueTokens, sortedAssets, - accountBalance, - isLoadingBalance, + accountWithBalance, isWalletEthZero, hiddenTokens, isReadOnlyWallet, diff --git a/src/hooks/useWalletsWithBalancesAndNames.ts b/src/hooks/useWalletsWithBalancesAndNames.ts index 19fd3eaeab2..04e382eddcd 100644 --- a/src/hooks/useWalletsWithBalancesAndNames.ts +++ b/src/hooks/useWalletsWithBalancesAndNames.ts @@ -4,16 +4,16 @@ import useWalletBalances from './useWalletBalances'; import useWallets from './useWallets'; import { Address } from 'viem'; -export default function useWalletsWithBalancesAndNames() { +export default function useWalletsWithBalancesAndNames(withPositions = true) { const { walletNames, wallets } = useWallets(); - const walletBalances = useWalletBalances(wallets!); + const walletBalances = useWalletBalances(wallets || {}, withPositions); const walletsWithBalancesAndNames = useMemo( () => mapValues(wallets, wallet => { const updatedAccounts = (wallet.addresses ?? []).map(account => ({ ...account, - balance: walletBalances?.balances?.[account.address?.toLowerCase() as Address]?.summary?.asset_value, + balance: walletBalances.balances[account.address.toLowerCase() as Address].totalBalanceDisplay, ens: walletNames[account.address], })); return { ...wallet, addresses: updatedAccounts }; diff --git a/src/resources/summary/summary.ts b/src/resources/summary/summary.ts index 04337c43eb2..344f5c57b63 100644 --- a/src/resources/summary/summary.ts +++ b/src/resources/summary/summary.ts @@ -56,7 +56,7 @@ export type AddysSummaryArgs = { // /////////////////////////////////////////////// // Query Key -const addysSummaryQueryKey = ({ addresses, currency }: AddysSummaryArgs) => +export const addysSummaryQueryKey = ({ addresses, currency }: AddysSummaryArgs) => createQueryKey('addysSummary', { addresses, currency }, { persisterVersion: 1 }); type AddysSummaryQueryKey = ReturnType; From 148a1eb8d095cd75a74959e6c5d7573981bd0c5a Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Mon, 5 Aug 2024 16:54:31 -0400 Subject: [PATCH 10/36] separate invalidateQueries because they don't update when grouped for some reason --- .../screens/Swap/providers/swap-provider.tsx | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/__swaps__/screens/Swap/providers/swap-provider.tsx b/src/__swaps__/screens/Swap/providers/swap-provider.tsx index 7fe0c399e89..1f86643325b 100644 --- a/src/__swaps__/screens/Swap/providers/swap-provider.tsx +++ b/src/__swaps__/screens/Swap/providers/swap-provider.tsx @@ -264,24 +264,20 @@ export const SwapProvider = ({ children }: SwapProviderProps) => { } } - queryClient.invalidateQueries([ - // old user assets invalidation - { - queryKey: userAssetsQueryKey({ - address: parameters.quote.from, - currency: nativeCurrency, - connectedToHardhat, - }), - }, - // new swaps user assets invalidations - { - queryKey: swapsUserAssetsQueryKey({ - address: parameters.quote.from as Address, - currency: nativeCurrency, - testnetMode: !!connectedToHardhat, - }), - }, - ]); + queryClient.invalidateQueries( + userAssetsQueryKey({ + address: parameters.quote.from, + currency: nativeCurrency, + connectedToHardhat, + }) + ); + queryClient.invalidateQueries( + swapsUserAssetsQueryKey({ + address: parameters.quote.from as Address, + currency: nativeCurrency, + testnetMode: !!connectedToHardhat, + }) + ); clearCustomGasSettings(chainId); NotificationManager?.postNotification('rapCompleted'); From d5a2a677460ef0c9b6aaa9305c92bc49f647f076 Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Mon, 5 Aug 2024 16:59:02 -0400 Subject: [PATCH 11/36] more instances --- src/hooks/useWatchPendingTxs.ts | 36 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/hooks/useWatchPendingTxs.ts b/src/hooks/useWatchPendingTxs.ts index ce012e60f30..30fee5b24a3 100644 --- a/src/hooks/useWatchPendingTxs.ts +++ b/src/hooks/useWatchPendingTxs.ts @@ -1,7 +1,7 @@ import { useCallback, useMemo } from 'react'; import useAccountSettings from './useAccountSettings'; import { RainbowTransaction, MinedTransaction } from '@/entities/transactions/transaction'; -import { fetchUserAssets, userAssetsQueryKey } from '@/resources/assets/UserAssetsQuery'; +import { userAssetsQueryKey } from '@/resources/assets/UserAssetsQuery'; import { userAssetsQueryKey as swapsUserAssetsQueryKey } from '@/__swaps__/screens/Swap/resources/assets/userAssets'; import { transactionFetchQuery } from '@/resources/transactions/transaction'; import { RainbowError, logger } from '@/logger'; @@ -14,6 +14,7 @@ import { getTransactionFlashbotStatus } from '@/handlers/transactions'; import { usePendingTransactionsStore } from '@/state/pendingTransactions'; import { useNonceStore } from '@/state/nonces'; import { Address } from 'viem'; +import { nftsQueryKey } from '@/resources/nfts'; export const useWatchPendingTransactions = ({ address }: { address: string }) => { const { storePendingTransactions, setPendingTransactions } = usePendingTransactionsStore(state => ({ @@ -31,24 +32,21 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => (_: RainbowTransaction) => { // NOTE: We have two user assets stores right now, so let's invalidate both queries and trigger a refetch const connectedToHardhat = getIsHardhatConnected(); - queryClient.invalidateQueries([ - // old user assets invalidation - { - queryKey: userAssetsQueryKey({ - address, - currency: nativeCurrency, - connectedToHardhat, - }), - }, - // new swaps user assets invalidations - { - queryKey: swapsUserAssetsQueryKey({ - address: address as Address, - currency: nativeCurrency, - testnetMode: !!connectedToHardhat, - }), - }, - ]); + queryClient.invalidateQueries( + userAssetsQueryKey({ + address, + currency: nativeCurrency, + connectedToHardhat, + }) + ); + queryClient.invalidateQueries( + swapsUserAssetsQueryKey({ + address: address as Address, + currency: nativeCurrency, + testnetMode: !!connectedToHardhat, + }) + ); + queryClient.invalidateQueries(nftsQueryKey({ address })); }, [address, nativeCurrency] ); From 1b4013ff3a5a84286619f8a2a8f64e242130a966 Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Mon, 5 Aug 2024 17:06:10 -0400 Subject: [PATCH 12/36] cleanup --- src/helpers/buildWalletSections.tsx | 6 +--- src/hooks/useAccountBalance.ts | 30 ------------------- src/hooks/useAssetsBalanceForAddress.ts | 40 ------------------------- 3 files changed, 1 insertion(+), 75 deletions(-) delete mode 100644 src/hooks/useAccountBalance.ts delete mode 100644 src/hooks/useAssetsBalanceForAddress.ts diff --git a/src/helpers/buildWalletSections.tsx b/src/helpers/buildWalletSections.tsx index f18aff6e5a0..52a081be842 100644 --- a/src/helpers/buildWalletSections.tsx +++ b/src/helpers/buildWalletSections.tsx @@ -7,7 +7,6 @@ import store from '@/redux/store'; import { PositionExtraData } from '@/components/asset-list/RecyclerAssetList2/core/ViewTypes'; import { getExperimetalFlag, DEFI_POSITIONS } from '@/config/experimental'; import { RainbowPositions } from '@/resources/defi/types'; -import { add, convertAmountToNativeDisplay } from './utilities'; const CONTENT_PLACEHOLDER = [ { type: 'LOADING_ASSETS', uid: 'loadings-asset-1' }, @@ -40,7 +39,6 @@ const ONLY_NFTS_CONTENT = [{ type: 'ETH_CARD', uid: 'eth-card' }]; const sortedAssetsSelector = (state: any) => state.sortedAssets; const accountBalanceSelector = (state: any) => state.accountBalance; -const isLoadingBalanceSelector = (state: any) => state.isLoadingBalance; const hiddenCoinsSelector = (state: any) => state.hiddenCoins; const isCoinListEditedSelector = (state: any) => state.isCoinListEdited; const isLoadingUserAssetsSelector = (state: any) => state.isLoadingUserAssets; @@ -108,7 +106,6 @@ const withBriefBalanceSection = ( sortedAssets: ParsedAddressAsset[], isLoadingUserAssets: boolean, accountBalance: number | undefined, - isLoadingBalance: boolean, nativeCurrency: NativeCurrencyKey, isCoinListEdited: boolean, pinnedCoins: any, @@ -128,7 +125,7 @@ const withBriefBalanceSection = ( type: 'PROFILE_STICKY_HEADER', uid: 'assets-profile-header-compact', value: accountBalance, - isLoadingUserAssets: isLoadingBalance, + isLoadingUserAssets, }, { type: 'PROFILE_AVATAR_ROW_SPACE_BEFORE', @@ -221,7 +218,6 @@ const briefBalanceSectionSelector = createSelector( sortedAssetsSelector, isLoadingUserAssetsSelector, accountBalanceSelector, - isLoadingBalanceSelector, nativeCurrencySelector, isCoinListEditedSelector, pinnedCoinsSelector, diff --git a/src/hooks/useAccountBalance.ts b/src/hooks/useAccountBalance.ts deleted file mode 100644 index 71257341cf8..00000000000 --- a/src/hooks/useAccountBalance.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Address } from 'viem'; -import useAccountSettings from './useAccountSettings'; -import { useAddysSummary } from '@/resources/summary/summary'; -import { usePositions } from '@/resources/defi/PositionsQuery'; -import { add, convertAmountToNativeDisplay } from '@/helpers/utilities'; - -const useAccountBalance = (address: Address) => { - const { nativeCurrency } = useAccountSettings(); - - const lowerCaseAddress = address.toLowerCase() as Address; - - const { data: summaryData, isLoading: isSummaryLoading } = useAddysSummary({ addresses: [lowerCaseAddress], currency: nativeCurrency }); - const { data: positionsData, isLoading: isPositionsLoading } = usePositions({ address: lowerCaseAddress, currency: nativeCurrency }); - - const assetBalance = summaryData?.data?.addresses?.[lowerCaseAddress]?.summary?.asset_value || 0; - const positionsBalance = positionsData?.totals?.total?.amount || '0'; - const totalBalance = add(assetBalance, positionsBalance); - - return { - assetBalanceAmount: assetBalance, - assetBalanceDisplay: convertAmountToNativeDisplay(assetBalance, nativeCurrency), - positionsBalanceAmount: positionsBalance, - positionsBalanceDisplay: convertAmountToNativeDisplay(positionsBalance, nativeCurrency), - totalBalanceAmount: totalBalance, - totalBalanceDisplay: convertAmountToNativeDisplay(totalBalance, nativeCurrency), - isLoading: isSummaryLoading || isPositionsLoading, - }; -}; - -export default useAccountBalance; diff --git a/src/hooks/useAssetsBalanceForAddress.ts b/src/hooks/useAssetsBalanceForAddress.ts deleted file mode 100644 index 58ad6d64f61..00000000000 --- a/src/hooks/useAssetsBalanceForAddress.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { useCallback } from 'react'; -import { Address } from 'viem'; - -import { selectUserAssetsBalance, selectorFilterByUserChains } from '@/__swaps__/screens/Swap/resources/_selectors/assets'; -import { useUserAssets } from '@/__swaps__/screens/Swap/resources/assets'; -import { EthereumAddress, ParsedAddressAsset } from '@/entities'; -import useAccountSettings from './useAccountSettings'; -import { convertAmountToNativeDisplay } from '@/helpers/utilities'; -import useCoinListEditOptions from './useCoinListEditOptions'; - -export function useAssetsBalanceForAddress(address: EthereumAddress) { - const { nativeCurrency } = useAccountSettings(); - const { hiddenCoinsObj: hidden } = useCoinListEditOptions(); - const isHidden = useCallback( - (asset: ParsedAddressAsset) => { - return !!hidden[asset.address]; - }, - [hidden] - ); - - const { data: totalAssetsBalance, isLoading } = useUserAssets( - { - address: address as Address, - currency: nativeCurrency, - }, - { - select: data => - selectorFilterByUserChains({ - data, - selector: data => selectUserAssetsBalance(data, asset => isHidden(asset as unknown as ParsedAddressAsset)), - }), - } - ); - - return { - amount: totalAssetsBalance, - display: totalAssetsBalance ? convertAmountToNativeDisplay(totalAssetsBalance, nativeCurrency) : undefined, - isLoading, - }; -} From 1277e6d54c498172a4d7ae6397a554d19b92e16a Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Thu, 8 Aug 2024 15:46:02 -0400 Subject: [PATCH 13/36] cleanup useWatchPendingTxs --- src/hooks/useWatchPendingTxs.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hooks/useWatchPendingTxs.ts b/src/hooks/useWatchPendingTxs.ts index 30fee5b24a3..aed5c6fad25 100644 --- a/src/hooks/useWatchPendingTxs.ts +++ b/src/hooks/useWatchPendingTxs.ts @@ -26,7 +26,7 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => const pendingTransactions = useMemo(() => storePendingTransactions[address] || [], [address, storePendingTransactions]); - const { nativeCurrency, accountAddress } = useAccountSettings(); + const { nativeCurrency } = useAccountSettings(); const refreshAssets = useCallback( (_: RainbowTransaction) => { @@ -190,7 +190,7 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => const chainIds = RainbowNetworks.filter(network => network.enabled && network.networkType !== 'testnet').map(network => network.id); await queryClient.refetchQueries({ queryKey: consolidatedTransactionsQueryKey({ - address: accountAddress, + address, currency: nativeCurrency, chainIds, }), @@ -200,7 +200,7 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => setTimeout(() => { queryClient.refetchQueries({ queryKey: consolidatedTransactionsQueryKey({ - address: accountAddress, + address, currency: nativeCurrency, chainIds, }), @@ -208,10 +208,10 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => }, 2000); } setPendingTransactions({ - address: accountAddress, + address, pendingTransactions: newPendingTransactions, }); - }, [accountAddress, nativeCurrency, pendingTransactions, processNonces, processPendingTransaction, setPendingTransactions]); + }, [address, nativeCurrency, pendingTransactions, processNonces, processPendingTransaction, setPendingTransactions]); return { watchPendingTransactions }; }; From 9efc708294c748b8732e9804d4e73e3a2bf6505b Mon Sep 17 00:00:00 2001 From: Matthew Wall Date: Thu, 8 Aug 2024 15:49:36 -0400 Subject: [PATCH 14/36] code suggestions --- src/components/DappBrowser/control-panel/ControlPanel.tsx | 7 ++----- src/components/change-wallet/AddressRow.tsx | 8 +------- src/components/contacts/ContactRow.js | 8 +------- src/hooks/useWalletSectionsData.ts | 3 +-- 4 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/components/DappBrowser/control-panel/ControlPanel.tsx b/src/components/DappBrowser/control-panel/ControlPanel.tsx index 04ebc91f966..54527d30c62 100644 --- a/src/components/DappBrowser/control-panel/ControlPanel.tsx +++ b/src/components/DappBrowser/control-panel/ControlPanel.tsx @@ -154,12 +154,9 @@ export const ControlPanel = () => { ), label: removeFirstEmojiFromString(account.label) || address(account.address, 6, 4), secondaryLabel: - // eslint-disable-next-line no-nested-ternary wallet.type === WalletTypes.readOnly ? i18n.t(i18n.l.wallet.change_wallet.watching) - : account.balance - ? account.balance - : i18n.t(i18n.l.wallet.change_wallet.no_balance), + : account.balance ?? i18n.t(i18n.l.wallet.change_wallet.no_balance), uniqueId: account.address, color: colors.avatarBackgrounds[account.color], imageUrl: account.image || undefined, @@ -184,7 +181,7 @@ export const ControlPanel = () => { const sortedItems = [...sortedWallets, ...bluetoothWallets, ...readOnlyWallets]; return sortedItems; - }, [walletsWithBalancesAndNames, currentAddress, nativeCurrency]); + }, [walletsWithBalancesAndNames, currentAddress]); const { testnetsEnabled } = store.getState().settings; diff --git a/src/components/change-wallet/AddressRow.tsx b/src/components/change-wallet/AddressRow.tsx index fab128e11e2..07e6e76da6c 100644 --- a/src/components/change-wallet/AddressRow.tsx +++ b/src/components/change-wallet/AddressRow.tsx @@ -126,13 +126,7 @@ export default function AddressRow({ contextMenuActions, data, editMode, onPress const labelQuaternary = useForegroundColor('labelQuaternary'); - const balanceOrNoBalance = useMemo(() => { - if (balance) { - return balance; - } else { - return lang.t('wallet.change_wallet.no_balance'); - } - }, [balance]); + const balanceOrNoBalance = balance || lang.t('wallet.change_wallet.no_balance'); const cleanedUpLabel = useMemo(() => removeFirstEmojiFromString(label), [label]); diff --git a/src/components/contacts/ContactRow.js b/src/components/contacts/ContactRow.js index 11b67df1d40..46883366f58 100644 --- a/src/components/contacts/ContactRow.js +++ b/src/components/contacts/ContactRow.js @@ -60,13 +60,7 @@ const ContactRow = ({ address, color, nickname, symmetricalMargins, ...props }, const { colors } = useTheme(); const { accountType, balance, ens, image, label, network, onPress, showcaseItem, testID } = props; - const cleanedUpBalance = useMemo(() => { - if (balance) { - return balance; - } else { - return i18n.t(i18n.l.wallet.change_wallet.no_balance); - } - }, [balance]); + const cleanedUpBalance = balance || i18n.t(i18n.l.wallet.change_wallet.no_balance); // show avatar for contact rows that are accounts, not contacts const avatar = accountType !== 'contacts' ? returnStringFirstEmoji(label) || profileUtils.addressHashedEmoji(address) : null; diff --git a/src/hooks/useWalletSectionsData.ts b/src/hooks/useWalletSectionsData.ts index 656d68815fa..82d5ae0b038 100644 --- a/src/hooks/useWalletSectionsData.ts +++ b/src/hooks/useWalletSectionsData.ts @@ -18,7 +18,7 @@ export default function useWalletSectionsData({ }: { type?: string; } = {}) { - const { selectedWallet } = useWallets(); + const { selectedWallet, isReadOnlyWallet } = useWallets(); const { isLoading: isLoadingUserAssets, data: sortedAssets = [] } = useSortedUserAssets(); const isWalletEthZero = useIsWalletEthZero(); @@ -38,7 +38,6 @@ export default function useWalletSectionsData({ const { showcaseTokens } = useShowcaseTokens(); const { hiddenTokens } = useHiddenTokens(); - const { isReadOnlyWallet } = useWallets(); const { hiddenCoinsObj: hiddenCoins, pinnedCoinsObj: pinnedCoins } = useCoinListEditOptions(); From 2c018d8c1eb43abed72f197866305d6d2c28aa36 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Thu, 8 Aug 2024 14:28:01 -0600 Subject: [PATCH 15/36] break up useWallets --- .../ens-profile/ActionButtons/MoreButton.tsx | 4 ++- src/hooks/useSwitchWallet.ts | 30 +++++++++++++++++++ src/hooks/useWallets.ts | 24 ++------------- src/notifications/NotificationsHandler.tsx | 14 +++++---- src/screens/SignTransactionSheet.tsx | 4 ++- .../points/components/LeaderboardRow.tsx | 4 ++- 6 files changed, 49 insertions(+), 31 deletions(-) create mode 100644 src/hooks/useSwitchWallet.ts diff --git a/src/components/ens-profile/ActionButtons/MoreButton.tsx b/src/components/ens-profile/ActionButtons/MoreButton.tsx index 95b96316997..a1947721c72 100644 --- a/src/components/ens-profile/ActionButtons/MoreButton.tsx +++ b/src/components/ens-profile/ActionButtons/MoreButton.tsx @@ -13,6 +13,7 @@ import Routes from '@/navigation/routesNames'; import { ethereumUtils } from '@/utils'; import { formatAddressForDisplay } from '@/utils/abbreviations'; import { Network } from '@/networks/types'; +import useSwitchWallet from '@/hooks/useSwitchWallet'; const ACTIONS = { ADD_CONTACT: 'add-contact', @@ -24,7 +25,8 @@ const ACTIONS = { }; export default function MoreButton({ address, ensName }: { address?: string; ensName?: string }) { - const { switchToWalletWithAddress, selectedWallet } = useWallets(); + const { selectedWallet } = useWallets(); + const { switchToWalletWithAddress } = useSwitchWallet(); const { isWatching } = useWatchWallet({ address }); const { navigate } = useNavigation(); const { setClipboard } = useClipboard(); diff --git a/src/hooks/useSwitchWallet.ts b/src/hooks/useSwitchWallet.ts new file mode 100644 index 00000000000..dd0bda69a0f --- /dev/null +++ b/src/hooks/useSwitchWallet.ts @@ -0,0 +1,30 @@ +import { useDispatch } from 'react-redux'; +import { addressSetSelected, walletsSetSelected } from '../redux/wallets'; +import useInitializeWallet from './useInitializeWallet'; +import { toChecksumAddress } from '@/handlers/web3'; +import { RainbowAccount } from '@/model/wallet'; +import useWallets from './useWallets'; + +export default function useSwitchWallet() { + const initializeWallet = useInitializeWallet(); + const dispatch = useDispatch(); + const { wallets } = useWallets(); + + const switchToWalletWithAddress = async (address: string): Promise => { + const walletKey = Object.keys(wallets!).find(key => { + // Addresses + return wallets![key].addresses.find((account: RainbowAccount) => account.address.toLowerCase() === address.toLowerCase()); + }); + + if (!walletKey) return null; + const p1 = dispatch(walletsSetSelected(wallets![walletKey])); + const p2 = dispatch(addressSetSelected(toChecksumAddress(address)!)); + await Promise.all([p1, p2]); + // @ts-expect-error ts-migrate(2554) FIXME: Expected 8-9 arguments, but got 7. + return initializeWallet(null, null, null, false, false, null, true); + }; + + return { + switchToWalletWithAddress, + }; +} diff --git a/src/hooks/useWallets.ts b/src/hooks/useWallets.ts index 64d5c2abcf3..4fc5b7778b4 100644 --- a/src/hooks/useWallets.ts +++ b/src/hooks/useWallets.ts @@ -1,12 +1,9 @@ import { useMemo } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import { useSelector } from 'react-redux'; import { createSelector } from 'reselect'; import { findLatestBackUp } from '../model/backup'; -import { addressSetSelected, walletsSetSelected } from '../redux/wallets'; -import useInitializeWallet from './useInitializeWallet'; -import { toChecksumAddress } from '@/handlers/web3'; import WalletTypes from '@/helpers/walletTypes'; -import { RainbowAccount, RainbowWallet } from '@/model/wallet'; +import { RainbowWallet } from '@/model/wallet'; import { AppState } from '@/redux/store'; import logger from '@/utils/logger'; @@ -27,8 +24,6 @@ const walletSelector = createSelector( ); export default function useWallets() { - const initializeWallet = useInitializeWallet(); - const dispatch = useDispatch(); const { isWalletLoading, latestBackup, selectedWallet, walletNames, wallets } = useSelector(walletSelector); const isDamaged = useMemo(() => { @@ -41,20 +36,6 @@ export default function useWallets() { return bool; }, [selectedWallet, wallets]); - const switchToWalletWithAddress = async (address: string): Promise => { - const walletKey = Object.keys(wallets!).find(key => { - // Addresses - return wallets![key].addresses.find((account: RainbowAccount) => account.address.toLowerCase() === address.toLowerCase()); - }); - - if (!walletKey) return null; - const p1 = dispatch(walletsSetSelected(wallets![walletKey])); - const p2 = dispatch(addressSetSelected(toChecksumAddress(address)!)); - await Promise.all([p1, p2]); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 8-9 arguments, but got 7. - return initializeWallet(null, null, null, false, false, null, true); - }; - return { isDamaged, isReadOnlyWallet: selectedWallet.type === WalletTypes.readOnly, @@ -62,7 +43,6 @@ export default function useWallets() { isWalletLoading, latestBackup, selectedWallet, - switchToWalletWithAddress, walletNames, wallets, }; diff --git a/src/notifications/NotificationsHandler.tsx b/src/notifications/NotificationsHandler.tsx index a076c628f09..48e49b00359 100644 --- a/src/notifications/NotificationsHandler.tsx +++ b/src/notifications/NotificationsHandler.tsx @@ -38,15 +38,17 @@ import { } from '@/notifications/settings/initialization'; import { logger } from '@/logger'; import { transactionFetchQuery } from '@/resources/transactions/transaction'; +import useSwitchWallet from '@/hooks/useSwitchWallet'; type Callback = () => void; type Props = PropsWithChildren<{ walletReady: boolean }>; export const NotificationsHandler = ({ walletReady }: Props) => { - const wallets = useWallets(); + const { wallets } = useWallets(); + const walletSwitcher = useSwitchWallet(); const dispatch: ThunkDispatch = useDispatch(); - const walletsRef = useRef(wallets); + const walletSwitcherRef = useRef(walletSwitcher); const prevWalletReady = usePrevious(walletReady); const subscriptionChangesListener = useRef(); const onTokenRefreshListener = useRef(); @@ -61,7 +63,7 @@ export const NotificationsHandler = ({ walletReady }: Props) => { We need to save wallets property to a ref in order to have an up-to-date value inside the event listener callbacks closure */ - walletsRef.current = wallets; + walletSwitcherRef.current = walletSwitcher; const onForegroundRemoteNotification = (remoteMessage: FirebaseMessagingTypes.RemoteMessage) => { const type = remoteMessage?.data?.type; @@ -152,12 +154,12 @@ export const NotificationsHandler = ({ walletReady }: Props) => { // casting data payload to type that was agreed on with backend const data = notification.data as unknown as TransactionNotificationData; - const wallets = walletsRef.current; + const walletSwitcher = walletSwitcherRef.current; const { accountAddress, nativeCurrency } = store.getState().settings; let walletAddress: string | null | undefined = accountAddress; if (!isLowerCaseMatch(accountAddress, data.address)) { - walletAddress = await wallets.switchToWalletWithAddress(data.address); + walletAddress = await walletSwitcher.switchToWalletWithAddress(data.address); } if (!walletAddress) { return; @@ -242,7 +244,7 @@ export const NotificationsHandler = ({ walletReady }: Props) => { if (walletReady && !alreadyRanInitialization.current) { const addresses: AddressWithRelationship[] = []; - Object.values(wallets.wallets ?? {}).forEach(wallet => + Object.values(wallets ?? {}).forEach(wallet => wallet?.addresses.forEach( ({ address, visible }: { address: string; visible: boolean }) => visible && diff --git a/src/screens/SignTransactionSheet.tsx b/src/screens/SignTransactionSheet.tsx index 84a0a3acdaa..06bba51e89a 100644 --- a/src/screens/SignTransactionSheet.tsx +++ b/src/screens/SignTransactionSheet.tsx @@ -97,6 +97,7 @@ import { RequestSource } from '@/utils/requestNavigationHandlers'; import { event } from '@/analytics/event'; import { getOnchainAssetBalance } from '@/handlers/assets'; import { performanceTracking, Screens, TimeToSignOperation } from '@/state/performance/performance'; +import useSwitchWallet from '@/hooks/useSwitchWallet'; const COLLAPSED_CARD_HEIGHT = 56; const MAX_CARD_HEIGHT = 176; @@ -162,7 +163,8 @@ export const SignTransactionSheet = () => { const [simulationScanResult, setSimulationScanResult] = useState(undefined); const { params: routeParams } = useRoute(); - const { wallets, walletNames, switchToWalletWithAddress } = useWallets(); + const { wallets, walletNames } = useWallets(); + const { switchToWalletWithAddress } = useSwitchWallet(); const { transactionDetails, onSuccess: onSuccessCallback, diff --git a/src/screens/points/components/LeaderboardRow.tsx b/src/screens/points/components/LeaderboardRow.tsx index 6892a058fd0..c5ee4583f3f 100644 --- a/src/screens/points/components/LeaderboardRow.tsx +++ b/src/screens/points/components/LeaderboardRow.tsx @@ -20,6 +20,7 @@ import { useTheme } from '@/theme'; import LinearGradient from 'react-native-linear-gradient'; import { ButtonPressAnimation } from '@/components/animations'; import { noop } from 'lodash'; +import useSwitchWallet from '@/hooks/useSwitchWallet'; const ACTIONS = { ADD_CONTACT: 'add-contact', @@ -43,7 +44,8 @@ export const LeaderboardRow = memo(function LeaderboardRow({ points: number; rank: number; }) { - const { switchToWalletWithAddress, selectedWallet } = useWallets(); + const { selectedWallet } = useWallets(); + const { switchToWalletWithAddress } = useSwitchWallet(); const { isWatching } = useWatchWallet({ address }); const { colors } = useTheme(); const { navigate } = useNavigation(); From 647d1b0a49f21bf5dc4a5924ced267982b117277 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Thu, 8 Aug 2024 14:57:34 -0600 Subject: [PATCH 16/36] rm latestBackup from useWallets --- src/components/backup/useCreateBackup.ts | 7 ++++--- src/hooks/useWalletCloudBackup.ts | 7 ++++--- src/hooks/useWallets.ts | 5 +---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/components/backup/useCreateBackup.ts b/src/components/backup/useCreateBackup.ts index 71a778b2252..92d62c01de2 100644 --- a/src/components/backup/useCreateBackup.ts +++ b/src/components/backup/useCreateBackup.ts @@ -1,6 +1,6 @@ /* eslint-disable no-promise-executor-return */ -import { useCallback, useState } from 'react'; -import { backupAllWalletsToCloud, getLocalBackupPassword, saveLocalBackupPassword } from '@/model/backup'; +import { useCallback, useMemo, useState } from 'react'; +import { backupAllWalletsToCloud, findLatestBackUp, getLocalBackupPassword, saveLocalBackupPassword } from '@/model/backup'; import { useCloudBackups } from './CloudBackupProvider'; import { cloudPlatform } from '@/utils/platform'; import { analytics } from '@/analytics'; @@ -34,7 +34,8 @@ export const useCreateBackup = ({ walletId, navigateToRoute }: UseCreateBackupPr const { fetchBackups } = useCloudBackups(); const walletCloudBackup = useWalletCloudBackup(); - const { latestBackup, wallets } = useWallets(); + const { wallets } = useWallets(); + const latestBackup = useMemo(() => findLatestBackUp(wallets), [wallets]); const [loading, setLoading] = useState('none'); const [password, setPassword] = useState(''); diff --git a/src/hooks/useWalletCloudBackup.ts b/src/hooks/useWalletCloudBackup.ts index c0c76e6e0cb..f0efed48182 100644 --- a/src/hooks/useWalletCloudBackup.ts +++ b/src/hooks/useWalletCloudBackup.ts @@ -1,10 +1,10 @@ import { captureException } from '@sentry/react-native'; import lang from 'i18n-js'; import { values } from 'lodash'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { Linking } from 'react-native'; import { useDispatch } from 'react-redux'; -import { addWalletToCloudBackup, backupWalletToCloud } from '../model/backup'; +import { addWalletToCloudBackup, backupWalletToCloud, findLatestBackUp } from '../model/backup'; import { setWalletBackedUp } from '../redux/wallets'; import { cloudPlatform } from '../utils/platform'; import useWallets from './useWallets'; @@ -40,7 +40,8 @@ export function getUserError(e: Error) { export default function useWalletCloudBackup() { const dispatch = useDispatch(); - const { latestBackup, wallets } = useWallets(); + const { wallets } = useWallets(); + const latestBackup = useMemo(() => findLatestBackUp(wallets), [wallets]); const walletCloudBackup = useCallback( async ({ diff --git a/src/hooks/useWallets.ts b/src/hooks/useWallets.ts index 4fc5b7778b4..d90c9b140a0 100644 --- a/src/hooks/useWallets.ts +++ b/src/hooks/useWallets.ts @@ -1,7 +1,6 @@ import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { createSelector } from 'reselect'; -import { findLatestBackUp } from '../model/backup'; import WalletTypes from '@/helpers/walletTypes'; import { RainbowWallet } from '@/model/wallet'; import { AppState } from '@/redux/store'; @@ -16,7 +15,6 @@ const walletSelector = createSelector( }), ({ isWalletLoading, selectedWallet, walletNames, wallets }) => ({ isWalletLoading, - latestBackup: findLatestBackUp(wallets), selectedWallet, walletNames, wallets, @@ -24,7 +22,7 @@ const walletSelector = createSelector( ); export default function useWallets() { - const { isWalletLoading, latestBackup, selectedWallet, walletNames, wallets } = useSelector(walletSelector); + const { isWalletLoading, selectedWallet, walletNames, wallets } = useSelector(walletSelector); const isDamaged = useMemo(() => { const bool = selectedWallet?.damaged; @@ -41,7 +39,6 @@ export default function useWallets() { isReadOnlyWallet: selectedWallet.type === WalletTypes.readOnly, isHardwareWallet: !!selectedWallet.deviceId, isWalletLoading, - latestBackup, selectedWallet, walletNames, wallets, From c05f854a6ea94cf448be11f661c012473fc449ea Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Thu, 8 Aug 2024 15:03:44 -0600 Subject: [PATCH 17/36] useMemo -> useEffect --- src/hooks/useWallets.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hooks/useWallets.ts b/src/hooks/useWallets.ts index d90c9b140a0..601c93fc1a1 100644 --- a/src/hooks/useWallets.ts +++ b/src/hooks/useWallets.ts @@ -1,4 +1,4 @@ -import { useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { useSelector } from 'react-redux'; import { createSelector } from 'reselect'; import WalletTypes from '@/helpers/walletTypes'; @@ -24,15 +24,15 @@ const walletSelector = createSelector( export default function useWallets() { const { isWalletLoading, selectedWallet, walletNames, wallets } = useSelector(walletSelector); - const isDamaged = useMemo(() => { - const bool = selectedWallet?.damaged; - if (bool) { + const isDamaged = selectedWallet?.damaged; + + useEffect(() => { + if (isDamaged) { logger.sentry('Wallet is damaged. Check values below:'); logger.sentry('selectedWallet: ', selectedWallet); logger.sentry('wallets: ', wallets); } - return bool; - }, [selectedWallet, wallets]); + }, [isDamaged, selectedWallet, wallets]); return { isDamaged, From 4f05b85bab32b4bc5c24bec18f2eed3e42f9a907 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Thu, 8 Aug 2024 15:05:56 -0600 Subject: [PATCH 18/36] logging --- src/hooks/useWallets.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/hooks/useWallets.ts b/src/hooks/useWallets.ts index 601c93fc1a1..5b1faf84d7b 100644 --- a/src/hooks/useWallets.ts +++ b/src/hooks/useWallets.ts @@ -4,7 +4,7 @@ import { createSelector } from 'reselect'; import WalletTypes from '@/helpers/walletTypes'; import { RainbowWallet } from '@/model/wallet'; import { AppState } from '@/redux/store'; -import logger from '@/utils/logger'; +import { logger } from '@/logger'; const walletSelector = createSelector( ({ wallets: { isWalletLoading, selected = {} as RainbowWallet, walletNames, wallets } }: AppState) => ({ @@ -28,9 +28,7 @@ export default function useWallets() { useEffect(() => { if (isDamaged) { - logger.sentry('Wallet is damaged. Check values below:'); - logger.sentry('selectedWallet: ', selectedWallet); - logger.sentry('wallets: ', wallets); + logger.warn('Wallet is damaged. Check attached metadata.', { selectedWallet, wallets }); } }, [isDamaged, selectedWallet, wallets]); From bb5cd7747669586e6cab561b1349a7bc9bf6c6c8 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Thu, 8 Aug 2024 15:09:32 -0600 Subject: [PATCH 19/36] cleanup --- src/components/ens-profile/ActionButtons/MoreButton.tsx | 3 +-- src/hooks/index.ts | 1 + src/notifications/NotificationsHandler.tsx | 3 +-- src/screens/SignTransactionSheet.tsx | 3 +-- src/screens/points/components/LeaderboardRow.tsx | 3 +-- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/components/ens-profile/ActionButtons/MoreButton.tsx b/src/components/ens-profile/ActionButtons/MoreButton.tsx index a1947721c72..c9ac185cef6 100644 --- a/src/components/ens-profile/ActionButtons/MoreButton.tsx +++ b/src/components/ens-profile/ActionButtons/MoreButton.tsx @@ -6,14 +6,13 @@ import { MenuActionConfig } from 'react-native-ios-context-menu'; import { showDeleteContactActionSheet } from '../../contacts'; import More from '../MoreButton/MoreButton'; import ContextMenuButton from '@/components/native-context-menu/contextMenu'; -import { useClipboard, useContacts, useWallets, useWatchWallet } from '@/hooks'; +import { useClipboard, useContacts, useSwitchWallet, useWallets, useWatchWallet } from '@/hooks'; import { useNavigation } from '@/navigation'; import { RAINBOW_PROFILES_BASE_URL } from '@/references'; import Routes from '@/navigation/routesNames'; import { ethereumUtils } from '@/utils'; import { formatAddressForDisplay } from '@/utils/abbreviations'; import { Network } from '@/networks/types'; -import useSwitchWallet from '@/hooks/useSwitchWallet'; const ACTIONS = { ADD_CONTACT: 'add-contact', diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 048802245d6..f550c40c845 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -94,6 +94,7 @@ export { default as useSwapSettings } from './useSwapSettings'; export { default as useSwapDerivedOutputs } from './useSwapDerivedOutputs'; export { default as useSwapDerivedValues } from './useSwapDerivedValues'; export { default as useSwapRefuel } from './useSwapRefuel'; +export { default as useSwitchWallet } from './useSwitchWallet'; export { default as useTimeout } from './useTimeout'; export { default as useTransactionConfirmation } from './useTransactionConfirmation'; export { default as usePendingTransactions } from './usePendingTransactions'; diff --git a/src/notifications/NotificationsHandler.tsx b/src/notifications/NotificationsHandler.tsx index 48e49b00359..d809e788d47 100644 --- a/src/notifications/NotificationsHandler.tsx +++ b/src/notifications/NotificationsHandler.tsx @@ -1,5 +1,5 @@ import { PropsWithChildren, useCallback, useEffect, useRef } from 'react'; -import { usePrevious, useWallets } from '@/hooks'; +import { usePrevious, useSwitchWallet, useWallets } from '@/hooks'; import { setupAndroidChannels } from '@/notifications/setupAndroidChannels'; import messaging, { FirebaseMessagingTypes } from '@react-native-firebase/messaging'; import { @@ -38,7 +38,6 @@ import { } from '@/notifications/settings/initialization'; import { logger } from '@/logger'; import { transactionFetchQuery } from '@/resources/transactions/transaction'; -import useSwitchWallet from '@/hooks/useSwitchWallet'; type Callback = () => void; diff --git a/src/screens/SignTransactionSheet.tsx b/src/screens/SignTransactionSheet.tsx index 06bba51e89a..d4b8b505431 100644 --- a/src/screens/SignTransactionSheet.tsx +++ b/src/screens/SignTransactionSheet.tsx @@ -57,7 +57,7 @@ import { import { findWalletWithAccount } from '@/helpers/findWalletWithAccount'; import { getAccountProfileInfo } from '@/helpers/accountInfo'; -import { useAccountSettings, useClipboard, useDimensions, useGas, useWallets } from '@/hooks'; +import { useAccountSettings, useClipboard, useDimensions, useGas, useSwitchWallet, useWallets } from '@/hooks'; import ImageAvatar from '@/components/contacts/ImageAvatar'; import { ContactAvatar } from '@/components/contacts'; import { IS_IOS } from '@/env'; @@ -97,7 +97,6 @@ import { RequestSource } from '@/utils/requestNavigationHandlers'; import { event } from '@/analytics/event'; import { getOnchainAssetBalance } from '@/handlers/assets'; import { performanceTracking, Screens, TimeToSignOperation } from '@/state/performance/performance'; -import useSwitchWallet from '@/hooks/useSwitchWallet'; const COLLAPSED_CARD_HEIGHT = 56; const MAX_CARD_HEIGHT = 176; diff --git a/src/screens/points/components/LeaderboardRow.tsx b/src/screens/points/components/LeaderboardRow.tsx index c5ee4583f3f..54fe8b6a0eb 100644 --- a/src/screens/points/components/LeaderboardRow.tsx +++ b/src/screens/points/components/LeaderboardRow.tsx @@ -3,7 +3,7 @@ import React, { memo, useCallback, useMemo } from 'react'; import { Keyboard, Share } from 'react-native'; import { MenuActionConfig } from 'react-native-ios-context-menu'; import ContextMenuButton from '@/components/native-context-menu/contextMenu'; -import { useClipboard, useContacts, useWallets, useWatchWallet } from '@/hooks'; +import { useClipboard, useContacts, useSwitchWallet, useWallets, useWatchWallet } from '@/hooks'; import { useNavigation } from '@/navigation'; import { RAINBOW_PROFILES_BASE_URL } from '@/references'; import Routes from '@/navigation/routesNames'; @@ -20,7 +20,6 @@ import { useTheme } from '@/theme'; import LinearGradient from 'react-native-linear-gradient'; import { ButtonPressAnimation } from '@/components/animations'; import { noop } from 'lodash'; -import useSwitchWallet from '@/hooks/useSwitchWallet'; const ACTIONS = { ADD_CONTACT: 'add-contact', From 8061f7a3425f5025c67ed9cab50a974cb67fa804 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Thu, 8 Aug 2024 15:11:56 -0600 Subject: [PATCH 20/36] remove unused withPositions params --- src/hooks/useWalletBalances.ts | 39 ++++++++------------- src/hooks/useWalletsWithBalancesAndNames.ts | 4 +-- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/hooks/useWalletBalances.ts b/src/hooks/useWalletBalances.ts index b65cd756d9b..a0a9b722205 100644 --- a/src/hooks/useWalletBalances.ts +++ b/src/hooks/useWalletBalances.ts @@ -25,7 +25,7 @@ type WalletBalanceResult = { isLoading: boolean; }; -const useWalletBalances = (wallets: AllRainbowWallets, withPositions: T = true as T): WalletBalanceResult => { +const useWalletBalances = (wallets: AllRainbowWallets): WalletBalanceResult => { const { nativeCurrency } = useAccountSettings(); const allAddresses = useMemo( @@ -42,7 +42,7 @@ const useWalletBalances = (wallets: AllRainbowWallets, queries: allAddresses.map(address => ({ queryKey: positionsQueryKey({ address, currency: nativeCurrency }), queryFn: () => fetchPositions({ address, currency: nativeCurrency }), - enabled: !!address && (withPositions as boolean), + enabled: !!address, })), }); @@ -53,33 +53,22 @@ const useWalletBalances = (wallets: AllRainbowWallets, const lowerCaseAddress = address.toLowerCase() as Address; const assetBalance = summaryData?.data?.addresses?.[lowerCaseAddress]?.summary?.asset_value || 0; - if (!withPositions) { - result[lowerCaseAddress] = { - assetBalanceAmount: assetBalance, - assetBalanceDisplay: convertAmountToNativeDisplay(assetBalance, nativeCurrency), - totalBalanceAmount: assetBalance, - totalBalanceDisplay: convertAmountToNativeDisplay(assetBalance, nativeCurrency), - }; - } else { - const positionData = queryClient.getQueryData( - positionsQueryKey({ address, currency: nativeCurrency }) - ); - const positionsBalance = positionData?.totals?.total?.amount || '0'; - const totalAccountBalance = add(assetBalance, positionsBalance); + const positionData = queryClient.getQueryData(positionsQueryKey({ address, currency: nativeCurrency })); + const positionsBalance = positionData?.totals?.total?.amount || '0'; + const totalAccountBalance = add(assetBalance, positionsBalance); - result[lowerCaseAddress] = { - assetBalanceAmount: assetBalance, - assetBalanceDisplay: convertAmountToNativeDisplay(assetBalance, nativeCurrency), - positionsBalanceAmount: positionsBalance, - positionsBalanceDisplay: convertAmountToNativeDisplay(positionsBalance, nativeCurrency), - totalBalanceAmount: totalAccountBalance, - totalBalanceDisplay: convertAmountToNativeDisplay(totalAccountBalance, nativeCurrency), - }; - } + result[lowerCaseAddress] = { + assetBalanceAmount: assetBalance, + assetBalanceDisplay: convertAmountToNativeDisplay(assetBalance, nativeCurrency), + positionsBalanceAmount: positionsBalance, + positionsBalanceDisplay: convertAmountToNativeDisplay(positionsBalance, nativeCurrency), + totalBalanceAmount: totalAccountBalance, + totalBalanceDisplay: convertAmountToNativeDisplay(totalAccountBalance, nativeCurrency), + }; } return result; - }, [allAddresses, summaryData, withPositions, nativeCurrency]); + }, [allAddresses, summaryData, nativeCurrency]); const isLoading = isSummaryLoading || positionQueries.some(query => query.isLoading); diff --git a/src/hooks/useWalletsWithBalancesAndNames.ts b/src/hooks/useWalletsWithBalancesAndNames.ts index 04e382eddcd..98395ceac60 100644 --- a/src/hooks/useWalletsWithBalancesAndNames.ts +++ b/src/hooks/useWalletsWithBalancesAndNames.ts @@ -4,9 +4,9 @@ import useWalletBalances from './useWalletBalances'; import useWallets from './useWallets'; import { Address } from 'viem'; -export default function useWalletsWithBalancesAndNames(withPositions = true) { +export default function useWalletsWithBalancesAndNames() { const { walletNames, wallets } = useWallets(); - const walletBalances = useWalletBalances(wallets || {}, withPositions); + const walletBalances = useWalletBalances(wallets || {}); const walletsWithBalancesAndNames = useMemo( () => From 2aa197b217d08dc4493de3591bab13b47e71153e Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Thu, 8 Aug 2024 15:14:29 -0600 Subject: [PATCH 21/36] type --- src/helpers/buildWalletSections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/buildWalletSections.tsx b/src/helpers/buildWalletSections.tsx index 52a081be842..d1bd9d23f96 100644 --- a/src/helpers/buildWalletSections.tsx +++ b/src/helpers/buildWalletSections.tsx @@ -105,7 +105,7 @@ const withPositionsSection = (isLoadingUserAssets: boolean) => { const withBriefBalanceSection = ( sortedAssets: ParsedAddressAsset[], isLoadingUserAssets: boolean, - accountBalance: number | undefined, + accountBalance: string | undefined, nativeCurrency: NativeCurrencyKey, isCoinListEdited: boolean, pinnedCoins: any, From f9bf7abd047aedf53c0f2405485bd9fc5cfe2a6b Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Thu, 8 Aug 2024 16:24:58 -0700 Subject: [PATCH 22/36] fix PROFILE_STICKY_HEADER loading value --- .../asset-list/RecyclerAssetList2/core/ViewTypes.ts | 2 +- src/helpers/buildWalletSections.tsx | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/asset-list/RecyclerAssetList2/core/ViewTypes.ts b/src/components/asset-list/RecyclerAssetList2/core/ViewTypes.ts index 697d5aca3ca..d44099bbb61 100644 --- a/src/components/asset-list/RecyclerAssetList2/core/ViewTypes.ts +++ b/src/components/asset-list/RecyclerAssetList2/core/ViewTypes.ts @@ -56,7 +56,7 @@ export type AssetListHeaderExtraData = { export type AssetsHeaderExtraData = { type: CellType.PROFILE_STICKY_HEADER; value: string; - isLoadingUserAssets: boolean; + isLoadingBalance: boolean; }; export type CoinExtraData = { type: CellType.COIN; uniqueId: string }; export type NFTExtraData = { diff --git a/src/helpers/buildWalletSections.tsx b/src/helpers/buildWalletSections.tsx index d1bd9d23f96..a4431817ac7 100644 --- a/src/helpers/buildWalletSections.tsx +++ b/src/helpers/buildWalletSections.tsx @@ -42,6 +42,7 @@ const accountBalanceSelector = (state: any) => state.accountBalance; const hiddenCoinsSelector = (state: any) => state.hiddenCoins; const isCoinListEditedSelector = (state: any) => state.isCoinListEdited; const isLoadingUserAssetsSelector = (state: any) => state.isLoadingUserAssets; +const isLoadingBalanceSelector = (state: any) => state.isLoadingBalance; const isReadOnlyWalletSelector = (state: any) => state.isReadOnlyWallet; const nativeCurrencySelector = (state: any) => state.nativeCurrency; const pinnedCoinsSelector = (state: any) => state.pinnedCoins; @@ -105,6 +106,7 @@ const withPositionsSection = (isLoadingUserAssets: boolean) => { const withBriefBalanceSection = ( sortedAssets: ParsedAddressAsset[], isLoadingUserAssets: boolean, + isLoadingBalance: boolean, accountBalance: string | undefined, nativeCurrency: NativeCurrencyKey, isCoinListEdited: boolean, @@ -125,7 +127,7 @@ const withBriefBalanceSection = ( type: 'PROFILE_STICKY_HEADER', uid: 'assets-profile-header-compact', value: accountBalance, - isLoadingUserAssets, + isLoadingBalance, }, { type: 'PROFILE_AVATAR_ROW_SPACE_BEFORE', @@ -217,6 +219,7 @@ const briefBalanceSectionSelector = createSelector( [ sortedAssetsSelector, isLoadingUserAssetsSelector, + isLoadingBalanceSelector, accountBalanceSelector, nativeCurrencySelector, isCoinListEditedSelector, From 5e81f25e8bf529725583a74e628ce68fe6b7c3ab Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Thu, 8 Aug 2024 16:27:00 -0700 Subject: [PATCH 23/36] fix --- .../asset-list/RecyclerAssetList2/core/RowRenderer.tsx | 2 +- .../RecyclerAssetList2/profile-header/ProfileBalanceRow.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/asset-list/RecyclerAssetList2/core/RowRenderer.tsx b/src/components/asset-list/RecyclerAssetList2/core/RowRenderer.tsx index 853fbe1cd9c..afbe410d580 100644 --- a/src/components/asset-list/RecyclerAssetList2/core/RowRenderer.tsx +++ b/src/components/asset-list/RecyclerAssetList2/core/RowRenderer.tsx @@ -111,7 +111,7 @@ function rowRenderer(type: CellType, { uid }: { uid: string }, _: unknown, exten ); diff --git a/src/components/asset-list/RecyclerAssetList2/profile-header/ProfileBalanceRow.tsx b/src/components/asset-list/RecyclerAssetList2/profile-header/ProfileBalanceRow.tsx index 9e219feb0fd..e84cc3d5f72 100644 --- a/src/components/asset-list/RecyclerAssetList2/profile-header/ProfileBalanceRow.tsx +++ b/src/components/asset-list/RecyclerAssetList2/profile-header/ProfileBalanceRow.tsx @@ -4,13 +4,13 @@ import { Box, Heading } from '@/design-system'; export const ProfileBalanceRowHeight = 24; -export function ProfileBalanceRow({ totalValue, isLoadingUserAssets }: { totalValue: string; isLoadingUserAssets: boolean }) { +export function ProfileBalanceRow({ totalValue, isLoadingBalance }: { totalValue: string; isLoadingBalance: boolean }) { const placeholderHeight = ProfileBalanceRowHeight; const placeholderWidth = 200; return ( <> - {isLoadingUserAssets ? ( + {isLoadingBalance ? ( From fc1095834ec799c838a2c06d25593050a7a6f154 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Fri, 9 Aug 2024 11:02:47 -0700 Subject: [PATCH 24/36] optional chaining --- src/hooks/useWallets.ts | 2 +- src/hooks/useWalletsWithBalancesAndNames.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/useWallets.ts b/src/hooks/useWallets.ts index 5b1faf84d7b..8b73d9a6045 100644 --- a/src/hooks/useWallets.ts +++ b/src/hooks/useWallets.ts @@ -1,4 +1,4 @@ -import { useEffect, useMemo } from 'react'; +import { useEffect } from 'react'; import { useSelector } from 'react-redux'; import { createSelector } from 'reselect'; import WalletTypes from '@/helpers/walletTypes'; diff --git a/src/hooks/useWalletsWithBalancesAndNames.ts b/src/hooks/useWalletsWithBalancesAndNames.ts index 98395ceac60..2cfbded466b 100644 --- a/src/hooks/useWalletsWithBalancesAndNames.ts +++ b/src/hooks/useWalletsWithBalancesAndNames.ts @@ -13,7 +13,7 @@ export default function useWalletsWithBalancesAndNames() { mapValues(wallets, wallet => { const updatedAccounts = (wallet.addresses ?? []).map(account => ({ ...account, - balance: walletBalances.balances[account.address.toLowerCase() as Address].totalBalanceDisplay, + balance: walletBalances.balances[account.address.toLowerCase() as Address]?.totalBalanceDisplay, ens: walletNames[account.address], })); return { ...wallet, addresses: updatedAccounts }; From b0eb61bcd3e681a7289865ab8251a6ab4b6736af Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Fri, 9 Aug 2024 12:18:04 -0700 Subject: [PATCH 25/36] fixes to buildWalletSections + related code --- .../asset-list/RecyclerAssetList2/core/ViewTypes.ts | 2 +- src/helpers/buildWalletSections.tsx | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/asset-list/RecyclerAssetList2/core/ViewTypes.ts b/src/components/asset-list/RecyclerAssetList2/core/ViewTypes.ts index d44099bbb61..ab6df6115e6 100644 --- a/src/components/asset-list/RecyclerAssetList2/core/ViewTypes.ts +++ b/src/components/asset-list/RecyclerAssetList2/core/ViewTypes.ts @@ -54,7 +54,7 @@ export type AssetListHeaderExtraData = { }; export type AssetsHeaderExtraData = { - type: CellType.PROFILE_STICKY_HEADER; + type: CellType.PROFILE_BALANCE_ROW; value: string; isLoadingBalance: boolean; }; diff --git a/src/helpers/buildWalletSections.tsx b/src/helpers/buildWalletSections.tsx index a4431817ac7..c3e21b257b8 100644 --- a/src/helpers/buildWalletSections.tsx +++ b/src/helpers/buildWalletSections.tsx @@ -121,13 +121,11 @@ const withBriefBalanceSection = ( const isEmpty = !hasTokens && !hasNFTs; const hasNFTsOnly = !hasTokens && hasNFTs; - + console.log(accountBalance); const header = [ { type: 'PROFILE_STICKY_HEADER', uid: 'assets-profile-header-compact', - value: accountBalance, - isLoadingBalance, }, { type: 'PROFILE_AVATAR_ROW_SPACE_BEFORE', @@ -149,13 +147,14 @@ const withBriefBalanceSection = ( type: 'PROFILE_NAME_ROW_SPACE_AFTER', uid: 'profile-name-space-after', }, - ...(!hasTokens && !isLoadingUserAssets + ...(!hasTokens && !isLoadingUserAssets && !isLoadingBalance ? [] : [ { type: 'PROFILE_BALANCE_ROW', uid: 'profile-balance', value: accountBalance, + isLoadingBalance, }, { type: 'PROFILE_BALANCE_ROW_SPACE_AFTER', From 943117b4d23cebf1bda0e0a15b45cd2d0bd8774d Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Fri, 9 Aug 2024 12:34:13 -0700 Subject: [PATCH 26/36] fix accountInfo isLoadingAccountBalance --- src/components/DappBrowser/control-panel/ControlPanel.tsx | 8 +++----- src/hooks/useUserAccounts.ts | 2 +- src/hooks/useWalletSectionsData.ts | 6 +++--- src/hooks/useWalletsWithBalancesAndNames.ts | 8 ++++---- src/screens/ChangeWalletSheet.tsx | 2 +- src/screens/Diagnostics/index.tsx | 2 +- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/components/DappBrowser/control-panel/ControlPanel.tsx b/src/components/DappBrowser/control-panel/ControlPanel.tsx index 54527d30c62..a661529dbd7 100644 --- a/src/components/DappBrowser/control-panel/ControlPanel.tsx +++ b/src/components/DappBrowser/control-panel/ControlPanel.tsx @@ -43,9 +43,8 @@ import { RouteProp, useRoute } from '@react-navigation/native'; import { toHex } from 'viem'; import { RainbowNetworks } from '@/networks'; import * as i18n from '@/languages'; -import { convertAmountToNativeDisplay } from '@/helpers/utilities'; -import { useDispatch, useSelector } from 'react-redux'; -import store, { AppState } from '@/redux/store'; +import { useDispatch } from 'react-redux'; +import store from '@/redux/store'; import { getDappHost } from '@/utils/connectedApps'; import WebView from 'react-native-webview'; import { Navigation, useNavigation } from '@/navigation'; @@ -88,8 +87,7 @@ export const ControlPanel = () => { const { params: { activeTabRef }, } = useRoute>(); - const nativeCurrency = useSelector((state: AppState) => state.settings.nativeCurrency); - const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); + const { walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); const activeTabUrl = useBrowserStore(state => state.getActiveTabUrl()); const activeTabHost = getDappHost(activeTabUrl || '') || DEFAULT_TAB_URL; const updateActiveSessionNetwork = useAppSessionsStore(state => state.updateActiveSessionNetwork); diff --git a/src/hooks/useUserAccounts.ts b/src/hooks/useUserAccounts.ts index 3c999e3e1d5..bfcd724e3bf 100644 --- a/src/hooks/useUserAccounts.ts +++ b/src/hooks/useUserAccounts.ts @@ -8,7 +8,7 @@ import { RainbowAccount } from '@/model/wallet'; import { Network } from '@/helpers'; export default function useUserAccounts() { - const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); + const { walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); const network = useSelector((state: AppState) => state.settings.network); const userAccounts = useMemo(() => { diff --git a/src/hooks/useWalletSectionsData.ts b/src/hooks/useWalletSectionsData.ts index 82d5ae0b038..6154960d288 100644 --- a/src/hooks/useWalletSectionsData.ts +++ b/src/hooks/useWalletSectionsData.ts @@ -30,7 +30,7 @@ export default function useWalletSectionsData({ address: accountAddress, }); - const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); + const { isLoading: isLoadingWalletBalances, walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); const accountWithBalance = walletsWithBalancesAndNames[selectedWallet.id]?.addresses.find( address => address.address.toLowerCase() === accountAddress.toLowerCase() @@ -57,7 +57,7 @@ export default function useWalletSectionsData({ sendableUniqueTokens, sortedAssets, accountBalance: accountWithBalance?.balance, - isLoadingBalance: !accountWithBalance, + isLoadingBalance: isLoadingWalletBalances, // @ts-expect-error ts-migrate(2698) FIXME: Spread types may only be created from object types... Remove this comment to see the full error message ...isWalletEthZero, hiddenTokens, @@ -74,7 +74,7 @@ export default function useWalletSectionsData({ return { hasNFTs, isEmpty, - isLoadingBalance: !accountWithBalance, + isLoadingBalance: isLoadingWalletBalances, isLoadingUserAssets, isWalletEthZero, briefSectionsData, diff --git a/src/hooks/useWalletsWithBalancesAndNames.ts b/src/hooks/useWalletsWithBalancesAndNames.ts index 2cfbded466b..80072fe4856 100644 --- a/src/hooks/useWalletsWithBalancesAndNames.ts +++ b/src/hooks/useWalletsWithBalancesAndNames.ts @@ -6,20 +6,20 @@ import { Address } from 'viem'; export default function useWalletsWithBalancesAndNames() { const { walletNames, wallets } = useWallets(); - const walletBalances = useWalletBalances(wallets || {}); + const { balances, isLoading } = useWalletBalances(wallets || {}); const walletsWithBalancesAndNames = useMemo( () => mapValues(wallets, wallet => { const updatedAccounts = (wallet.addresses ?? []).map(account => ({ ...account, - balance: walletBalances.balances[account.address.toLowerCase() as Address]?.totalBalanceDisplay, + balance: balances[account.address.toLowerCase() as Address]?.totalBalanceDisplay, ens: walletNames[account.address], })); return { ...wallet, addresses: updatedAccounts }; }), - [walletBalances, walletNames, wallets] + [balances, walletNames, wallets] ); - return walletsWithBalancesAndNames; + return { isLoading, walletsWithBalancesAndNames }; } diff --git a/src/screens/ChangeWalletSheet.tsx b/src/screens/ChangeWalletSheet.tsx index f345079b3e3..6b544f02a8f 100644 --- a/src/screens/ChangeWalletSheet.tsx +++ b/src/screens/ChangeWalletSheet.tsx @@ -109,7 +109,7 @@ export default function ChangeWalletSheet() { const { goBack, navigate } = useNavigation(); const dispatch = useDispatch(); const initializeWallet = useInitializeWallet(); - const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); + const { walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); const [editMode, setEditMode] = useState(false); const [currentAddress, setCurrentAddress] = useState(currentAccountAddress || accountAddress); diff --git a/src/screens/Diagnostics/index.tsx b/src/screens/Diagnostics/index.tsx index cdbbf4bd044..00ebc3bd42d 100644 --- a/src/screens/Diagnostics/index.tsx +++ b/src/screens/Diagnostics/index.tsx @@ -33,7 +33,7 @@ export const WalletDiagnosticsSheet = () => { const [toastVisible, setToastVisible] = useState(false); const toastTimeout = useRef(); - const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); + const { walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); useEffect(() => { const init = async () => { From 7a11e756019d2db3dc16e849841ec252db0596f4 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Fri, 9 Aug 2024 12:41:39 -0700 Subject: [PATCH 27/36] clean up useWalletBalances --- src/hooks/useWalletBalances.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/hooks/useWalletBalances.ts b/src/hooks/useWalletBalances.ts index a0a9b722205..6d2cbc95c6b 100644 --- a/src/hooks/useWalletBalances.ts +++ b/src/hooks/useWalletBalances.ts @@ -9,7 +9,7 @@ import { RainbowPositions } from '@/resources/defi/types'; import { add, convertAmountToNativeDisplay } from '@/helpers/utilities'; import { queryClient } from '@/react-query'; -type WalletBalanceWithPositions = { +type WalletBalance = { assetBalanceAmount: number; assetBalanceDisplay: string; positionsBalanceAmount: string | number; @@ -18,14 +18,12 @@ type WalletBalanceWithPositions = { totalBalanceDisplay: string; }; -type WalletBalanceWithoutPositions = Omit; - -type WalletBalanceResult = { - balances: Record; +type WalletBalanceResult = { + balances: Record; isLoading: boolean; }; -const useWalletBalances = (wallets: AllRainbowWallets): WalletBalanceResult => { +const useWalletBalances = (wallets: AllRainbowWallets): WalletBalanceResult => { const { nativeCurrency } = useAccountSettings(); const allAddresses = useMemo( @@ -46,8 +44,8 @@ const useWalletBalances = (wallets: AllRainbowWallets) })), }); - const balancesWithPositions = useMemo(() => { - const result: Record = {}; + const balances = useMemo(() => { + const result: Record = {}; for (const address of allAddresses) { const lowerCaseAddress = address.toLowerCase() as Address; @@ -73,7 +71,7 @@ const useWalletBalances = (wallets: AllRainbowWallets) const isLoading = isSummaryLoading || positionQueries.some(query => query.isLoading); return { - balances: balancesWithPositions as WalletBalanceResult['balances'], + balances, isLoading, }; }; From 38e9eb57b09cf2ad1d2d158e3fb95913c47f4bd1 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Fri, 9 Aug 2024 13:33:48 -0700 Subject: [PATCH 28/36] stuff is still broken but committing walletsWithBalancesAndNames fix --- src/hooks/useWalletBalances.ts | 6 ++++-- src/hooks/useWalletSectionsData.ts | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/hooks/useWalletBalances.ts b/src/hooks/useWalletBalances.ts index 6d2cbc95c6b..6e50c6f30b2 100644 --- a/src/hooks/useWalletBalances.ts +++ b/src/hooks/useWalletBalances.ts @@ -44,9 +44,13 @@ const useWalletBalances = (wallets: AllRainbowWallets): WalletBalanceResult => { })), }); + const isLoading = isSummaryLoading || positionQueries.some(query => query.isLoading); + const balances = useMemo(() => { const result: Record = {}; + if (isLoading) return result; + for (const address of allAddresses) { const lowerCaseAddress = address.toLowerCase() as Address; const assetBalance = summaryData?.data?.addresses?.[lowerCaseAddress]?.summary?.asset_value || 0; @@ -68,8 +72,6 @@ const useWalletBalances = (wallets: AllRainbowWallets): WalletBalanceResult => { return result; }, [allAddresses, summaryData, nativeCurrency]); - const isLoading = isSummaryLoading || positionQueries.some(query => query.isLoading); - return { balances, isLoading, diff --git a/src/hooks/useWalletSectionsData.ts b/src/hooks/useWalletSectionsData.ts index 6154960d288..257a157f9e4 100644 --- a/src/hooks/useWalletSectionsData.ts +++ b/src/hooks/useWalletSectionsData.ts @@ -35,7 +35,7 @@ export default function useWalletSectionsData({ const accountWithBalance = walletsWithBalancesAndNames[selectedWallet.id]?.addresses.find( address => address.address.toLowerCase() === accountAddress.toLowerCase() ); - + console.log(accountWithBalance); const { showcaseTokens } = useShowcaseTokens(); const { hiddenTokens } = useHiddenTokens(); @@ -57,7 +57,7 @@ export default function useWalletSectionsData({ sendableUniqueTokens, sortedAssets, accountBalance: accountWithBalance?.balance, - isLoadingBalance: isLoadingWalletBalances, + isLoadingBalance: !accountWithBalance, // @ts-expect-error ts-migrate(2698) FIXME: Spread types may only be created from object types... Remove this comment to see the full error message ...isWalletEthZero, hiddenTokens, @@ -74,7 +74,7 @@ export default function useWalletSectionsData({ return { hasNFTs, isEmpty, - isLoadingBalance: isLoadingWalletBalances, + isLoadingBalance: !accountWithBalance, isLoadingUserAssets, isWalletEthZero, briefSectionsData, From 335bb0d79d1b45a6bfb522fb46ef69ff558acaa7 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Fri, 9 Aug 2024 15:39:15 -0700 Subject: [PATCH 29/36] refactor useWalletsWithBalancesAndNames and fix consumers --- .../DappBrowser/control-panel/ControlPanel.tsx | 11 ++++++----- src/components/change-wallet/AddressRow.tsx | 4 ++-- src/components/contacts/ContactRow.js | 4 ++-- src/helpers/buildWalletSections.tsx | 14 +++++++------- src/hooks/useWalletSectionsData.ts | 2 +- src/hooks/useWalletsWithBalancesAndNames.ts | 2 +- 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/components/DappBrowser/control-panel/ControlPanel.tsx b/src/components/DappBrowser/control-panel/ControlPanel.tsx index a661529dbd7..2d6488bdb22 100644 --- a/src/components/DappBrowser/control-panel/ControlPanel.tsx +++ b/src/components/DappBrowser/control-panel/ControlPanel.tsx @@ -63,6 +63,7 @@ import { getRemoteConfig } from '@/model/remoteConfig'; import { SWAPS_V2, useExperimentalFlag } from '@/config'; import { swapsStore } from '@/state/swaps/swapsStore'; import { userAssetsStore } from '@/state/assets/userAssets'; +import { greaterThan } from '@/helpers/utilities'; const PAGES = { HOME: 'home', @@ -138,7 +139,7 @@ export const ControlPanel = () => { const bluetoothWallets: ControlPanelMenuItemProps[] = []; const readOnlyWallets: ControlPanelMenuItemProps[] = []; - const accountBalances: Record = {}; + const accountBalances: Record = {}; Object.values(walletsWithBalancesAndNames).forEach(wallet => { wallet.addresses @@ -154,14 +155,14 @@ export const ControlPanel = () => { secondaryLabel: wallet.type === WalletTypes.readOnly ? i18n.t(i18n.l.wallet.change_wallet.watching) - : account.balance ?? i18n.t(i18n.l.wallet.change_wallet.no_balance), + : account.balances.totalBalanceDisplay ?? i18n.t(i18n.l.wallet.change_wallet.no_balance), uniqueId: account.address, color: colors.avatarBackgrounds[account.color], imageUrl: account.image || undefined, selected: account.address === currentAddress, }; - accountBalances[account.address] = Number(account.balance); + accountBalances[account.address] = account.balances.totalBalanceAmount; if ([WalletTypes.mnemonic, WalletTypes.seed, WalletTypes.privateKey].includes(wallet.type)) { sortedWallets.push(item); @@ -173,8 +174,8 @@ export const ControlPanel = () => { }); }); - sortedWallets.sort((a, b) => accountBalances[b.uniqueId] - accountBalances[a.uniqueId]); - bluetoothWallets.sort((a, b) => accountBalances[b.uniqueId] - accountBalances[a.uniqueId]); + sortedWallets.sort((a, b) => (greaterThan(accountBalances[b.uniqueId], accountBalances[a.uniqueId]) ? 1 : -1)); + bluetoothWallets.sort((a, b) => (greaterThan(accountBalances[b.uniqueId], accountBalances[a.uniqueId]) ? 1 : -1)); const sortedItems = [...sortedWallets, ...bluetoothWallets, ...readOnlyWallets]; diff --git a/src/components/change-wallet/AddressRow.tsx b/src/components/change-wallet/AddressRow.tsx index 07e6e76da6c..8985151edf0 100644 --- a/src/components/change-wallet/AddressRow.tsx +++ b/src/components/change-wallet/AddressRow.tsx @@ -120,13 +120,13 @@ interface AddressRowProps { export default function AddressRow({ contextMenuActions, data, editMode, onPress }: AddressRowProps) { const notificationsEnabled = useExperimentalFlag(NOTIFICATIONS); - const { address, balance, color: accountColor, ens, image: accountImage, isSelected, isReadOnly, isLedger, label, walletId } = data; + const { address, balances, color: accountColor, ens, image: accountImage, isSelected, isReadOnly, isLedger, label, walletId } = data; const { colors, isDarkMode } = useTheme(); const labelQuaternary = useForegroundColor('labelQuaternary'); - const balanceOrNoBalance = balance || lang.t('wallet.change_wallet.no_balance'); + const balanceOrNoBalance = balances?.totalBalanceDisplay || lang.t('wallet.change_wallet.no_balance'); const cleanedUpLabel = useMemo(() => removeFirstEmojiFromString(label), [label]); diff --git a/src/components/contacts/ContactRow.js b/src/components/contacts/ContactRow.js index 46883366f58..afa222d1050 100644 --- a/src/components/contacts/ContactRow.js +++ b/src/components/contacts/ContactRow.js @@ -58,9 +58,9 @@ const ContactRow = ({ address, color, nickname, symmetricalMargins, ...props }, const { width: deviceWidth } = useDimensions(); const { onAddOrUpdateContacts } = useContacts(); const { colors } = useTheme(); - const { accountType, balance, ens, image, label, network, onPress, showcaseItem, testID } = props; + const { accountType, balances, ens, image, label, network, onPress, showcaseItem, testID } = props; - const cleanedUpBalance = balance || i18n.t(i18n.l.wallet.change_wallet.no_balance); + const cleanedUpBalance = balances?.totalBalanceDisplay || i18n.t(i18n.l.wallet.change_wallet.no_balance); // show avatar for contact rows that are accounts, not contacts const avatar = accountType !== 'contacts' ? returnStringFirstEmoji(label) || profileUtils.addressHashedEmoji(address) : null; diff --git a/src/helpers/buildWalletSections.tsx b/src/helpers/buildWalletSections.tsx index c3e21b257b8..255add920b8 100644 --- a/src/helpers/buildWalletSections.tsx +++ b/src/helpers/buildWalletSections.tsx @@ -38,7 +38,7 @@ const EMPTY_WALLET_CONTENT = [ const ONLY_NFTS_CONTENT = [{ type: 'ETH_CARD', uid: 'eth-card' }]; const sortedAssetsSelector = (state: any) => state.sortedAssets; -const accountBalanceSelector = (state: any) => state.accountBalance; +const accountBalanceDisplaySelector = (state: any) => state.accountBalanceDisplay; const hiddenCoinsSelector = (state: any) => state.hiddenCoins; const isCoinListEditedSelector = (state: any) => state.isCoinListEdited; const isLoadingUserAssetsSelector = (state: any) => state.isLoadingUserAssets; @@ -107,7 +107,7 @@ const withBriefBalanceSection = ( sortedAssets: ParsedAddressAsset[], isLoadingUserAssets: boolean, isLoadingBalance: boolean, - accountBalance: string | undefined, + accountBalanceDisplay: string | undefined, nativeCurrency: NativeCurrencyKey, isCoinListEdited: boolean, pinnedCoins: any, @@ -121,7 +121,7 @@ const withBriefBalanceSection = ( const isEmpty = !hasTokens && !hasNFTs; const hasNFTsOnly = !hasTokens && hasNFTs; - console.log(accountBalance); + const header = [ { type: 'PROFILE_STICKY_HEADER', @@ -153,7 +153,7 @@ const withBriefBalanceSection = ( { type: 'PROFILE_BALANCE_ROW', uid: 'profile-balance', - value: accountBalance, + value: accountBalanceDisplay, isLoadingBalance, }, { @@ -164,13 +164,13 @@ const withBriefBalanceSection = ( { type: 'PROFILE_ACTION_BUTTONS_ROW', uid: 'profile-action-buttons', - value: accountBalance, + value: accountBalanceDisplay, }, hasTokens ? { type: 'PROFILE_ACTION_BUTTONS_ROW_SPACE_AFTER', uid: 'profile-action-buttons-space-after', - value: accountBalance, + value: accountBalanceDisplay, } : { type: 'BIG_EMPTY_WALLET_SPACER', uid: 'big-empty-wallet-spacer-1' }, ]; @@ -219,7 +219,7 @@ const briefBalanceSectionSelector = createSelector( sortedAssetsSelector, isLoadingUserAssetsSelector, isLoadingBalanceSelector, - accountBalanceSelector, + accountBalanceDisplaySelector, nativeCurrencySelector, isCoinListEditedSelector, pinnedCoinsSelector, diff --git a/src/hooks/useWalletSectionsData.ts b/src/hooks/useWalletSectionsData.ts index 257a157f9e4..1f2e4eae219 100644 --- a/src/hooks/useWalletSectionsData.ts +++ b/src/hooks/useWalletSectionsData.ts @@ -56,7 +56,7 @@ export default function useWalletSectionsData({ pinnedCoins, sendableUniqueTokens, sortedAssets, - accountBalance: accountWithBalance?.balance, + accountBalanceDisplay: accountWithBalance?.balances.totalBalanceDisplay, isLoadingBalance: !accountWithBalance, // @ts-expect-error ts-migrate(2698) FIXME: Spread types may only be created from object types... Remove this comment to see the full error message ...isWalletEthZero, diff --git a/src/hooks/useWalletsWithBalancesAndNames.ts b/src/hooks/useWalletsWithBalancesAndNames.ts index 80072fe4856..d65d3ad35ff 100644 --- a/src/hooks/useWalletsWithBalancesAndNames.ts +++ b/src/hooks/useWalletsWithBalancesAndNames.ts @@ -13,7 +13,7 @@ export default function useWalletsWithBalancesAndNames() { mapValues(wallets, wallet => { const updatedAccounts = (wallet.addresses ?? []).map(account => ({ ...account, - balance: balances[account.address.toLowerCase() as Address]?.totalBalanceDisplay, + balances: balances[account.address.toLowerCase() as Address], ens: walletNames[account.address], })); return { ...wallet, addresses: updatedAccounts }; From 04069bab5c18c4aa0951389925ffd171f83f790c Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Fri, 9 Aug 2024 16:36:43 -0700 Subject: [PATCH 30/36] fix wallet screen balance loading state --- src/components/DappBrowser/control-panel/ControlPanel.tsx | 6 +++--- src/hooks/useUserAccounts.ts | 2 +- src/hooks/useWalletSectionsData.ts | 8 ++++---- src/hooks/useWalletsWithBalancesAndNames.ts | 4 ++-- src/screens/ChangeWalletSheet.tsx | 2 +- src/screens/Diagnostics/index.tsx | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/components/DappBrowser/control-panel/ControlPanel.tsx b/src/components/DappBrowser/control-panel/ControlPanel.tsx index 2d6488bdb22..267658cffd5 100644 --- a/src/components/DappBrowser/control-panel/ControlPanel.tsx +++ b/src/components/DappBrowser/control-panel/ControlPanel.tsx @@ -88,7 +88,7 @@ export const ControlPanel = () => { const { params: { activeTabRef }, } = useRoute>(); - const { walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); + const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); const activeTabUrl = useBrowserStore(state => state.getActiveTabUrl()); const activeTabHost = getDappHost(activeTabUrl || '') || DEFAULT_TAB_URL; const updateActiveSessionNetwork = useAppSessionsStore(state => state.updateActiveSessionNetwork); @@ -155,14 +155,14 @@ export const ControlPanel = () => { secondaryLabel: wallet.type === WalletTypes.readOnly ? i18n.t(i18n.l.wallet.change_wallet.watching) - : account.balances.totalBalanceDisplay ?? i18n.t(i18n.l.wallet.change_wallet.no_balance), + : account.balances?.totalBalanceDisplay ?? i18n.t(i18n.l.wallet.change_wallet.no_balance), uniqueId: account.address, color: colors.avatarBackgrounds[account.color], imageUrl: account.image || undefined, selected: account.address === currentAddress, }; - accountBalances[account.address] = account.balances.totalBalanceAmount; + accountBalances[account.address] = account.balances?.totalBalanceAmount; if ([WalletTypes.mnemonic, WalletTypes.seed, WalletTypes.privateKey].includes(wallet.type)) { sortedWallets.push(item); diff --git a/src/hooks/useUserAccounts.ts b/src/hooks/useUserAccounts.ts index bfcd724e3bf..3c999e3e1d5 100644 --- a/src/hooks/useUserAccounts.ts +++ b/src/hooks/useUserAccounts.ts @@ -8,7 +8,7 @@ import { RainbowAccount } from '@/model/wallet'; import { Network } from '@/helpers'; export default function useUserAccounts() { - const { walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); + const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); const network = useSelector((state: AppState) => state.settings.network); const userAccounts = useMemo(() => { diff --git a/src/hooks/useWalletSectionsData.ts b/src/hooks/useWalletSectionsData.ts index 1f2e4eae219..59576b7eae6 100644 --- a/src/hooks/useWalletSectionsData.ts +++ b/src/hooks/useWalletSectionsData.ts @@ -30,7 +30,7 @@ export default function useWalletSectionsData({ address: accountAddress, }); - const { isLoading: isLoadingWalletBalances, walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); + const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); const accountWithBalance = walletsWithBalancesAndNames[selectedWallet.id]?.addresses.find( address => address.address.toLowerCase() === accountAddress.toLowerCase() @@ -56,8 +56,8 @@ export default function useWalletSectionsData({ pinnedCoins, sendableUniqueTokens, sortedAssets, - accountBalanceDisplay: accountWithBalance?.balances.totalBalanceDisplay, - isLoadingBalance: !accountWithBalance, + accountBalanceDisplay: accountWithBalance?.balances?.totalBalanceDisplay, + isLoadingBalance: !accountWithBalance?.balances, // @ts-expect-error ts-migrate(2698) FIXME: Spread types may only be created from object types... Remove this comment to see the full error message ...isWalletEthZero, hiddenTokens, @@ -74,7 +74,7 @@ export default function useWalletSectionsData({ return { hasNFTs, isEmpty, - isLoadingBalance: !accountWithBalance, + isLoadingBalance: !accountWithBalance?.balances, isLoadingUserAssets, isWalletEthZero, briefSectionsData, diff --git a/src/hooks/useWalletsWithBalancesAndNames.ts b/src/hooks/useWalletsWithBalancesAndNames.ts index d65d3ad35ff..dcf48245d98 100644 --- a/src/hooks/useWalletsWithBalancesAndNames.ts +++ b/src/hooks/useWalletsWithBalancesAndNames.ts @@ -6,7 +6,7 @@ import { Address } from 'viem'; export default function useWalletsWithBalancesAndNames() { const { walletNames, wallets } = useWallets(); - const { balances, isLoading } = useWalletBalances(wallets || {}); + const { balances } = useWalletBalances(wallets || {}); const walletsWithBalancesAndNames = useMemo( () => @@ -21,5 +21,5 @@ export default function useWalletsWithBalancesAndNames() { [balances, walletNames, wallets] ); - return { isLoading, walletsWithBalancesAndNames }; + return walletsWithBalancesAndNames; } diff --git a/src/screens/ChangeWalletSheet.tsx b/src/screens/ChangeWalletSheet.tsx index 6b544f02a8f..f345079b3e3 100644 --- a/src/screens/ChangeWalletSheet.tsx +++ b/src/screens/ChangeWalletSheet.tsx @@ -109,7 +109,7 @@ export default function ChangeWalletSheet() { const { goBack, navigate } = useNavigation(); const dispatch = useDispatch(); const initializeWallet = useInitializeWallet(); - const { walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); + const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); const [editMode, setEditMode] = useState(false); const [currentAddress, setCurrentAddress] = useState(currentAccountAddress || accountAddress); diff --git a/src/screens/Diagnostics/index.tsx b/src/screens/Diagnostics/index.tsx index 00ebc3bd42d..cdbbf4bd044 100644 --- a/src/screens/Diagnostics/index.tsx +++ b/src/screens/Diagnostics/index.tsx @@ -33,7 +33,7 @@ export const WalletDiagnosticsSheet = () => { const [toastVisible, setToastVisible] = useState(false); const toastTimeout = useRef(); - const { walletsWithBalancesAndNames } = useWalletsWithBalancesAndNames(); + const walletsWithBalancesAndNames = useWalletsWithBalancesAndNames(); useEffect(() => { const init = async () => { From 4240c4e2a9e986894e0137b4406b29b3928b1f9f Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Tue, 13 Aug 2024 07:51:37 -0700 Subject: [PATCH 31/36] console.log --- src/hooks/useWalletSectionsData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useWalletSectionsData.ts b/src/hooks/useWalletSectionsData.ts index 59576b7eae6..7fe57995040 100644 --- a/src/hooks/useWalletSectionsData.ts +++ b/src/hooks/useWalletSectionsData.ts @@ -35,7 +35,7 @@ export default function useWalletSectionsData({ const accountWithBalance = walletsWithBalancesAndNames[selectedWallet.id]?.addresses.find( address => address.address.toLowerCase() === accountAddress.toLowerCase() ); - console.log(accountWithBalance); + const { showcaseTokens } = useShowcaseTokens(); const { hiddenTokens } = useHiddenTokens(); From cbf63dfd53314811b834816ca42fc57f033a7744 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Tue, 13 Aug 2024 08:02:03 -0700 Subject: [PATCH 32/36] switch amount types from string | number -> string --- src/components/DappBrowser/control-panel/ControlPanel.tsx | 2 +- src/hooks/useWalletBalances.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/DappBrowser/control-panel/ControlPanel.tsx b/src/components/DappBrowser/control-panel/ControlPanel.tsx index bafce3bb37d..23476e745ed 100644 --- a/src/components/DappBrowser/control-panel/ControlPanel.tsx +++ b/src/components/DappBrowser/control-panel/ControlPanel.tsx @@ -139,7 +139,7 @@ export const ControlPanel = () => { const bluetoothWallets: ControlPanelMenuItemProps[] = []; const readOnlyWallets: ControlPanelMenuItemProps[] = []; - const accountBalances: Record = {}; + const accountBalances: Record = {}; Object.values(walletsWithBalancesAndNames).forEach(wallet => { wallet.addresses diff --git a/src/hooks/useWalletBalances.ts b/src/hooks/useWalletBalances.ts index 6e50c6f30b2..23bb27b29f4 100644 --- a/src/hooks/useWalletBalances.ts +++ b/src/hooks/useWalletBalances.ts @@ -10,11 +10,11 @@ import { add, convertAmountToNativeDisplay } from '@/helpers/utilities'; import { queryClient } from '@/react-query'; type WalletBalance = { - assetBalanceAmount: number; + assetBalanceAmount: string; assetBalanceDisplay: string; - positionsBalanceAmount: string | number; + positionsBalanceAmount: string; positionsBalanceDisplay: string; - totalBalanceAmount: string | number; + totalBalanceAmount: string; totalBalanceDisplay: string; }; @@ -53,7 +53,7 @@ const useWalletBalances = (wallets: AllRainbowWallets): WalletBalanceResult => { for (const address of allAddresses) { const lowerCaseAddress = address.toLowerCase() as Address; - const assetBalance = summaryData?.data?.addresses?.[lowerCaseAddress]?.summary?.asset_value || 0; + const assetBalance = summaryData?.data?.addresses?.[lowerCaseAddress]?.summary?.asset_value.toString() || '0'; const positionData = queryClient.getQueryData(positionsQueryKey({ address, currency: nativeCurrency })); const positionsBalance = positionData?.totals?.total?.amount || '0'; From e1349b063b7ce7daea5eeb0bd0b24c3e54737e05 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Tue, 13 Aug 2024 09:07:12 -0700 Subject: [PATCH 33/36] align stale/cache times, remove keepPreviousData --- src/hooks/useWalletBalances.ts | 17 +++++++++++++---- src/resources/summary/summary.ts | 1 - 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/hooks/useWalletBalances.ts b/src/hooks/useWalletBalances.ts index 23bb27b29f4..c4c4e818d76 100644 --- a/src/hooks/useWalletBalances.ts +++ b/src/hooks/useWalletBalances.ts @@ -9,6 +9,11 @@ import { RainbowPositions } from '@/resources/defi/types'; import { add, convertAmountToNativeDisplay } from '@/helpers/utilities'; import { queryClient } from '@/react-query'; +const QUERY_CONFIG = { + staleTime: 1000 * 60 * 2, // 2 minutes + cacheTime: 1000 * 60 * 60 * 24, // 24 hours +}; + type WalletBalance = { assetBalanceAmount: string; assetBalanceDisplay: string; @@ -31,16 +36,20 @@ const useWalletBalances = (wallets: AllRainbowWallets): WalletBalanceResult => { [wallets] ); - const { data: summaryData, isLoading: isSummaryLoading } = useAddysSummary({ - addresses: allAddresses, - currency: nativeCurrency, - }); + const { data: summaryData, isLoading: isSummaryLoading } = useAddysSummary( + { + addresses: allAddresses, + currency: nativeCurrency, + }, + QUERY_CONFIG + ); const positionQueries = useQueries({ queries: allAddresses.map(address => ({ queryKey: positionsQueryKey({ address, currency: nativeCurrency }), queryFn: () => fetchPositions({ address, currency: nativeCurrency }), enabled: !!address, + ...QUERY_CONFIG, })), }); diff --git a/src/resources/summary/summary.ts b/src/resources/summary/summary.ts index 344f5c57b63..90705878f46 100644 --- a/src/resources/summary/summary.ts +++ b/src/resources/summary/summary.ts @@ -88,6 +88,5 @@ export function useAddysSummary( ...config, staleTime: 1000 * 60 * 2, // Set data to become stale after 2 minutes cacheTime: 1000 * 60 * 60 * 24, // Keep unused data in cache for 24 hours - keepPreviousData: true, // Use previous data while new data is loading after it becomes stale }); } From 6acff71c9c9dd03446c0d1ea8c90b10b9220f66d Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Tue, 13 Aug 2024 09:15:47 -0700 Subject: [PATCH 34/36] remove spammy isDamaged logging --- src/hooks/useWallets.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/hooks/useWallets.ts b/src/hooks/useWallets.ts index 8b73d9a6045..38363886917 100644 --- a/src/hooks/useWallets.ts +++ b/src/hooks/useWallets.ts @@ -1,10 +1,8 @@ -import { useEffect } from 'react'; import { useSelector } from 'react-redux'; import { createSelector } from 'reselect'; import WalletTypes from '@/helpers/walletTypes'; import { RainbowWallet } from '@/model/wallet'; import { AppState } from '@/redux/store'; -import { logger } from '@/logger'; const walletSelector = createSelector( ({ wallets: { isWalletLoading, selected = {} as RainbowWallet, walletNames, wallets } }: AppState) => ({ @@ -24,16 +22,8 @@ const walletSelector = createSelector( export default function useWallets() { const { isWalletLoading, selectedWallet, walletNames, wallets } = useSelector(walletSelector); - const isDamaged = selectedWallet?.damaged; - - useEffect(() => { - if (isDamaged) { - logger.warn('Wallet is damaged. Check attached metadata.', { selectedWallet, wallets }); - } - }, [isDamaged, selectedWallet, wallets]); - return { - isDamaged, + isDamaged: selectedWallet?.damaged, isReadOnlyWallet: selectedWallet.type === WalletTypes.readOnly, isHardwareWallet: !!selectedWallet.deviceId, isWalletLoading, From 5e06f01acbf824033d2a9b03e649839fc905b283 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Tue, 13 Aug 2024 09:59:11 -0700 Subject: [PATCH 35/36] add loading balance copy + remove incorrectly used no balance copy --- src/components/DappBrowser/control-panel/ControlPanel.tsx | 7 +++---- src/components/change-wallet/AddressRow.tsx | 4 ++-- src/components/contacts/ContactRow.js | 4 ++-- src/languages/en_US.json | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/components/DappBrowser/control-panel/ControlPanel.tsx b/src/components/DappBrowser/control-panel/ControlPanel.tsx index 23476e745ed..a0d844c4fdc 100644 --- a/src/components/DappBrowser/control-panel/ControlPanel.tsx +++ b/src/components/DappBrowser/control-panel/ControlPanel.tsx @@ -145,6 +145,8 @@ export const ControlPanel = () => { wallet.addresses .filter(account => account.visible) .forEach(account => { + const balanceText = account.balances ? account.balances.totalBalanceDisplay : i18n.t(i18n.l.wallet.change_wallet.loading_balance); + const item: ControlPanelMenuItemProps = { IconComponent: account.image ? ( @@ -152,10 +154,7 @@ export const ControlPanel = () => { ), label: removeFirstEmojiFromString(account.label) || address(account.address, 6, 4), - secondaryLabel: - wallet.type === WalletTypes.readOnly - ? i18n.t(i18n.l.wallet.change_wallet.watching) - : account.balances?.totalBalanceDisplay ?? i18n.t(i18n.l.wallet.change_wallet.no_balance), + secondaryLabel: wallet.type === WalletTypes.readOnly ? i18n.t(i18n.l.wallet.change_wallet.watching) : balanceText, uniqueId: account.address, color: colors.avatarBackgrounds[account.color], imageUrl: account.image || undefined, diff --git a/src/components/change-wallet/AddressRow.tsx b/src/components/change-wallet/AddressRow.tsx index 8985151edf0..a67479f22a6 100644 --- a/src/components/change-wallet/AddressRow.tsx +++ b/src/components/change-wallet/AddressRow.tsx @@ -126,7 +126,7 @@ export default function AddressRow({ contextMenuActions, data, editMode, onPress const labelQuaternary = useForegroundColor('labelQuaternary'); - const balanceOrNoBalance = balances?.totalBalanceDisplay || lang.t('wallet.change_wallet.no_balance'); + const balanceText = balances ? balances.totalBalanceDisplay : lang.t('wallet.change_wallet.loading_balance'); const cleanedUpLabel = useMemo(() => removeFirstEmojiFromString(label), [label]); @@ -244,7 +244,7 @@ export default function AddressRow({ contextMenuActions, data, editMode, onPress {walletName} - {balanceOrNoBalance} + {balanceText} diff --git a/src/components/contacts/ContactRow.js b/src/components/contacts/ContactRow.js index afa222d1050..be9b2ad9efe 100644 --- a/src/components/contacts/ContactRow.js +++ b/src/components/contacts/ContactRow.js @@ -60,7 +60,7 @@ const ContactRow = ({ address, color, nickname, symmetricalMargins, ...props }, const { colors } = useTheme(); const { accountType, balances, ens, image, label, network, onPress, showcaseItem, testID } = props; - const cleanedUpBalance = balances?.totalBalanceDisplay || i18n.t(i18n.l.wallet.change_wallet.no_balance); + const balanceText = balances ? balances.totalBalanceDisplay : lang.t('wallet.change_wallet.loading_balance'); // show avatar for contact rows that are accounts, not contacts const avatar = accountType !== 'contacts' ? returnStringFirstEmoji(label) || profileUtils.addressHashedEmoji(address) : null; @@ -133,7 +133,7 @@ const ContactRow = ({ address, color, nickname, symmetricalMargins, ...props }, )} - {cleanedUpBalance} + {balanceText} ) : ( diff --git a/src/languages/en_US.json b/src/languages/en_US.json index 70c93854a3f..c243830f84d 100644 --- a/src/languages/en_US.json +++ b/src/languages/en_US.json @@ -2488,7 +2488,7 @@ "balance_title": "Balance", "buy": "Buy", "change_wallet": { - "no_balance": "No Balance", + "loading_balance": "Loading Balance...", "balance_eth": "%{balanceEth} ETH", "watching": "Watching", "ledger": "Ledger" From 3ada8f0edb067cf56f27a5a377257e93d4400858 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Wed, 14 Aug 2024 10:03:52 -0700 Subject: [PATCH 36/36] fix i18n mistake --- src/components/contacts/ContactRow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/contacts/ContactRow.js b/src/components/contacts/ContactRow.js index be9b2ad9efe..b213d33dd23 100644 --- a/src/components/contacts/ContactRow.js +++ b/src/components/contacts/ContactRow.js @@ -60,7 +60,7 @@ const ContactRow = ({ address, color, nickname, symmetricalMargins, ...props }, const { colors } = useTheme(); const { accountType, balances, ens, image, label, network, onPress, showcaseItem, testID } = props; - const balanceText = balances ? balances.totalBalanceDisplay : lang.t('wallet.change_wallet.loading_balance'); + const balanceText = balances ? balances.totalBalanceDisplay : i18n.t(i18n.l.wallet.change_wallet.loading_balance); // show avatar for contact rows that are accounts, not contacts const avatar = accountType !== 'contacts' ? returnStringFirstEmoji(label) || profileUtils.addressHashedEmoji(address) : null;