diff --git a/src/components/Tokens/TokenDetails/BalanceSummary.tsx b/src/components/Tokens/TokenDetails/BalanceSummary.tsx index 3145de96ff..ffd5d24416 100644 --- a/src/components/Tokens/TokenDetails/BalanceSummary.tsx +++ b/src/components/Tokens/TokenDetails/BalanceSummary.tsx @@ -1,83 +1,110 @@ import { Trans } from '@lingui/macro' -import { useToken } from 'hooks/Tokens' -import { useNetworkTokenBalances } from 'hooks/useNetworkTokenBalances' -import { AlertTriangle } from 'react-feather' +import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' +import { formatToDecimal } from 'analytics/utils' +import CurrencyLogo from 'components/CurrencyLogo' +import { useStablecoinValue } from 'hooks/useStablecoinPrice' import styled from 'styled-components/macro' +import { formatDollarAmount } from 'utils/formatDollarAmt' const BalancesCard = styled.div` - width: 100%; - height: fit-content; - color: ${({ theme }) => theme.textPrimary}; - font-size: 12px; - line-height: 16px; - padding: 20px; box-shadow: ${({ theme }) => theme.shallowShadow}; background-color: ${({ theme }) => theme.backgroundSurface}; border: ${({ theme }) => `1px solid ${theme.backgroundOutline}`}; border-radius: 16px; -` -const ErrorState = styled.div` - display: flex; - align-items: center; - gap: 12px; - color: ${({ theme }) => theme.textSecondary}; - font-weight: 500; - font-size: 14px; - line-height: 20px; -` -const ErrorText = styled.span` - display: flex; - flex-wrap: wrap; -` + color: ${({ theme }) => theme.textPrimary}; + display: none; + font-size: 12px; + height: fit-content; + line-height: 16px; + padding: 20px; + width: 100%; + // 768 hardcoded to match NFT-redesign navbar breakpoints + // src/nft/css/sprinkles.css.ts + // change to match theme breakpoints when this navbar is updated + @media screen and (min-width: 768px) { + display: flex; + } +` const TotalBalanceSection = styled.div` height: fit-content; + width: 100%; ` const TotalBalance = styled.div` + align-items: center; display: flex; - justify-content: space-between; + flex-direction: row; font-size: 20px; + justify-content: space-between; line-height: 28px; margin-top: 12px; - align-items: center; ` const TotalBalanceItem = styled.div` display: flex; ` -export default function BalanceSummary({ - address, - balance, - balanceUsd, -}: { - address: string - balance?: number - balanceUsd?: number -}) { - const token = useToken(address) - const { loading, error } = useNetworkTokenBalances({ address }) +export interface BalanceSummaryProps { + tokenAmount: CurrencyAmount | undefined + nativeCurrencyAmount: CurrencyAmount | undefined + isNative: boolean +} + +export default function BalanceSummary({ tokenAmount, nativeCurrencyAmount, isNative }: BalanceSummaryProps) { + const balanceUsdValue = useStablecoinValue(tokenAmount)?.toFixed(2) + const nativeBalanceUsdValue = useStablecoinValue(nativeCurrencyAmount)?.toFixed(2) + + const tokenIsWrappedNative = + tokenAmount && + nativeCurrencyAmount && + tokenAmount.currency.address.toLowerCase() === nativeCurrencyAmount.currency.wrapped.address.toLowerCase() + + if ( + (!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) { + currencies.push({ + currency: tokenAmount.currency, + formattedBalance: formatToDecimal(tokenAmount, Math.min(tokenAmount.currency.decimals, 2)), + formattedUSDValue: balanceUsdValue ? parseFloat(balanceUsdValue) : undefined, + }) + } + if (showNative && nativeCurrencyAmount) { + const nativeData = { + currency: nativeCurrencyAmount.currency, + formattedBalance: formatToDecimal(nativeCurrencyAmount, Math.min(nativeCurrencyAmount.currency.decimals, 2)), + formattedUSDValue: nativeBalanceUsdValue ? parseFloat(nativeBalanceUsdValue) : undefined, + } + if (isNative) { + currencies.unshift(nativeData) + } else { + currencies.push(nativeData) + } + } - if (loading || (!error && !balance && !balanceUsd)) return null return ( - {error ? ( - - - - There was an error loading your {token?.symbol} balance - - - ) : ( - <> - - Your balance - - {`${balance} ${token?.symbol}`} - {`$${balanceUsd}`} - - - - )} + + Your balance + {currencies.map(({ currency, formattedBalance, formattedUSDValue }) => ( + + + +  {formattedBalance} {currency?.symbol} + + + {formatDollarAmount(formattedUSDValue === 0 ? undefined : formattedUSDValue)} + + + ))} + ) } diff --git a/src/components/Tokens/TokenDetails/FooterBalanceSummary.tsx b/src/components/Tokens/TokenDetails/FooterBalanceSummary.tsx deleted file mode 100644 index d8062537f6..0000000000 --- a/src/components/Tokens/TokenDetails/FooterBalanceSummary.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useToken } from 'hooks/Tokens' -import { useNetworkTokenBalances } from 'hooks/useNetworkTokenBalances' -import { useState } from 'react' -import { AlertTriangle } from 'react-feather' -import { Link } from 'react-router-dom' -import styled from 'styled-components/macro' - -import { SMALLEST_MOBILE_MEDIA_BREAKPOINT } from '../constants' -import { LoadingBubble } from '../loading' - -const PLACEHOLDER_NAV_FOOTER_HEIGHT = '56px' -const BalanceFooter = styled.div` - height: fit-content; - border: 1px solid ${({ theme }) => theme.backgroundOutline}; - background-color: ${({ theme }) => theme.backgroundSurface}; - border-radius: 20px 20px 0px 0px; - padding: 12px 16px; - font-weight: 500; - font-size: 14px; - line-height: 20px; - width: 100%; - color: ${({ theme }) => theme.textSecondary}; - position: fixed; - left: 0; - bottom: ${PLACEHOLDER_NAV_FOOTER_HEIGHT}; - display: flex; - flex-direction: column; - align-content: center; -` -const BalanceValue = styled.div` - font-size: 20px; - line-height: 28px; - display: flex; - gap: 8px; -` -const BalanceTotal = styled.div` - display: flex; - flex-wrap: wrap; - gap: 8px; - color: ${({ theme }) => theme.textPrimary}; -` -const BalanceInfo = styled.div` - display: flex; - justify-content: flex-start; - flex-direction: column; -` -const FakeFooterNavBar = styled.div` - position: fixed; - bottom: 0px; - left: 0px; - background-color: ${({ theme }) => theme.backgroundBackdrop}; - height: ${PLACEHOLDER_NAV_FOOTER_HEIGHT}; - width: 100%; - align-items: flex-end; - padding: 20px 8px; - font-size: 10px; -` -const FiatValue = styled.span` - display: flex; - align-self: flex-end; - font-size: 12px; - line-height: 24px; - - @media only screen and (max-width: ${SMALLEST_MOBILE_MEDIA_BREAKPOINT}) { - line-height: 16px; - } -` -const NetworkBalancesSection = styled.div` - height: fit-content; - border-top: 1px solid ${({ theme }) => theme.backgroundOutline}; - display: flex; - flex-direction: column; - padding: 16px 0px 8px 0px; - margin-top: 16px; - color: ${({ theme }) => theme.textPrimary}; -` -const NetworkBalancesLabel = styled.span` - color: ${({ theme }) => theme.textSecondary}; -` -const SwapButton = styled.button` - background-color: ${({ theme }) => theme.accentAction}; - border-radius: 12px; - display: flex; - align-items: center; - border: none; - color: ${({ theme }) => theme.accentTextLightPrimary}; - padding: 12px 16px; - width: 120px; - height: 44px; - font-size: 16px; - font-weight: 600; - justify-content: center; -` -const TotalBalancesSection = styled.div` - display: flex; - color: ${({ theme }) => theme.textSecondary}; - justify-content: space-between; - align-items: center; -` -const ViewAll = styled.span` - display: flex; - color: ${({ theme }) => theme.accentAction}; - font-size: 14px; - line-height: 20px; - cursor: pointer; -` -const ErrorState = styled.div` - display: flex; - align-items: center; - gap: 8px; - padding-right: 8px; -` -const LoadingState = styled.div` - display: flex; - flex-direction: column; - gap: 12px; -` -const TopBalanceLoadBubble = styled(LoadingBubble)` - height: 12px; - width: 172px; -` -const BottomBalanceLoadBubble = styled(LoadingBubble)` - height: 16px; - width: 188px; -` -const ErrorText = styled.span` - display: flex; - flex-wrap: wrap; -` - -export default function FooterBalanceSummary({ - address, - networkBalances, - balance, - balanceUsd, -}: { - address: string - networkBalances: (JSX.Element | null)[] | null - balance?: number - balanceUsd?: number -}) { - const tokenSymbol = useToken(address)?.symbol - const [showMultipleBalances, setShowMultipleBalances] = useState(false) - const multipleBalances = false // for testing purposes - const networkNameIfOneBalance = 'Ethereum' // for testing purposes - const { loading, error } = useNetworkTokenBalances({ address }) - return ( - - - {loading ? ( - - - - - ) : error ? ( - - - - There was an error fetching your balance - - - ) : ( - !!balance && - !!balanceUsd && ( - - {multipleBalances ? 'Balance on all networks' : `Your balance on ${networkNameIfOneBalance}`} - - - {balance} {tokenSymbol} - - {`$${balanceUsd}`} - - {multipleBalances && ( - setShowMultipleBalances(!showMultipleBalances)}> - {showMultipleBalances ? 'Hide' : 'View'} all balances - - )} - - ) - )} - - - Swap - - - - {showMultipleBalances && ( - - - Your balances by network - - {networkBalances} - - )} - **leaving space for updated nav footer** - - ) -} diff --git a/src/components/Tokens/TokenDetails/LoadingTokenDetails.tsx b/src/components/Tokens/TokenDetails/LoadingTokenDetails.tsx index b5b7db415e..6408627489 100644 --- a/src/components/Tokens/TokenDetails/LoadingTokenDetails.tsx +++ b/src/components/Tokens/TokenDetails/LoadingTokenDetails.tsx @@ -1,5 +1,5 @@ import { WidgetSkeleton } from 'components/Widget' -import { Footer, LeftPanel, RightPanel, TokenDetailsLayout } from 'pages/TokenDetails' +import { LeftPanel, RightPanel, TokenDetailsLayout } from 'pages/TokenDetails' import styled, { useTheme } from 'styled-components/macro' import { LoadingBubble } from '../loading' @@ -158,7 +158,6 @@ export function LoadingTokenDetails() { -