Commit 63032930 authored by Jack Short's avatar Jack Short Committed by GitHub

chore: updating all numbers in swap flow to be converted properly (#7301)

* format price impact

* format price

* adding confirm swap modal

* removing export

* adding export back

* correct active currency

* activeLocalCurrencyIsUSD

* fallback to usd if no conversion rate for previous
parent 185cb525
...@@ -6,7 +6,7 @@ import { MouseoverTooltip } from 'components/Tooltip' ...@@ -6,7 +6,7 @@ import { MouseoverTooltip } from 'components/Tooltip'
import { useMemo } from 'react' import { useMemo } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
import { formatPriceImpact, NumberType, useFormatter } from 'utils/formatNumbers' import { NumberType, useFormatter } from 'utils/formatNumbers'
import { warningSeverity } from 'utils/prices' import { warningSeverity } from 'utils/prices'
const FiatLoadingBubble = styled(LoadingBubble)` const FiatLoadingBubble = styled(LoadingBubble)`
...@@ -22,7 +22,7 @@ export function FiatValue({ ...@@ -22,7 +22,7 @@ export function FiatValue({
fiatValue: { data?: number; isLoading: boolean } fiatValue: { data?: number; isLoading: boolean }
priceImpact?: Percent priceImpact?: Percent
}) { }) {
const { formatNumber } = useFormatter() const { formatNumber, formatPriceImpact } = useFormatter()
const priceImpactColor = useMemo(() => { const priceImpactColor = useMemo(() => {
if (!priceImpact) return undefined if (!priceImpact) return undefined
......
...@@ -9,7 +9,7 @@ import { ZERO_PERCENT } from 'constants/misc' ...@@ -9,7 +9,7 @@ import { ZERO_PERCENT } from 'constants/misc'
import useNativeCurrency from 'lib/hooks/useNativeCurrency' import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import { ClassicTrade, InterfaceTrade } from 'state/routing/types' import { ClassicTrade, InterfaceTrade } from 'state/routing/types'
import { getTransactionCount, isClassicTrade } from 'state/routing/utils' import { getTransactionCount, isClassicTrade } from 'state/routing/utils'
import { formatPriceImpact, NumberType, useFormatter } from 'utils/formatNumbers' import { NumberType, useFormatter } from 'utils/formatNumbers'
import { ExternalLink, Separator, ThemedText } from '../../theme' import { ExternalLink, Separator, ThemedText } from '../../theme'
import Column from '../Column' import Column from '../Column'
...@@ -47,7 +47,7 @@ export function AdvancedSwapDetails({ trade, allowedSlippage, syncing = false }: ...@@ -47,7 +47,7 @@ export function AdvancedSwapDetails({ trade, allowedSlippage, syncing = false }:
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const nativeCurrency = useNativeCurrency(chainId) const nativeCurrency = useNativeCurrency(chainId)
const txCount = getTransactionCount(trade) const txCount = getTransactionCount(trade)
const { formatNumber, formatCurrencyAmount } = useFormatter() const { formatCurrencyAmount, formatNumber, formatPriceImpact } = useFormatter()
const supportsGasEstimate = chainId && SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId) const supportsGasEstimate = chainId && SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId)
...@@ -194,6 +194,8 @@ function TokenTaxLineItem({ ...@@ -194,6 +194,8 @@ function TokenTaxLineItem({
type: 'input' | 'output' type: 'input' | 'output'
syncing: boolean syncing: boolean
}) { }) {
const { formatPriceImpact } = useFormatter()
if (syncing) return null if (syncing) return null
const [currency, percentage] = const [currency, percentage] =
......
...@@ -4,10 +4,12 @@ import { ArrowRight } from 'react-feather' ...@@ -4,10 +4,12 @@ import { ArrowRight } from 'react-feather'
import { InterfaceTrade } from 'state/routing/types' import { InterfaceTrade } from 'state/routing/types'
import { useTheme } from 'styled-components' import { useTheme } from 'styled-components'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
import { formatReviewSwapCurrencyAmount } from 'utils/formatNumbers' import { useFormatter } from 'utils/formatNumbers'
export function TradeSummary({ trade }: { trade: Pick<InterfaceTrade, 'inputAmount' | 'postTaxOutputAmount'> }) { export function TradeSummary({ trade }: { trade: Pick<InterfaceTrade, 'inputAmount' | 'postTaxOutputAmount'> }) {
const theme = useTheme() const theme = useTheme()
const { formatReviewSwapCurrencyAmount } = useFormatter()
return ( return (
<Row gap="sm" justify="center" align="center"> <Row gap="sm" justify="center" align="center">
<CurrencyLogo currency={trade.inputAmount.currency} size="16px" /> <CurrencyLogo currency={trade.inputAmount.currency} size="16px" />
......
...@@ -6,7 +6,7 @@ import Row from 'components/Row' ...@@ -6,7 +6,7 @@ import Row from 'components/Row'
import { AlertTriangle } from 'react-feather' import { AlertTriangle } from 'react-feather'
import styled from 'styled-components' import styled from 'styled-components'
import { CloseIcon, ThemedText } from 'theme' import { CloseIcon, ThemedText } from 'theme'
import { formatPriceImpact } from 'utils/formatNumbers' import { useFormatter } from 'utils/formatNumbers'
import Modal from '../Modal' import Modal from '../Modal'
...@@ -37,6 +37,8 @@ interface PriceImpactModalProps { ...@@ -37,6 +37,8 @@ interface PriceImpactModalProps {
} }
export default function PriceImpactModal({ priceImpact, onDismiss, onContinue }: PriceImpactModalProps) { export default function PriceImpactModal({ priceImpact, onDismiss, onContinue }: PriceImpactModalProps) {
const { formatPriceImpact } = useFormatter()
return ( return (
<Modal isOpen onDismiss={onDismiss}> <Modal isOpen onDismiss={onDismiss}>
<Wrapper gap="md"> <Wrapper gap="md">
......
...@@ -3,7 +3,7 @@ import { Percent } from '@uniswap/sdk-core' ...@@ -3,7 +3,7 @@ import { Percent } from '@uniswap/sdk-core'
import { OutlineCard } from 'components/Card' import { OutlineCard } from 'components/Card'
import styled, { useTheme } from 'styled-components' import styled, { useTheme } from 'styled-components'
import { opacify } from 'theme/utils' import { opacify } from 'theme/utils'
import formatPriceImpact from 'utils/formatPriceImpact' import { useFormatter } from 'utils/formatNumbers'
import { ThemedText } from '../../theme' import { ThemedText } from '../../theme'
import { AutoColumn } from '../Column' import { AutoColumn } from '../Column'
...@@ -20,6 +20,7 @@ interface PriceImpactWarningProps { ...@@ -20,6 +20,7 @@ interface PriceImpactWarningProps {
} }
export default function PriceImpactWarning({ priceImpact }: PriceImpactWarningProps) { export default function PriceImpactWarning({ priceImpact }: PriceImpactWarningProps) {
const { formatPriceImpact } = useFormatter()
const theme = useTheme() const theme = useTheme()
return ( return (
......
...@@ -16,8 +16,8 @@ import { getTransactionCount, isClassicTrade } from 'state/routing/utils' ...@@ -16,8 +16,8 @@ import { getTransactionCount, isClassicTrade } from 'state/routing/utils'
import { useRouterPreference, useUserSlippageTolerance } from 'state/user/hooks' import { useRouterPreference, useUserSlippageTolerance } from 'state/user/hooks'
import styled, { DefaultTheme, useTheme } from 'styled-components' import styled, { DefaultTheme, useTheme } from 'styled-components'
import { ExternalLink, ThemedText } from 'theme' import { ExternalLink, ThemedText } from 'theme'
import { formatPriceImpact, NumberType, useFormatter } from 'utils/formatNumbers' import { FormatterRule, NumberType, SIX_SIG_FIGS_NO_COMMAS, useFormatter } from 'utils/formatNumbers'
import { formatTransactionAmount, priceToPreciseFloat } from 'utils/formatNumbers' import { priceToPreciseFloat } from 'utils/formatNumbers'
import getRoutingDiagramEntries from 'utils/getRoutingDiagramEntries' import getRoutingDiagramEntries from 'utils/getRoutingDiagramEntries'
import { formatSwapButtonClickEventProperties } from 'utils/loggingFormatters' import { formatSwapButtonClickEventProperties } from 'utils/loggingFormatters'
import { getPriceImpactColor } from 'utils/prices' import { getPriceImpactColor } from 'utils/prices'
...@@ -28,6 +28,8 @@ import { GasBreakdownTooltip } from './GasBreakdownTooltip' ...@@ -28,6 +28,8 @@ import { GasBreakdownTooltip } from './GasBreakdownTooltip'
import { SwapCallbackError, SwapShowAcceptChanges } from './styled' import { SwapCallbackError, SwapShowAcceptChanges } from './styled'
import { Label } from './SwapModalHeaderAmount' import { Label } from './SwapModalHeaderAmount'
const sixFigsFormatterRules: FormatterRule[] = [{ upperBound: Infinity, formatterOptions: SIX_SIG_FIGS_NO_COMMAS }]
const DetailsContainer = styled(Column)` const DetailsContainer = styled(Column)`
padding: 0 8px; padding: 0 8px;
` `
...@@ -78,11 +80,14 @@ export default function SwapModalFooter({ ...@@ -78,11 +80,14 @@ export default function SwapModalFooter({
const theme = useTheme() const theme = useTheme()
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const nativeCurrency = useNativeCurrency(chainId) const nativeCurrency = useNativeCurrency(chainId)
const { formatNumber } = useFormatter() const { formatCurrencyAmount, formatNumber, formatPriceImpact } = useFormatter()
const label = `${trade.executionPrice.baseCurrency?.symbol} ` const label = `${trade.executionPrice.baseCurrency?.symbol} `
const labelInverted = `${trade.executionPrice.quoteCurrency?.symbol}` const labelInverted = `${trade.executionPrice.quoteCurrency?.symbol}`
const formattedPrice = formatTransactionAmount(priceToPreciseFloat(trade.executionPrice)) const formattedPrice = formatNumber({
input: priceToPreciseFloat(trade.executionPrice),
type: NumberType.TokenTx,
})
const txCount = getTransactionCount(trade) const txCount = getTransactionCount(trade)
return ( return (
...@@ -164,8 +169,14 @@ export default function SwapModalFooter({ ...@@ -164,8 +169,14 @@ export default function SwapModalFooter({
</MouseoverTooltip> </MouseoverTooltip>
<DetailRowValue> <DetailRowValue>
{trade.tradeType === TradeType.EXACT_INPUT {trade.tradeType === TradeType.EXACT_INPUT
? `${trade.minimumAmountOut(allowedSlippage).toSignificant(6)} ${trade.outputAmount.currency.symbol}` ? `${formatCurrencyAmount({
: `${trade.maximumAmountIn(allowedSlippage).toSignificant(6)} ${trade.inputAmount.currency.symbol}`} amount: trade.minimumAmountOut(allowedSlippage),
type: sixFigsFormatterRules,
})} ${trade.outputAmount.currency.symbol}`
: `${formatCurrencyAmount({
amount: trade.maximumAmountIn(allowedSlippage),
type: sixFigsFormatterRules,
})} ${trade.inputAmount.currency.symbol}`}
</DetailRowValue> </DetailRowValue>
</Row> </Row>
</ThemedText.BodySmall> </ThemedText.BodySmall>
...@@ -223,6 +234,8 @@ export default function SwapModalFooter({ ...@@ -223,6 +234,8 @@ export default function SwapModalFooter({
} }
function TokenTaxLineItem({ trade, type }: { trade: ClassicTrade; type: 'input' | 'output' }) { function TokenTaxLineItem({ trade, type }: { trade: ClassicTrade; type: 'input' | 'output' }) {
const { formatPriceImpact } = useFormatter()
const [currency, percentage] = const [currency, percentage] =
type === 'input' ? [trade.inputAmount.currency, trade.inputTax] : [trade.outputAmount.currency, trade.outputTax] type === 'input' ? [trade.inputAmount.currency, trade.inputTax] : [trade.outputAmount.currency, trade.outputTax]
......
...@@ -10,7 +10,6 @@ import { Field } from 'state/swap/actions' ...@@ -10,7 +10,6 @@ import { Field } from 'state/swap/actions'
import styled from 'styled-components' import styled from 'styled-components'
import { BREAKPOINTS, ThemedText } from 'theme' import { BREAKPOINTS, ThemedText } from 'theme'
import { NumberType, useFormatter } from 'utils/formatNumbers' import { NumberType, useFormatter } from 'utils/formatNumbers'
import { formatReviewSwapCurrencyAmount } from 'utils/formatNumbers'
export const Label = styled(ThemedText.BodySmall)<{ cursor?: string }>` export const Label = styled(ThemedText.BodySmall)<{ cursor?: string }>`
cursor: ${({ cursor }) => cursor}; cursor: ${({ cursor }) => cursor};
...@@ -45,7 +44,7 @@ interface AmountProps { ...@@ -45,7 +44,7 @@ interface AmountProps {
} }
export function SwapModalHeaderAmount({ tooltipText, label, amount, usdAmount, field, currency }: AmountProps) { export function SwapModalHeaderAmount({ tooltipText, label, amount, usdAmount, field, currency }: AmountProps) {
const { formatNumber } = useFormatter() const { formatNumber, formatReviewSwapCurrencyAmount } = useFormatter()
return ( return (
<Row align="center" justify="space-between" gap="md"> <Row align="center" justify="space-between" gap="md">
......
...@@ -5,7 +5,7 @@ import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' ...@@ -5,7 +5,7 @@ import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
import { formatPrice, NumberType, useFormatter } from 'utils/formatNumbers' import { NumberType, useFormatter } from 'utils/formatNumbers'
interface TradePriceProps { interface TradePriceProps {
price: Price<Currency, Currency> price: Price<Currency, Currency>
...@@ -28,7 +28,7 @@ const StyledPriceContainer = styled.button` ...@@ -28,7 +28,7 @@ const StyledPriceContainer = styled.button`
` `
export default function TradePrice({ price }: TradePriceProps) { export default function TradePrice({ price }: TradePriceProps) {
const { formatNumber } = useFormatter() const { formatNumber, formatPrice } = useFormatter()
const [showInverted, setShowInverted] = useState<boolean>(false) const [showInverted, setShowInverted] = useState<boolean>(false)
...@@ -37,11 +37,11 @@ export default function TradePrice({ price }: TradePriceProps) { ...@@ -37,11 +37,11 @@ export default function TradePrice({ price }: TradePriceProps) {
const formattedPrice = useMemo(() => { const formattedPrice = useMemo(() => {
try { try {
return formatPrice(showInverted ? price : price.invert(), NumberType.TokenTx) return formatPrice({ price: showInverted ? price : price.invert(), type: NumberType.TokenTx })
} catch { } catch {
return '0' return '0'
} }
}, [price, showInverted]) }, [formatPrice, price, showInverted])
const label = showInverted ? `${price.quoteCurrency?.symbol}` : `${price.baseCurrency?.symbol} ` const label = showInverted ? `${price.quoteCurrency?.symbol}` : `${price.baseCurrency?.symbol} `
const labelInverted = showInverted ? `${price.baseCurrency?.symbol} ` : `${price.quoteCurrency?.symbol}` const labelInverted = showInverted ? `${price.baseCurrency?.symbol} ` : `${price.quoteCurrency?.symbol}`
......
...@@ -37,7 +37,7 @@ import { ExternalLink, HideExtraSmall, HideSmall, StyledRouterLink, ThemedText } ...@@ -37,7 +37,7 @@ import { ExternalLink, HideExtraSmall, HideSmall, StyledRouterLink, ThemedText }
import { currencyId } from 'utils/currencyId' import { currencyId } from 'utils/currencyId'
import { WrongChainError } from 'utils/errors' import { WrongChainError } from 'utils/errors'
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
import { formatPrice, NumberType } from 'utils/formatNumbers' import { NumberType, useFormatter } from 'utils/formatNumbers'
import { formatTickPrice } from 'utils/formatTickPrice' import { formatTickPrice } from 'utils/formatTickPrice'
import { unwrappedToken } from 'utils/unwrappedToken' import { unwrappedToken } from 'utils/unwrappedToken'
...@@ -179,6 +179,8 @@ function CurrentPriceCard({ ...@@ -179,6 +179,8 @@ function CurrentPriceCard({
currencyQuote?: Currency currencyQuote?: Currency
currencyBase?: Currency currencyBase?: Currency
}) { }) {
const { formatPrice } = useFormatter()
if (!pool || !currencyQuote || !currencyBase) { if (!pool || !currencyQuote || !currencyBase) {
return null return null
} }
...@@ -190,7 +192,7 @@ function CurrentPriceCard({ ...@@ -190,7 +192,7 @@ function CurrentPriceCard({
<Trans>Current price</Trans> <Trans>Current price</Trans>
</ExtentsText> </ExtentsText>
<ThemedText.DeprecatedMediumHeader textAlign="center"> <ThemedText.DeprecatedMediumHeader textAlign="center">
{formatPrice(inverted ? pool.token1Price : pool.token0Price, NumberType.TokenTx)} {formatPrice({ price: inverted ? pool.token1Price : pool.token0Price, type: NumberType.TokenTx })}
</ThemedText.DeprecatedMediumHeader> </ThemedText.DeprecatedMediumHeader>
<ExtentsText> <ExtentsText>
<Trans> <Trans>
......
...@@ -8,7 +8,6 @@ import { ...@@ -8,7 +8,6 @@ import {
formatPriceImpact, formatPriceImpact,
formatReviewSwapCurrencyAmount, formatReviewSwapCurrencyAmount,
formatSlippage, formatSlippage,
formatTransactionAmount,
formatUSDPrice, formatUSDPrice,
NumberType, NumberType,
priceToPreciseFloat, priceToPreciseFloat,
...@@ -513,53 +512,6 @@ describe('priceToPreciseFloat', () => { ...@@ -513,53 +512,6 @@ describe('priceToPreciseFloat', () => {
}) })
}) })
describe('formatTransactionAmount', () => {
it('undefined or null', () => {
expect(formatTransactionAmount(undefined)).toEqual('')
expect(formatTransactionAmount(null)).toEqual('')
})
it('0', () => {
expect(formatTransactionAmount(0)).toEqual('0.00')
})
it('< 0.00001', () => {
expect(formatTransactionAmount(0.000000001)).toEqual('<0.00001')
})
it('1 > number ≥ .00001 full precision', () => {
expect(formatTransactionAmount(0.987654321)).toEqual('0.98765')
})
it('1 > number ≥ .00001 minimum 2 decimals', () => {
expect(formatTransactionAmount(0.9)).toEqual('0.90')
})
it('1 > number ≥ .00001 no trailing zeros beyond 2nd decimal', () => {
expect(formatTransactionAmount(0.901000123)).toEqual('0.901')
})
it('10,000 > number ≥ 1 round to 6 sig figs', () => {
expect(formatTransactionAmount(7654.3210789)).toEqual('7,654.32')
})
it('10,000 > number ≥ 1 round to 6 sig figs 2nd case', () => {
expect(formatTransactionAmount(76.3210789)).toEqual('76.3211')
})
it('10,000 > number ≥ 1 no trailing zeros beyond 2nd decimal place', () => {
expect(formatTransactionAmount(7.60000054321)).toEqual('7.60')
})
it('10,000 > number ≥ 1 always show at least 2 decimal places', () => {
expect(formatTransactionAmount(7)).toEqual('7.00')
})
it('1M > number ≥ 10,000 few decimals', () => {
expect(formatTransactionAmount(765432.1)).toEqual('765,432.10')
})
it('1M > number ≥ 10,000 lots of decimals', () => {
expect(formatTransactionAmount(76543.2123424)).toEqual('76,543.21')
})
it('Number ≥ 1M', () => {
expect(formatTransactionAmount(1234567.8901)).toEqual('1,234,567.89')
})
it('Number ≥ 1M extra long', () => {
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
expect(formatTransactionAmount(1234567890123456.789)).toEqual('1.234568e+15')
})
})
describe('formatReviewSwapCurrencyAmount', () => { describe('formatReviewSwapCurrencyAmount', () => {
it('should use TokenTx formatting under a default length', () => { it('should use TokenTx formatting under a default length', () => {
const currencyAmount = CurrencyAmount.fromRawAmount(USDC_MAINNET, '2000000000') // 2,000 USDC const currencyAmount = CurrencyAmount.fromRawAmount(USDC_MAINNET, '2000000000') // 2,000 USDC
......
This diff is collapsed.
import { Percent } from '@uniswap/sdk-core'
import formatPriceImpact from './formatPriceImpact'
describe('formatPriceImpact', () => {
it('formats price impact', () => {
expect(formatPriceImpact(new Percent(5, 10_000))).toEqual('-0.05%')
})
// While there's theoretically no such thing as "positive price impact", this can show up
// due to a bug in routing-api, so it's still tested for
it('formats price impact when given a negative value', () => {
expect(formatPriceImpact(new Percent(-5, 10_000))).toEqual('0.05%')
})
})
import { Percent } from '@uniswap/sdk-core'
export default function formatPriceImpact(priceImpact: Percent) {
return `${priceImpact.multiply(-1).toFixed(2)}%`
}
...@@ -20,5 +20,5 @@ export function formatTickPrice({ price, atLimit, direction, placeholder, number ...@@ -20,5 +20,5 @@ export function formatTickPrice({ price, atLimit, direction, placeholder, number
return placeholder return placeholder
} }
return formatPrice(price, numberType ?? NumberType.TokenNonTx) return formatPrice({ price, type: numberType ?? NumberType.TokenNonTx })
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment