refactor: consolidate percent formatting util (#7467)
* refactor: consolidate percent formatting util * refactor: use generic percent formatter * fix: add descriptive comment for formatDelta
This commit is contained in:
parent
c5f2df4bc0
commit
86fc15907a
@ -161,7 +161,7 @@ export default function AuthenticatedHeader({ account, openSettings }: { account
|
||||
const clearCollectionFilters = useWalletCollections((state) => state.clearCollectionFilters)
|
||||
const isClaimAvailable = useIsNftClaimAvailable((state) => state.isClaimAvailable)
|
||||
const shouldShowBuyFiatButton = useIsNotOriginCountry('GB')
|
||||
const { formatNumber, formatPercent } = useFormatter()
|
||||
const { formatNumber, formatDelta } = useFormatter()
|
||||
|
||||
const shouldDisableNFTRoutes = useDisableNFTRoutes()
|
||||
|
||||
@ -284,7 +284,7 @@ export default function AuthenticatedHeader({ account, openSettings }: { account
|
||||
{`${formatNumber({
|
||||
input: Math.abs(absoluteChange as number),
|
||||
type: NumberType.PortfolioBalance,
|
||||
})} (${formatPercent(percentChange)})`}
|
||||
})} (${formatDelta(percentChange)})`}
|
||||
</ThemedText.BodySecondary>
|
||||
</>
|
||||
)}
|
||||
|
@ -72,7 +72,7 @@ const TokenNameText = styled(ThemedText.SubHeader)`
|
||||
type PortfolioToken = NonNullable<TokenBalance['token']>
|
||||
|
||||
function TokenRow({ token, quantity, denominatedValue, tokenProjectMarket }: TokenBalance & { token: PortfolioToken }) {
|
||||
const { formatPercent } = useFormatter()
|
||||
const { formatDelta } = useFormatter()
|
||||
const percentChange = tokenProjectMarket?.pricePercentChange?.value ?? 0
|
||||
|
||||
const navigate = useNavigate()
|
||||
@ -124,7 +124,7 @@ function TokenRow({ token, quantity, denominatedValue, tokenProjectMarket }: Tok
|
||||
</ThemedText.SubHeader>
|
||||
<Row justify="flex-end">
|
||||
<DeltaArrow delta={percentChange} />
|
||||
<ThemedText.BodySecondary>{formatPercent(percentChange)}</ThemedText.BodySecondary>
|
||||
<ThemedText.BodySecondary>{formatDelta(percentChange)}</ThemedText.BodySecondary>
|
||||
</Row>
|
||||
</>
|
||||
)
|
||||
|
@ -52,11 +52,11 @@ interface ChartDeltaProps {
|
||||
|
||||
function ChartDelta({ startingPrice, endingPrice, noColor }: ChartDeltaProps) {
|
||||
const delta = calculateDelta(startingPrice.value, endingPrice.value)
|
||||
const { formatPercent } = useFormatter()
|
||||
const { formatDelta } = useFormatter()
|
||||
|
||||
return (
|
||||
<DeltaContainer>
|
||||
{formatPercent(delta)}
|
||||
{formatDelta(delta)}
|
||||
<DeltaArrow delta={delta} noColor={noColor} />
|
||||
</DeltaContainer>
|
||||
)
|
||||
|
@ -22,7 +22,7 @@ export function FiatValue({
|
||||
fiatValue: { data?: number; isLoading: boolean }
|
||||
priceImpact?: Percent
|
||||
}) {
|
||||
const { formatNumber, formatPriceImpact } = useFormatter()
|
||||
const { formatNumber, formatPercent } = useFormatter()
|
||||
|
||||
const priceImpactColor = useMemo(() => {
|
||||
if (!priceImpact) return undefined
|
||||
@ -54,7 +54,7 @@ export function FiatValue({
|
||||
<MouseoverTooltip
|
||||
text={<Trans>The estimated difference between the USD values of input and output amounts.</Trans>}
|
||||
>
|
||||
(<Trans>{formatPriceImpact(priceImpact)}</Trans>)
|
||||
(<Trans>{formatPercent(priceImpact.multiply(-1))}</Trans>)
|
||||
</MouseoverTooltip>
|
||||
</ThemedText.BodySmall>
|
||||
)}
|
||||
|
@ -129,7 +129,7 @@ interface TokenRowProps {
|
||||
export const TokenRow = ({ token, isHovered, setHoveredIndex, toggleOpen, index, eventProperties }: TokenRowProps) => {
|
||||
const addRecentlySearchedAsset = useAddRecentlySearchedAsset()
|
||||
const navigate = useNavigate()
|
||||
const { formatFiatPrice, formatPercent } = useFormatter()
|
||||
const { formatFiatPrice, formatDelta } = useFormatter()
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
const address = !token.address && token.standard === TokenStandard.Native ? 'NATIVE' : token.address
|
||||
@ -194,7 +194,7 @@ export const TokenRow = ({ token, isHovered, setHoveredIndex, toggleOpen, index,
|
||||
<DeltaArrow delta={token.market?.pricePercentChange?.value} />
|
||||
<ThemedText.BodySmall>
|
||||
<DeltaText delta={token.market?.pricePercentChange?.value}>
|
||||
{formatPercent(Math.abs(token.market?.pricePercentChange?.value ?? 0))}
|
||||
{formatDelta(Math.abs(token.market?.pricePercentChange?.value ?? 0))}
|
||||
</DeltaText>
|
||||
</ThemedText.BodySmall>
|
||||
</PriceChangeContainer>
|
||||
|
@ -38,23 +38,23 @@ const NUMBER_WITH_MAX_TWO_DECIMAL_PLACES = /^(?:\d*\.\d{0,2}|\d+)$/
|
||||
const MINIMUM_RECOMMENDED_SLIPPAGE = new Percent(5, 10_000)
|
||||
const MAXIMUM_RECOMMENDED_SLIPPAGE = new Percent(1, 100)
|
||||
|
||||
function useFormatSlippageInput() {
|
||||
const { formatSlippage } = useFormatter()
|
||||
function useFormatPercentInput() {
|
||||
const { formatPercent } = useFormatter()
|
||||
|
||||
return (slippage: Percent) => formatSlippage(slippage).slice(0, -1) // remove % sign
|
||||
return (slippage: Percent) => formatPercent(slippage).slice(0, -1) // remove % sign
|
||||
}
|
||||
|
||||
export default function MaxSlippageSettings({ autoSlippage }: { autoSlippage: Percent }) {
|
||||
const [userSlippageTolerance, setUserSlippageTolerance] = useUserSlippageTolerance()
|
||||
const { formatSlippage } = useFormatter()
|
||||
const formatSlippageInput = useFormatSlippageInput()
|
||||
const { formatPercent } = useFormatter()
|
||||
const formatPercentInput = useFormatPercentInput()
|
||||
|
||||
// In order to trigger `custom` mode, we need to set `userSlippageTolerance` to a value that is not `auto`.
|
||||
// To do so, we use `autoSlippage` value. However, since users are likely to change that value,
|
||||
// we render it as a placeholder instead of a value.
|
||||
const defaultSlippageInputValue =
|
||||
userSlippageTolerance !== SlippageTolerance.Auto && !userSlippageTolerance.equalTo(autoSlippage)
|
||||
? formatSlippageInput(userSlippageTolerance)
|
||||
? formatPercentInput(userSlippageTolerance)
|
||||
: ''
|
||||
|
||||
// If user has previously entered a custom slippage, we want to show that value in the input field
|
||||
@ -124,7 +124,7 @@ export default function MaxSlippageSettings({ autoSlippage }: { autoSlippage: Pe
|
||||
{userSlippageTolerance === SlippageTolerance.Auto ? (
|
||||
<Trans>Auto</Trans>
|
||||
) : (
|
||||
formatSlippage(userSlippageTolerance)
|
||||
formatPercent(userSlippageTolerance)
|
||||
)}
|
||||
</ThemedText.BodyPrimary>
|
||||
}
|
||||
@ -158,7 +158,7 @@ export default function MaxSlippageSettings({ autoSlippage }: { autoSlippage: Pe
|
||||
<InputContainer gap="md" error={!!slippageError}>
|
||||
<Input
|
||||
data-testid="slippage-input"
|
||||
placeholder={formatSlippageInput(autoSlippage)}
|
||||
placeholder={formatPercentInput(autoSlippage)}
|
||||
value={slippageInput}
|
||||
onChange={(e) => parseSlippageInput(e.target.value)}
|
||||
onBlur={() => {
|
||||
@ -176,7 +176,7 @@ export default function MaxSlippageSettings({ autoSlippage }: { autoSlippage: Pe
|
||||
<ThemedText.BodySmall color="deprecated_accentWarning">
|
||||
{tooLow ? (
|
||||
<Trans>
|
||||
Slippage below {formatSlippage(MINIMUM_RECOMMENDED_SLIPPAGE)} may result in a failed transaction
|
||||
Slippage below {formatPercent(MINIMUM_RECOMMENDED_SLIPPAGE)} may result in a failed transaction
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans>Your transaction may be frontrun and result in an unfavorable trade.</Trans>
|
||||
|
@ -49,7 +49,7 @@ const IconContainerWithSlippage = styled(IconContainer)<{ displayWarning?: boole
|
||||
|
||||
const ButtonContent = ({ trade }: { trade?: InterfaceTrade }) => {
|
||||
const [userSlippageTolerance] = useUserSlippageTolerance()
|
||||
const { formatSlippage } = useFormatter()
|
||||
const { formatPercent } = useFormatter()
|
||||
|
||||
if (userSlippageTolerance === SlippageTolerance.Auto || isUniswapXTrade(trade)) {
|
||||
return (
|
||||
@ -64,7 +64,7 @@ const ButtonContent = ({ trade }: { trade?: InterfaceTrade }) => {
|
||||
return (
|
||||
<IconContainerWithSlippage data-testid="settings-icon-with-slippage" gap="sm" displayWarning={isInvalidSlippage}>
|
||||
<ThemedText.BodySmall>
|
||||
<Trans>{formatSlippage(userSlippageTolerance)} slippage</Trans>
|
||||
<Trans>{formatPercent(userSlippageTolerance)} slippage</Trans>
|
||||
</ThemedText.BodySmall>
|
||||
<Icon />
|
||||
</IconContainerWithSlippage>
|
||||
|
@ -442,7 +442,7 @@ interface LoadedRowProps {
|
||||
|
||||
/* Loaded State: row component with token information */
|
||||
export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HTMLDivElement>) => {
|
||||
const { formatFiatPrice, formatNumber, formatPercent } = useFormatter()
|
||||
const { formatFiatPrice, formatNumber, formatDelta } = useFormatter()
|
||||
|
||||
const { tokenListIndex, tokenListLength, token, sortRank } = props
|
||||
const filterString = useAtomValue(filterStringAtom)
|
||||
@ -451,7 +451,7 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT
|
||||
const chainId = supportedChainIdFromGQLChain(filterNetwork)
|
||||
const timePeriod = useAtomValue(filterTimeAtom)
|
||||
const delta = token.market?.pricePercentChange?.value
|
||||
const formattedDelta = formatPercent(delta)
|
||||
const formattedDelta = formatDelta(delta)
|
||||
|
||||
const exploreTokenSelectedEventProperties = {
|
||||
chain_id: chainId,
|
||||
|
@ -37,7 +37,7 @@ interface PriceImpactModalProps {
|
||||
}
|
||||
|
||||
export default function PriceImpactModal({ priceImpact, onDismiss, onContinue }: PriceImpactModalProps) {
|
||||
const { formatPriceImpact } = useFormatter()
|
||||
const { formatPercent } = useFormatter()
|
||||
|
||||
return (
|
||||
<Modal isOpen onDismiss={onDismiss}>
|
||||
@ -56,7 +56,7 @@ export default function PriceImpactModal({ priceImpact, onDismiss, onContinue }:
|
||||
<Trans>
|
||||
This transaction will result in a{' '}
|
||||
<ThemedText.BodyPrimary lineHeight="24px" color="critical" display="inline">
|
||||
{formatPriceImpact(priceImpact)}
|
||||
~{formatPercent(priceImpact)}
|
||||
</ThemedText.BodyPrimary>{' '}
|
||||
price impact on the market price of this pool. Do you wish to continue?
|
||||
</Trans>
|
||||
|
@ -20,7 +20,7 @@ interface PriceImpactWarningProps {
|
||||
}
|
||||
|
||||
export default function PriceImpactWarning({ priceImpact }: PriceImpactWarningProps) {
|
||||
const { formatPriceImpact } = useFormatter()
|
||||
const { formatPercent } = useFormatter()
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
@ -41,7 +41,7 @@ export default function PriceImpactWarning({ priceImpact }: PriceImpactWarningPr
|
||||
</ThemedText.DeprecatedSubHeader>
|
||||
</RowFixed>
|
||||
<ThemedText.DeprecatedLabel textAlign="right" fontSize={14} color="critical">
|
||||
{formatPriceImpact(priceImpact)}
|
||||
~{formatPercent(priceImpact)}
|
||||
</ThemedText.DeprecatedLabel>
|
||||
</RowBetween>
|
||||
</MouseoverTooltip>
|
||||
|
@ -103,9 +103,10 @@ function Loading({ width = 50 }: { width?: number }) {
|
||||
return <LoadingRow data-testid="loading-row" height={15} width={width} />
|
||||
}
|
||||
|
||||
function ColoredPercentRow({ percent }: { percent: Percent }) {
|
||||
const { formatSlippage } = useFormatter()
|
||||
return <ColorWrapper textColor={getPriceImpactColor(percent)}>{formatSlippage(percent)}</ColorWrapper>
|
||||
function ColoredPercentRow({ percent, estimate }: { percent: Percent; estimate?: boolean }) {
|
||||
const { formatPercent } = useFormatter()
|
||||
const formattedPercent = (estimate ? '~' : '') + formatPercent(percent)
|
||||
return <ColorWrapper textColor={getPriceImpactColor(percent)}>{formattedPercent}</ColorWrapper>
|
||||
}
|
||||
|
||||
function CurrencyAmountRow({ amount }: { amount: CurrencyAmount<Currency> }) {
|
||||
@ -136,7 +137,7 @@ type LineItemData = {
|
||||
|
||||
function useLineItem(props: SwapLineItemProps): LineItemData | undefined {
|
||||
const { trade, syncing, allowedSlippage, type } = props
|
||||
const { formatNumber, formatSlippage } = useFormatter()
|
||||
const { formatNumber, formatPercent } = useFormatter()
|
||||
const isAutoSlippage = useUserSlippageTolerance()[0] === SlippageTolerance.Auto
|
||||
const feesEnabled = useFeesEnabled()
|
||||
|
||||
@ -179,7 +180,7 @@ function useLineItem(props: SwapLineItemProps): LineItemData | undefined {
|
||||
return {
|
||||
Label: () => <Trans>Price impact</Trans>,
|
||||
TooltipBody: () => <Trans>The impact your trade has on the market price of this pool.</Trans>,
|
||||
Value: () => (isPreview ? <Loading /> : <ColoredPercentRow percent={trade.priceImpact} />),
|
||||
Value: () => (isPreview ? <Loading /> : <ColoredPercentRow percent={trade.priceImpact} estimate />),
|
||||
}
|
||||
case SwapLineItemType.MAX_SLIPPAGE:
|
||||
return {
|
||||
@ -187,7 +188,7 @@ function useLineItem(props: SwapLineItemProps): LineItemData | undefined {
|
||||
TooltipBody: () => <MaxSlippageTooltip {...props} />,
|
||||
Value: () => (
|
||||
<Row gap="8px">
|
||||
{isAutoSlippage && <AutoBadge />} {formatSlippage(allowedSlippage)}
|
||||
{isAutoSlippage && <AutoBadge />} {formatPercent(allowedSlippage)}
|
||||
</Row>
|
||||
),
|
||||
}
|
||||
@ -197,7 +198,7 @@ function useLineItem(props: SwapLineItemProps): LineItemData | undefined {
|
||||
return {
|
||||
Label: () => (
|
||||
<>
|
||||
<Trans>Fee</Trans> {trade.swapFee && `(${formatSlippage(trade.swapFee.percent)})`}
|
||||
<Trans>Fee</Trans> {trade.swapFee && `(${formatPercent(trade.swapFee.percent)})`}
|
||||
</>
|
||||
),
|
||||
TooltipBody: () => <SwapFeeTooltipContent hasFee={Boolean(trade.swapFee)} />,
|
||||
|
@ -32,12 +32,12 @@ function RouteLabel({ trade }: { trade: SubmittableTrade }) {
|
||||
}
|
||||
|
||||
function PriceImpactRow({ trade }: { trade: ClassicTrade }) {
|
||||
const { formatPriceImpact } = useFormatter()
|
||||
const { formatPercent } = useFormatter()
|
||||
return (
|
||||
<ThemedText.BodySmall color="neutral2">
|
||||
<RowBetween>
|
||||
<Trans>Price Impact</Trans>
|
||||
<div>{formatPriceImpact(trade.priceImpact)}</div>
|
||||
<div>{formatPercent(trade.priceImpact)}</div>
|
||||
</RowBetween>
|
||||
</ThemedText.BodySmall>
|
||||
)
|
||||
|
@ -347,7 +347,7 @@ exports[`SwapDetailsDropdown.tsx renders a trade 1`] = `
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
-105566.373%
|
||||
~-105566.373%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1661,7 +1661,7 @@ exports[`SwapLineItem.tsx exact input 1`] = `
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
-105566.373%
|
||||
~-105566.373%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -3328,7 +3328,7 @@ exports[`SwapLineItem.tsx exact input api 1`] = `
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
-105566.373%
|
||||
~-105566.373%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -4995,7 +4995,7 @@ exports[`SwapLineItem.tsx exact output 1`] = `
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
-105566.373%
|
||||
~-105566.373%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -6870,7 +6870,7 @@ exports[`SwapLineItem.tsx fee on buy 1`] = `
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
-105566.373%
|
||||
~-105566.373%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -8745,7 +8745,7 @@ exports[`SwapLineItem.tsx fee on sell 1`] = `
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
-105566.373%
|
||||
~-105566.373%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -287,7 +287,7 @@ exports[`SwapModalFooter.tsx matches base snapshot, test trade exact input 1`] =
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
-105566.373%
|
||||
~-105566.373%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -204,7 +204,7 @@ const StatItemText = styled(Text)`
|
||||
`
|
||||
|
||||
function StatItem({ title, value, delta }: { title: ReactNode; value: number; delta?: number }) {
|
||||
const { formatNumber, formatPercent } = useFormatter()
|
||||
const { formatNumber, formatDelta } = useFormatter()
|
||||
|
||||
return (
|
||||
<StatItemColumn>
|
||||
@ -219,7 +219,7 @@ function StatItem({ title, value, delta }: { title: ReactNode; value: number; de
|
||||
{!!delta && (
|
||||
<Row width="max-content" padding="4px 0px">
|
||||
<DeltaArrow delta={delta} />
|
||||
<ThemedText.BodySecondary>{formatPercent(delta)}</ThemedText.BodySecondary>
|
||||
<ThemedText.BodySecondary>{formatDelta(delta)}</ThemedText.BodySecondary>
|
||||
</Row>
|
||||
)}
|
||||
</StatsTextContainer>
|
||||
|
@ -356,71 +356,37 @@ describe('formatUSDPrice', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('formatPriceImpact', () => {
|
||||
describe('formatPercent', () => {
|
||||
beforeEach(() => {
|
||||
mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1.0, isLoading: false })
|
||||
mocked(useCurrencyConversionFlagEnabled).mockReturnValue(true)
|
||||
})
|
||||
|
||||
it('should correctly format undefined', () => {
|
||||
const { formatPriceImpact } = renderHook(() => useFormatter()).result.current
|
||||
const { formatPercent } = renderHook(() => useFormatter()).result.current
|
||||
|
||||
expect(formatPriceImpact(undefined)).toBe('-')
|
||||
})
|
||||
|
||||
it('correctly formats a percent with 3 significant digits', () => {
|
||||
const { formatPriceImpact } = renderHook(() => useFormatter()).result.current
|
||||
|
||||
expect(formatPriceImpact(new Percent(-1, 100000))).toBe('0.001%')
|
||||
expect(formatPriceImpact(new Percent(-1, 1000))).toBe('0.100%')
|
||||
expect(formatPriceImpact(new Percent(-1, 100))).toBe('1.000%')
|
||||
expect(formatPriceImpact(new Percent(-1, 10))).toBe('10.000%')
|
||||
expect(formatPriceImpact(new Percent(-1, 1))).toBe('100.000%')
|
||||
})
|
||||
|
||||
it('correctly formats a percent with 3 significant digits with french locale', () => {
|
||||
mocked(useActiveLocale).mockReturnValue('fr-FR')
|
||||
const { formatPriceImpact } = renderHook(() => useFormatter()).result.current
|
||||
|
||||
expect(formatPriceImpact(new Percent(-1, 100000))).toBe('0,001%')
|
||||
expect(formatPriceImpact(new Percent(-1, 1000))).toBe('0,100%')
|
||||
expect(formatPriceImpact(new Percent(-1, 100))).toBe('1,000%')
|
||||
expect(formatPriceImpact(new Percent(-1, 10))).toBe('10,000%')
|
||||
expect(formatPriceImpact(new Percent(-1, 1))).toBe('100,000%')
|
||||
})
|
||||
})
|
||||
|
||||
describe('formatSlippage', () => {
|
||||
beforeEach(() => {
|
||||
mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1.0, isLoading: false })
|
||||
mocked(useCurrencyConversionFlagEnabled).mockReturnValue(true)
|
||||
})
|
||||
|
||||
it('should correctly format undefined', () => {
|
||||
const { formatSlippage } = renderHook(() => useFormatter()).result.current
|
||||
|
||||
expect(formatSlippage(undefined)).toBe('-')
|
||||
expect(formatPercent(undefined)).toBe('-')
|
||||
})
|
||||
|
||||
it('correctly formats a percent with no trailing digits', () => {
|
||||
const { formatSlippage } = renderHook(() => useFormatter()).result.current
|
||||
const { formatPercent } = renderHook(() => useFormatter()).result.current
|
||||
|
||||
expect(formatSlippage(new Percent(1, 100000))).toBe('0.001%')
|
||||
expect(formatSlippage(new Percent(1, 1000))).toBe('0.1%')
|
||||
expect(formatSlippage(new Percent(1, 100))).toBe('1%')
|
||||
expect(formatSlippage(new Percent(1, 10))).toBe('10%')
|
||||
expect(formatSlippage(new Percent(1, 1))).toBe('100%')
|
||||
expect(formatPercent(new Percent(1, 100000))).toBe('0.001%')
|
||||
expect(formatPercent(new Percent(1, 1000))).toBe('0.1%')
|
||||
expect(formatPercent(new Percent(1, 100))).toBe('1%')
|
||||
expect(formatPercent(new Percent(1, 10))).toBe('10%')
|
||||
expect(formatPercent(new Percent(1, 1))).toBe('100%')
|
||||
})
|
||||
|
||||
it('correctly formats a percent with french locale', () => {
|
||||
mocked(useActiveLocale).mockReturnValue('fr-FR')
|
||||
const { formatSlippage } = renderHook(() => useFormatter()).result.current
|
||||
const { formatPercent } = renderHook(() => useFormatter()).result.current
|
||||
|
||||
expect(formatSlippage(new Percent(1, 100000))).toBe('0,001%')
|
||||
expect(formatSlippage(new Percent(1, 1000))).toBe('0,1%')
|
||||
expect(formatSlippage(new Percent(1, 100))).toBe('1%')
|
||||
expect(formatSlippage(new Percent(1, 10))).toBe('10%')
|
||||
expect(formatSlippage(new Percent(1, 1))).toBe('100%')
|
||||
expect(formatPercent(new Percent(1, 100000))).toBe('0,001%')
|
||||
expect(formatPercent(new Percent(1, 1000))).toBe('0,1%')
|
||||
expect(formatPercent(new Percent(1, 100))).toBe('1%')
|
||||
expect(formatPercent(new Percent(1, 10))).toBe('10%')
|
||||
expect(formatPercent(new Percent(1, 1))).toBe('100%')
|
||||
})
|
||||
})
|
||||
|
||||
@ -461,36 +427,36 @@ describe('formatReviewSwapCurrencyAmount', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('formatPercent', () => {
|
||||
describe('formatDelta', () => {
|
||||
beforeEach(() => {
|
||||
mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1.0, isLoading: false })
|
||||
mocked(useCurrencyConversionFlagEnabled).mockReturnValue(true)
|
||||
})
|
||||
|
||||
it.each([[null], [undefined], [Infinity], [NaN]])('should correctly format %p', (value) => {
|
||||
const { formatPercent } = renderHook(() => useFormatter()).result.current
|
||||
const { formatDelta } = renderHook(() => useFormatter()).result.current
|
||||
|
||||
expect(formatPercent(value)).toBe('-')
|
||||
expect(formatDelta(value)).toBe('-')
|
||||
})
|
||||
|
||||
it('correctly formats a percent with 2 decimal places', () => {
|
||||
const { formatPercent } = renderHook(() => useFormatter()).result.current
|
||||
const { formatDelta } = renderHook(() => useFormatter()).result.current
|
||||
|
||||
expect(formatPercent(0)).toBe('0.00%')
|
||||
expect(formatPercent(0.1)).toBe('0.10%')
|
||||
expect(formatPercent(1)).toBe('1.00%')
|
||||
expect(formatPercent(10)).toBe('10.00%')
|
||||
expect(formatPercent(100)).toBe('100.00%')
|
||||
expect(formatDelta(0)).toBe('0.00%')
|
||||
expect(formatDelta(0.1)).toBe('0.10%')
|
||||
expect(formatDelta(1)).toBe('1.00%')
|
||||
expect(formatDelta(10)).toBe('10.00%')
|
||||
expect(formatDelta(100)).toBe('100.00%')
|
||||
})
|
||||
|
||||
it('correctly formats a percent with 2 decimal places in french locale', () => {
|
||||
mocked(useActiveLocale).mockReturnValue('fr-FR')
|
||||
const { formatPercent } = renderHook(() => useFormatter()).result.current
|
||||
const { formatDelta } = renderHook(() => useFormatter()).result.current
|
||||
|
||||
expect(formatPercent(0)).toBe('0,00%')
|
||||
expect(formatPercent(0.1)).toBe('0,10%')
|
||||
expect(formatPercent(1)).toBe('1,00%')
|
||||
expect(formatPercent(10)).toBe('10,00%')
|
||||
expect(formatPercent(100)).toBe('100,00%')
|
||||
expect(formatDelta(0)).toBe('0,00%')
|
||||
expect(formatDelta(0.1)).toBe('0,10%')
|
||||
expect(formatDelta(1)).toBe('1,00%')
|
||||
expect(formatDelta(10)).toBe('10,00%')
|
||||
expect(formatDelta(100)).toBe('100,00%')
|
||||
})
|
||||
})
|
||||
|
@ -466,31 +466,22 @@ function formatCurrencyAmount({
|
||||
})
|
||||
}
|
||||
|
||||
function formatPriceImpact(priceImpact: Percent | undefined, locale: SupportedLocale = DEFAULT_LOCALE): string {
|
||||
if (!priceImpact) return '-'
|
||||
function formatPercent(percent: Percent | undefined, locale: SupportedLocale = DEFAULT_LOCALE) {
|
||||
if (!percent) return '-'
|
||||
|
||||
return `${Number(priceImpact.multiply(-1).toFixed(3)).toLocaleString(locale, {
|
||||
minimumFractionDigits: 3,
|
||||
return `${Number(percent.toFixed(3)).toLocaleString(locale, {
|
||||
maximumFractionDigits: 3,
|
||||
useGrouping: false,
|
||||
})}%`
|
||||
}
|
||||
|
||||
function formatSlippage(slippage: Percent | undefined, locale: SupportedLocale = DEFAULT_LOCALE) {
|
||||
if (!slippage) return '-'
|
||||
|
||||
return `${Number(slippage.toFixed(3)).toLocaleString(locale, {
|
||||
maximumFractionDigits: 3,
|
||||
useGrouping: false,
|
||||
})}%`
|
||||
}
|
||||
|
||||
function formatPercent(percent: Nullish<number>, locale: SupportedLocale = DEFAULT_LOCALE) {
|
||||
if (percent === null || percent === undefined || percent === Infinity || isNaN(percent)) {
|
||||
// Used to format floats representing percent change with fixed decimal places
|
||||
function formatDelta(delta: Nullish<number>, locale: SupportedLocale = DEFAULT_LOCALE) {
|
||||
if (delta === null || delta === undefined || delta === Infinity || isNaN(delta)) {
|
||||
return '-'
|
||||
}
|
||||
|
||||
return `${Number(Math.abs(percent).toFixed(2)).toLocaleString(locale, {
|
||||
return `${Number(Math.abs(delta).toFixed(2)).toLocaleString(locale, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
useGrouping: false,
|
||||
@ -694,21 +685,11 @@ export function useFormatter() {
|
||||
[currencyToFormatWith, formatterLocale, localCurrencyConversionRateToFormatWith]
|
||||
)
|
||||
|
||||
const formatPriceImpactWithLocales = useCallback(
|
||||
(priceImpact: Percent | undefined) => formatPriceImpact(priceImpact, formatterLocale),
|
||||
[formatterLocale]
|
||||
)
|
||||
|
||||
const formatReviewSwapCurrencyAmountWithLocales = useCallback(
|
||||
(amount: CurrencyAmount<Currency>) => formatReviewSwapCurrencyAmount(amount, formatterLocale),
|
||||
[formatterLocale]
|
||||
)
|
||||
|
||||
const formatSlippageWithLocales = useCallback(
|
||||
(slippage: Percent | undefined) => formatSlippage(slippage, formatterLocale),
|
||||
[formatterLocale]
|
||||
)
|
||||
|
||||
const formatTickPriceWithLocales = useCallback(
|
||||
(options: Omit<FormatTickPriceOptions, LocalesType>) =>
|
||||
formatTickPrice({
|
||||
@ -742,8 +723,13 @@ export function useFormatter() {
|
||||
[currencyToFormatWith, formatterLocale, localCurrencyConversionRateToFormatWith]
|
||||
)
|
||||
|
||||
const formatDeltaWithLocales = useCallback(
|
||||
(percent: Nullish<number>) => formatDelta(percent, formatterLocale),
|
||||
[formatterLocale]
|
||||
)
|
||||
|
||||
const formatPercentWithLocales = useCallback(
|
||||
(percent: Nullish<number>) => formatPercent(percent, formatterLocale),
|
||||
(percent: Percent | undefined) => formatPercent(percent, formatterLocale),
|
||||
[formatterLocale]
|
||||
)
|
||||
|
||||
@ -753,11 +739,10 @@ export function useFormatter() {
|
||||
formatFiatPrice: formatFiatPriceWithLocales,
|
||||
formatNumber: formatNumberWithLocales,
|
||||
formatNumberOrString: formatNumberOrStringWithLocales,
|
||||
formatDelta: formatDeltaWithLocales,
|
||||
formatPercent: formatPercentWithLocales,
|
||||
formatPrice: formatPriceWithLocales,
|
||||
formatPriceImpact: formatPriceImpactWithLocales,
|
||||
formatReviewSwapCurrencyAmount: formatReviewSwapCurrencyAmountWithLocales,
|
||||
formatSlippage: formatSlippageWithLocales,
|
||||
formatTickPrice: formatTickPriceWithLocales,
|
||||
}),
|
||||
[
|
||||
@ -765,11 +750,10 @@ export function useFormatter() {
|
||||
formatFiatPriceWithLocales,
|
||||
formatNumberOrStringWithLocales,
|
||||
formatNumberWithLocales,
|
||||
formatDeltaWithLocales,
|
||||
formatPercentWithLocales,
|
||||
formatPriceImpactWithLocales,
|
||||
formatPriceWithLocales,
|
||||
formatReviewSwapCurrencyAmountWithLocales,
|
||||
formatSlippageWithLocales,
|
||||
formatTickPriceWithLocales,
|
||||
]
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user