From ae624594be6275a766705e6daccfae5e848f526b Mon Sep 17 00:00:00 2001 From: Owen Craston Date: Fri, 17 Jan 2025 15:12:07 -0800 Subject: [PATCH] extract balance logic into a hook --- .../TokenList/PortfolioBalance/index.tsx | 211 ++---------------- .../hooks/usePortfolioBalance/index.ts | 7 + .../usePortfolioBalance.test.ts | 187 ++++++++++++++++ .../usePortfolioBalance.ts | 187 ++++++++++++++++ .../usePortfolioBalance.types.ts | 34 +++ app/hooks/usePortfolioBalance/index.ts | 211 ++++++++++++++++++ 6 files changed, 642 insertions(+), 195 deletions(-) create mode 100644 app/components/hooks/usePortfolioBalance/index.ts create mode 100644 app/components/hooks/usePortfolioBalance/usePortfolioBalance.test.ts create mode 100644 app/components/hooks/usePortfolioBalance/usePortfolioBalance.ts create mode 100644 app/components/hooks/usePortfolioBalance/usePortfolioBalance.types.ts create mode 100644 app/hooks/usePortfolioBalance/index.ts diff --git a/app/components/UI/Tokens/TokenList/PortfolioBalance/index.tsx b/app/components/UI/Tokens/TokenList/PortfolioBalance/index.tsx index 0883d3836ead..f4236af4763d 100644 --- a/app/components/UI/Tokens/TokenList/PortfolioBalance/index.tsx +++ b/app/components/UI/Tokens/TokenList/PortfolioBalance/index.tsx @@ -1,32 +1,6 @@ import React from 'react'; import { View, TouchableOpacity } from 'react-native'; -import { useNavigation } from '@react-navigation/native'; -import { useSelector } from 'react-redux'; -import useIsOriginalNativeTokenSymbol from '../../../../hooks/useIsOriginalNativeTokenSymbol/useIsOriginalNativeTokenSymbol'; -import { useMetrics } from '../../../../hooks/useMetrics'; import { useTheme } from '../../../../../util/theme'; -import AppConstants from '../../../../../core/AppConstants'; -import Engine from '../../../../../core/Engine'; -import Routes from '../../../../../constants/navigation/Routes'; -import { MetaMetricsEvents } from '../../../../../core/Analytics'; -import { - selectChainId, - selectIsPopularNetwork, - selectProviderConfig, - selectTicker, -} from '../../../../../selectors/networkController'; -import { selectCurrentCurrency } from '../../../../../selectors/currencyRateController'; -import { - selectIsTokenNetworkFilterEqualCurrentNetwork, - selectPrivacyMode, -} from '../../../../../selectors/preferencesController'; -import { RootState } from '../../../../../reducers'; -import { renderFiat } from '../../../../../util/number'; -import { - isPortfolioViewEnabled, - isTestNet, -} from '../../../../../util/networks'; -import { isPortfolioUrl } from '../../../../../util/url'; import createStyles from '../../styles'; import Button, { ButtonVariants, @@ -42,209 +16,56 @@ import Icon, { IconSize, IconName, } from '../../../../../component-library/components/Icons/Icon'; -import { BrowserTab } from '../../types'; import { WalletViewSelectorsIDs } from '../../../../../../e2e/selectors/wallet/WalletView.selectors'; import { strings } from '../../../../../../locales/i18n'; import { EYE_SLASH_ICON_TEST_ID, EYE_ICON_TEST_ID } from './index.constants'; -import { selectSelectedInternalAccount } from '../../../../../selectors/accountsController'; -import { useGetFormattedTokensPerChain } from '../../../../hooks/useGetFormattedTokensPerChain'; -import { - TotalFiatBalancesCrossChains, - useGetTotalFiatBalanceCrossChains, -} from '../../../../hooks/useGetTotalFiatBalanceCrossChains'; -import { InternalAccount } from '@metamask/keyring-internal-api'; -import { getChainIdsToPoll } from '../../../../../selectors/tokensController'; import AggregatedPercentageCrossChains from '../../../../../component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentageCrossChains'; -import { - selectMultichainSelectedAccountCachedBalance, - selectMultichainIsEvm, - selectMultichainDefaultToken, -} from '../../../../../selectors/multichain'; +import { usePortfolioBalance } from '../../../../hooks/usePortfolioBalance'; export const PortfolioBalance = () => { - const { PreferencesController } = Engine.context; const { colors } = useTheme(); const styles = createStyles(colors); - const balance = Engine.getTotalFiatAccountBalance(); - - const selectedInternalAccount: InternalAccount | undefined = useSelector( - selectSelectedInternalAccount, - ); - const allChainIDs = useSelector(getChainIdsToPoll); - const isTokenNetworkFilterEqualCurrentNetwork = useSelector( - selectIsTokenNetworkFilterEqualCurrentNetwork, - ); - const isPopularNetwork = useSelector(selectIsPopularNetwork); - - const formattedTokensWithBalancesPerChain = useGetFormattedTokensPerChain( - [selectedInternalAccount as InternalAccount], - !isTokenNetworkFilterEqualCurrentNetwork && isPopularNetwork, - allChainIDs, - ); - - const totalFiatBalancesCrossChain: TotalFiatBalancesCrossChains = - useGetTotalFiatBalanceCrossChains( - [selectedInternalAccount as InternalAccount], - formattedTokensWithBalancesPerChain, - ); - - const tokenFiatBalancesCrossChains = - totalFiatBalancesCrossChain[selectedInternalAccount?.address as string] - ?.tokenFiatBalancesCrossChains ?? []; - const totalFiatBalance = - totalFiatBalancesCrossChain[selectedInternalAccount?.address as string] - ?.totalFiatBalance ?? 0; - const totalTokenFiat = - totalFiatBalancesCrossChain[selectedInternalAccount?.address as string] - ?.totalTokenFiat ?? 0; - - const navigation = useNavigation(); - const { trackEvent, isEnabled, createEventBuilder } = useMetrics(); - - const { type } = useSelector(selectProviderConfig); - const chainId = useSelector(selectChainId); - const ticker = useSelector(selectTicker); - const isDataCollectionForMarketingEnabled = useSelector( - (state: RootState) => state.security.dataCollectionForMarketing, - ); - const currentCurrency = useSelector(selectCurrentCurrency); - const browserTabs = useSelector((state: RootState) => state.browser.tabs); - const privacyMode = useSelector(selectPrivacyMode); - - const multichainSelectedAccountCachedBalance = useSelector( - selectMultichainSelectedAccountCachedBalance, - ); - - const isEvm = useSelector(selectMultichainIsEvm); - const { symbol } = useSelector(selectMultichainDefaultToken); - console.log('isEvm', isEvm); - console.log('symbol', symbol); - - const isOriginalNativeTokenSymbol = useIsOriginalNativeTokenSymbol( - chainId, - ticker, - type, - ); - - let displayBalance; - if (isEvm) { - let total; - if (isOriginalNativeTokenSymbol) { - if (isPortfolioViewEnabled()) { - total = totalFiatBalance ?? 0; - } else { - const tokenFiatTotal = balance?.tokenFiat ?? 0; - const ethFiatTotal = balance?.ethFiat ?? 0; - total = tokenFiatTotal + ethFiatTotal; - } - } else if (isPortfolioViewEnabled()) { - total = totalTokenFiat ?? 0; - } else { - total = balance?.tokenFiat ?? 0; - } - displayBalance = `${renderFiat(total, currentCurrency)}`; - } else { - // For non-EVM accounts, display the native balance with symbol - displayBalance = `${multichainSelectedAccountCachedBalance} ${symbol}`; - } - - const onOpenPortfolio = () => { - const existingPortfolioTab = browserTabs.find(({ url }: BrowserTab) => - isPortfolioUrl(url), - ); - - let existingTabId; - let newTabUrl; - if (existingPortfolioTab) { - existingTabId = existingPortfolioTab.id; - } else { - const analyticsEnabled = isEnabled(); - const portfolioUrl = new URL(AppConstants.PORTFOLIO.URL); - - portfolioUrl.searchParams.append('metamaskEntry', 'mobile'); - - // Append user's privacy preferences for metrics + marketing on user navigation to Portfolio. - portfolioUrl.searchParams.append( - 'metricsEnabled', - String(analyticsEnabled), - ); - portfolioUrl.searchParams.append( - 'marketingEnabled', - String(!!isDataCollectionForMarketingEnabled), - ); - - newTabUrl = portfolioUrl.href; - } - const params = { - ...(newTabUrl && { newTabUrl }), - ...(existingTabId && { existingTabId, newTabUrl: undefined }), - timestamp: Date.now(), - }; - navigation.navigate(Routes.BROWSER.HOME, { - screen: Routes.BROWSER.VIEW, - params, - }); - trackEvent( - createEventBuilder(MetaMetricsEvents.PORTFOLIO_LINK_CLICKED) - .addProperties({ - portfolioUrl: AppConstants.PORTFOLIO.URL, - }) - .build(), - ); - }; + const { data, actions } = usePortfolioBalance(); const renderAggregatedPercentage = () => { - if (!isEvm || isTestNet(chainId)) { + if (!data.shouldShowAggregatedPercentage) { return null; } - if (isPortfolioViewEnabled()) { - return ( - - ); - } return ( - ); }; - const toggleIsBalanceAndAssetsHidden = (value: boolean) => { - PreferencesController.setPrivacyMode(value); - }; - return ( - {displayBalance} + {data.displayBalance} toggleIsBalanceAndAssetsHidden(!privacyMode)} + onPress={() => actions.togglePrivacyMode(!data.privacyMode)} testID="balance-container" > @@ -252,14 +73,14 @@ export const PortfolioBalance = () => { {renderAggregatedPercentage()} - {isEvm && ( + {data.shouldShowPortfolioButton && (