From c871e55d82bc205a1f484f0171d356b0bbb9c395 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 25 Oct 2022 13:46:25 -0700 Subject: [PATCH] fix: clean up balance summaries (#4984) * fix: clean up balance summaries * fix: nits * fix: off-chain balances * fix: only show token under details * fix: consolidate formatting --- .../Tokens/TokenDetails/BalanceSummary.tsx | 120 ++++++------------ .../MobileBalanceSummaryFooter.tsx | 62 +++------ src/lib/hooks/useCurrencyBalance.ts | 5 +- src/pages/TokenDetails/index.tsx | 22 +--- 4 files changed, 66 insertions(+), 143 deletions(-) diff --git a/src/components/Tokens/TokenDetails/BalanceSummary.tsx b/src/components/Tokens/TokenDetails/BalanceSummary.tsx index 139c0f2659..32140aa592 100644 --- a/src/components/Tokens/TokenDetails/BalanceSummary.tsx +++ b/src/components/Tokens/TokenDetails/BalanceSummary.tsx @@ -1,10 +1,13 @@ import { Trans } from '@lingui/macro' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' +import { useWeb3React } from '@web3-react/core' import { formatToDecimal } from 'analytics/utils' import CurrencyLogo from 'components/CurrencyLogo' -import { validateUrlChainParam } from 'graphql/data/util' +import { NATIVE_CHAIN_ID } from 'constants/tokens' +import { CHAIN_ID_TO_BACKEND_NAME } from 'graphql/data/util' import { useStablecoinValue } from 'hooks/useStablecoinPrice' -import { useParams } from 'react-router-dom' +import useCurrencyBalance from 'lib/hooks/useCurrencyBalance' +import { useMemo } from 'react' import styled from 'styled-components/macro' import { StyledInternalLink } from 'theme' import { currencyAmountToPreciseFloat, formatDollar } from 'utils/formatNumbers' @@ -29,11 +32,11 @@ const BalancesCard = styled.div` display: flex; } ` -const TotalBalanceSection = styled.div` +const BalanceSection = styled.div` height: fit-content; width: 100%; ` -const TotalBalance = styled.div` +const BalanceRow = styled.div` align-items: center; display: flex; flex-direction: row; @@ -42,99 +45,52 @@ const TotalBalance = styled.div` line-height: 28px; margin-top: 12px; ` -const TotalBalanceItem = styled.div` +const BalanceItem = styled.div` display: flex; ` -const BalanceRowLink = styled(StyledInternalLink)` +const BalanceLink = styled(StyledInternalLink)` color: unset; ` -function BalanceRow({ currency, formattedBalance, usdValue, href }: BalanceRowData) { - const content = ( - - - -  {formattedBalance} {currency?.symbol} - - {formatDollar({ num: usdValue === 0 ? undefined : usdValue, isPrice: true })} - +export function useFormatBalance(balance: CurrencyAmount | undefined) { + return useMemo( + () => (balance ? formatToDecimal(balance, Math.min(balance.currency.decimals, 2)) : undefined), + [balance] ) - if (href) { - return {content} - } - return content } -interface BalanceRowData { - currency: Currency - formattedBalance: number - usdValue: number | undefined - href?: string -} -export interface BalanceSummaryProps { - tokenAmount: CurrencyAmount | undefined - nativeCurrencyAmount: CurrencyAmount | undefined - isNative: boolean +export function useFormatUsdValue(usdValue: CurrencyAmount | null) { + return useMemo(() => { + const float = usdValue ? currencyAmountToPreciseFloat(usdValue) : undefined + if (!float) return undefined + return formatDollar({ num: float, isPrice: true }) + }, [usdValue]) } -export default function BalanceSummary({ tokenAmount, nativeCurrencyAmount, isNative }: BalanceSummaryProps) { - const balanceUsdValue = useStablecoinValue(tokenAmount) - const nativeBalanceUsdValue = useStablecoinValue(nativeCurrencyAmount) - - const { chainName } = useParams<{ chainName?: string }>() - const pageChainName = validateUrlChainParam(chainName).toLowerCase() - - const tokenIsWrappedNative = - tokenAmount && - nativeCurrencyAmount && - tokenAmount.currency.address.toLowerCase() === nativeCurrencyAmount.currency.wrapped.address.toLowerCase() - - if ( - (!tokenAmount && !nativeCurrencyAmount) || - (!tokenAmount && !tokenIsWrappedNative && !isNative) || - (!isNative && !tokenIsWrappedNative && tokenAmount?.equalTo(0)) || - (isNative && tokenAmount?.equalTo(0) && nativeCurrencyAmount?.equalTo(0)) - ) { - return null - } - const showNative = tokenIsWrappedNative || isNative - - const currencies = [] - - if (tokenAmount) { - const tokenData: BalanceRowData = { - currency: tokenAmount.currency, - formattedBalance: formatToDecimal(tokenAmount, Math.min(tokenAmount.currency.decimals, 2)), - usdValue: balanceUsdValue ? currencyAmountToPreciseFloat(balanceUsdValue) : undefined, - } - if (isNative) { - tokenData.href = `/tokens/${pageChainName}/${tokenAmount.currency.address}` - } - currencies.push(tokenData) - } - if (showNative && nativeCurrencyAmount) { - const nativeData: BalanceRowData = { - currency: nativeCurrencyAmount.currency, - formattedBalance: formatToDecimal(nativeCurrencyAmount, Math.min(nativeCurrencyAmount.currency.decimals, 2)), - usdValue: nativeBalanceUsdValue ? currencyAmountToPreciseFloat(nativeBalanceUsdValue) : undefined, - } - if (isNative) { - currencies.unshift(nativeData) - } else { - nativeData.href = `/tokens/${pageChainName}/NATIVE` - currencies.push(nativeData) - } - } +export default function BalanceSummary({ token }: { token: Currency }) { + const { account } = useWeb3React() + const balance = useCurrencyBalance(account, token) + const formattedBalance = useFormatBalance(balance) + const usdValue = useStablecoinValue(balance) + const formattedUsdValue = useFormatUsdValue(usdValue) + const chain = CHAIN_ID_TO_BACKEND_NAME[token.chainId].toLowerCase() + if (!account || !balance) return null return ( - + Your balance - {currencies.map((props, i) => ( - - ))} - + + + + +  {formattedBalance} {token.symbol} + + {formattedUsdValue} + + + ) } diff --git a/src/components/Tokens/TokenDetails/MobileBalanceSummaryFooter.tsx b/src/components/Tokens/TokenDetails/MobileBalanceSummaryFooter.tsx index 5be481ca11..4eb6f24bac 100644 --- a/src/components/Tokens/TokenDetails/MobileBalanceSummaryFooter.tsx +++ b/src/components/Tokens/TokenDetails/MobileBalanceSummaryFooter.tsx @@ -1,11 +1,14 @@ import { Trans } from '@lingui/macro' -import { formatToDecimal } from 'analytics/utils' +import { Currency } from '@uniswap/sdk-core' +import { useWeb3React } from '@web3-react/core' +import { NATIVE_CHAIN_ID } from 'constants/tokens' +import { CHAIN_ID_TO_BACKEND_NAME } from 'graphql/data/util' import { useStablecoinValue } from 'hooks/useStablecoinPrice' +import useCurrencyBalance from 'lib/hooks/useCurrencyBalance' import styled from 'styled-components/macro' import { StyledInternalLink } from 'theme' -import { currencyAmountToPreciseFloat, formatDollar } from 'utils/formatNumbers' -import { BalanceSummaryProps } from './BalanceSummary' +import { useFormatBalance, useFormatUsdValue } from './BalanceSummary' const Wrapper = styled.div` align-content: center; @@ -41,7 +44,7 @@ const BalanceValue = styled.div` display: flex; gap: 8px; ` -const BalanceTotal = styled.div` +const Balance = styled.div` align-items: center; display: flex; flex-direction: row; @@ -78,51 +81,28 @@ const SwapButton = styled(StyledInternalLink)` max-width: 100vw; ` -export default function MobileBalanceSummaryFooter({ - tokenAmount, - nativeCurrencyAmount, - isNative, - tokenAddress, -}: BalanceSummaryProps & { tokenAddress: string }) { - const balanceUsdValue = useStablecoinValue(tokenAmount) - const nativeBalanceUsdValue = useStablecoinValue(nativeCurrencyAmount) - - const formattedBalance = tokenAmount - ? formatToDecimal(tokenAmount, Math.min(tokenAmount.currency.decimals, 2)) - : undefined - - const balanceUsd = balanceUsdValue ? currencyAmountToPreciseFloat(balanceUsdValue) : undefined - - const formattedNativeBalance = nativeCurrencyAmount - ? formatToDecimal(nativeCurrencyAmount, Math.min(nativeCurrencyAmount.currency.decimals, 2)) - : undefined - const nativeBalanceUsd = nativeBalanceUsdValue ? currencyAmountToPreciseFloat(nativeBalanceUsdValue) : undefined +export default function MobileBalanceSummaryFooter({ token }: { token: Currency }) { + const { account } = useWeb3React() + const balance = useCurrencyBalance(account, token) + const formattedBalance = useFormatBalance(balance) + const usdValue = useStablecoinValue(balance) + const formattedUsdValue = useFormatUsdValue(usdValue) + const chain = CHAIN_ID_TO_BACKEND_NAME[token.chainId].toLowerCase() return ( - {Boolean(formattedBalance !== undefined && !isNative && tokenAmount?.greaterThan(0)) && ( + {Boolean(account && balance) && ( - Your {tokenAmount?.currency?.symbol} balance - + Your {token.symbol} balance + - {formattedBalance} {tokenAmount?.currency?.symbol} + {formattedBalance} {token.symbol} - {formatDollar({ num: balanceUsd, isPrice: true })} - + {formattedUsdValue} + )} - {Boolean(isNative && nativeCurrencyAmount?.greaterThan(0)) && ( - - Your {nativeCurrencyAmount?.currency?.symbol} balance - - - {formattedNativeBalance} {nativeCurrencyAmount?.currency?.symbol} - - {formatDollar({ num: nativeBalanceUsd, isPrice: true })} - - - )} - + Swap diff --git a/src/lib/hooks/useCurrencyBalance.ts b/src/lib/hooks/useCurrencyBalance.ts index da4e6ec5c9..bd72573436 100644 --- a/src/lib/hooks/useCurrencyBalance.ts +++ b/src/lib/hooks/useCurrencyBalance.ts @@ -117,6 +117,7 @@ export function useCurrencyBalances( [currencies] ) + const { chainId } = useWeb3React() const tokenBalances = useTokenBalances(account, tokens) const containsETH: boolean = useMemo(() => currencies?.some((currency) => currency?.isNative) ?? false, [currencies]) const ethBalance = useNativeCurrencyBalances(useMemo(() => (containsETH ? [account] : []), [containsETH, account])) @@ -124,12 +125,12 @@ export function useCurrencyBalances( return useMemo( () => currencies?.map((currency) => { - if (!account || !currency) return undefined + if (!account || !currency || currency.chainId !== chainId) return undefined if (currency.isToken) return tokenBalances[currency.address] if (currency.isNative) return ethBalance[account] return undefined }) ?? [], - [account, currencies, ethBalance, tokenBalances] + [account, chainId, currencies, ethBalance, tokenBalances] ) } diff --git a/src/pages/TokenDetails/index.tsx b/src/pages/TokenDetails/index.tsx index d27b94f093..719b208dd1 100644 --- a/src/pages/TokenDetails/index.tsx +++ b/src/pages/TokenDetails/index.tsx @@ -1,5 +1,4 @@ import { Currency } from '@uniswap/sdk-core' -import { useWeb3React } from '@web3-react/core' import { PageName } from 'analytics/constants' import { Trace } from 'analytics/Trace' import { filterTimeAtom } from 'components/Tokens/state' @@ -28,14 +27,12 @@ import { useIsUserAddedTokenOnChain } from 'hooks/Tokens' import { useOnGlobalChainSwitch } from 'hooks/useGlobalChainSwitch' import { useAtomValue } from 'jotai/utils' import { useTokenFromQuery } from 'lib/hooks/useCurrency' -import useCurrencyBalance, { useTokenBalance } from 'lib/hooks/useCurrencyBalance' import { useCallback, useState, useTransition } from 'react' import { ArrowLeft } from 'react-feather' import { useNavigate, useParams } from 'react-router-dom' export default function TokenDetails() { const { tokenAddress, chainName } = useParams<{ tokenAddress?: string; chainName?: string }>() - const { account } = useWeb3React() const chain = validateUrlChainParam(chainName) const pageChainId = CHAIN_NAME_TO_CHAIN_ID[chain] const nativeCurrency = nativeOnChain(pageChainId) @@ -48,10 +45,6 @@ export default function TokenDetails() { ) const queryToken = useTokenFromQuery(isNative ? undefined : { ...tokenQueryData, chainId: pageChainId }) const token = isNative ? nativeCurrency : queryToken - const tokenQueryAddress = isNative ? nativeCurrency.wrapped.address : tokenAddress - - const nativeCurrencyBalance = useCurrencyBalance(account, nativeCurrency) - const tokenBalance = useTokenBalance(account, token?.wrapped) const tokenWarning = tokenAddress ? checkWarning(tokenAddress) : null const isBlockedToken = tokenWarning?.canProceed === false @@ -141,21 +134,14 @@ export default function TokenDetails() { onReviewSwapClick={onReviewSwapClick} /> {tokenWarning && } - + {token && } + {token && } - {tokenQueryAddress && ( - - )} - {tokenQueryAddress && ( + {tokenAddress && ( onResolveSwap(true)} onBlocked={() => navigate(-1)} onCancel={() => onResolveSwap(false)}