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