Commit 184d515e authored by Jack Short's avatar Jack Short Committed by GitHub

chore: formatter to use local currency price (#7273)

* chore: updating formatCurrencyAmount to handle multiple langs and currencies

* missed advanced swap details

* missed confirmed swap modal

* removing updating visual effects

* removing it from parseLocale

* chore: displaying local currency and language formatting

* making effects visible

* moving to hook

* useFormatCurrencyAmount

* moving it to useformatter hook

* exporting formatting locales

* missed one parsed remote

* initial passover of using conversion rate in formatting function

* moving hook to bottom of file

* moving to bottom

* moving to bottom

* fallback to usd

* refactors

* better fallback protection

* moving to function

* fixing typecheck
parent 86e4dd51
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core' import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import Column, { AutoColumn } from 'components/Column' import Column, { AutoColumn } from 'components/Column'
import { useLocalCurrencyPrice } from 'hooks/useLocalCurrencyPrice' import { useUSDPrice } from 'hooks/useUSDPrice'
import { InterfaceTrade } from 'state/routing/types' import { InterfaceTrade } from 'state/routing/types'
import { Field } from 'state/swap/actions' import { Field } from 'state/swap/actions'
import styled from 'styled-components' import styled from 'styled-components'
...@@ -26,8 +26,8 @@ export default function SwapModalHeader({ ...@@ -26,8 +26,8 @@ export default function SwapModalHeader({
inputCurrency?: Currency inputCurrency?: Currency
allowedSlippage: Percent allowedSlippage: Percent
}) { }) {
const fiatValueInput = useLocalCurrencyPrice(trade.inputAmount) const fiatValueInput = useUSDPrice(trade.inputAmount)
const fiatValueOutput = useLocalCurrencyPrice(trade.postTaxOutputAmount) const fiatValueOutput = useUSDPrice(trade.postTaxOutputAmount)
return ( return (
<HeaderContainer gap="sm"> <HeaderContainer gap="sm">
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, Price } from '@uniswap/sdk-core' import { Currency, Price } from '@uniswap/sdk-core'
import { useLocalCurrencyPrice } from 'hooks/useLocalCurrencyPrice' import { useUSDPrice } from 'hooks/useUSDPrice'
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' 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'
...@@ -33,9 +33,7 @@ export default function TradePrice({ price }: TradePriceProps) { ...@@ -33,9 +33,7 @@ export default function TradePrice({ price }: TradePriceProps) {
const [showInverted, setShowInverted] = useState<boolean>(false) const [showInverted, setShowInverted] = useState<boolean>(false)
const { baseCurrency, quoteCurrency } = price const { baseCurrency, quoteCurrency } = price
const { data: usdPrice } = useLocalCurrencyPrice( const { data: usdPrice } = useUSDPrice(tryParseCurrencyAmount('1', showInverted ? baseCurrency : quoteCurrency))
tryParseCurrencyAmount('1', showInverted ? baseCurrency : quoteCurrency)
)
const formattedPrice = useMemo(() => { const formattedPrice = useMemo(() => {
try { try {
......
import { Currency } from 'graphql/data/__generated__/types-and-hooks'
import { useLocalCurrencyConversionRate } from 'graphql/data/ConversionRate'
import { useActiveLocalCurrency } from './useActiveLocalCurrency'
import { useUSDPrice } from './useUSDPrice'
type useUSDPriceParameters = Parameters<typeof useUSDPrice>
export function useLocalCurrencyPrice(...useUSDPriceParameters: useUSDPriceParameters) {
const activeLocalCurrency = useActiveLocalCurrency()
const activeLocalCurrencyIsUSD = activeLocalCurrency === Currency.Usd
const { data: usdPrice, isLoading: isUSDPriceLoading } = useUSDPrice(...useUSDPriceParameters)
const { data: localCurrencyConversionRate, isLoading: isLocalCurrencyConversionRateLoading } =
useLocalCurrencyConversionRate(activeLocalCurrency, activeLocalCurrencyIsUSD)
if (activeLocalCurrencyIsUSD) {
return { data: usdPrice, isLoading: isUSDPriceLoading }
}
const isLoading = isUSDPriceLoading || isLocalCurrencyConversionRateLoading
if (!usdPrice || !localCurrencyConversionRate) {
return { data: undefined, isLoading }
}
return { data: usdPrice * localCurrencyConversionRate, isLoading: false }
}
import { formatEther } from '@ethersproject/units' import { formatEther } from '@ethersproject/units'
import { ChainId } from '@uniswap/sdk-core' import { ChainId } from '@uniswap/sdk-core'
import { useLocalCurrencyPrice } from 'hooks/useLocalCurrencyPrice' import { useUSDPrice } from 'hooks/useUSDPrice'
import useNativeCurrency from 'lib/hooks/useNativeCurrency' import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { GenieAsset } from 'nft/types' import { GenieAsset } from 'nft/types'
...@@ -8,7 +8,7 @@ import { GenieAsset } from 'nft/types' ...@@ -8,7 +8,7 @@ import { GenieAsset } from 'nft/types'
export const useNativeUsdPrice = (chainId: number = ChainId.MAINNET): number => { export const useNativeUsdPrice = (chainId: number = ChainId.MAINNET): number => {
const nativeCurrency = useNativeCurrency(chainId) const nativeCurrency = useNativeCurrency(chainId)
const parsedAmount = tryParseCurrencyAmount('1', nativeCurrency) const parsedAmount = tryParseCurrencyAmount('1', nativeCurrency)
const usdcValue = useLocalCurrencyPrice(parsedAmount)?.data ?? 0 const usdcValue = useUSDPrice(parsedAmount)?.data ?? 0
return usdcValue return usdcValue
} }
......
...@@ -35,12 +35,12 @@ import { getSwapCurrencyId, TOKEN_SHORTHANDS } from 'constants/tokens' ...@@ -35,12 +35,12 @@ import { getSwapCurrencyId, TOKEN_SHORTHANDS } from 'constants/tokens'
import { useUniswapXDefaultEnabled } from 'featureFlags/flags/uniswapXDefault' import { useUniswapXDefaultEnabled } from 'featureFlags/flags/uniswapXDefault'
import { useCurrency, useDefaultActiveTokens } from 'hooks/Tokens' import { useCurrency, useDefaultActiveTokens } from 'hooks/Tokens'
import { useIsSwapUnsupported } from 'hooks/useIsSwapUnsupported' import { useIsSwapUnsupported } from 'hooks/useIsSwapUnsupported'
import { useLocalCurrencyPrice } from 'hooks/useLocalCurrencyPrice'
import { useMaxAmountIn } from 'hooks/useMaxAmountIn' import { useMaxAmountIn } from 'hooks/useMaxAmountIn'
import usePermit2Allowance, { AllowanceState } from 'hooks/usePermit2Allowance' import usePermit2Allowance, { AllowanceState } from 'hooks/usePermit2Allowance'
import usePrevious from 'hooks/usePrevious' import usePrevious from 'hooks/usePrevious'
import { SwapResult, useSwapCallback } from 'hooks/useSwapCallback' import { SwapResult, useSwapCallback } from 'hooks/useSwapCallback'
import { useSwitchChain } from 'hooks/useSwitchChain' import { useSwitchChain } from 'hooks/useSwitchChain'
import { useUSDPrice } from 'hooks/useUSDPrice'
import useWrapCallback, { WrapErrorText, WrapType } from 'hooks/useWrapCallback' import useWrapCallback, { WrapErrorText, WrapType } from 'hooks/useWrapCallback'
import JSBI from 'jsbi' import JSBI from 'jsbi'
import { formatSwapQuoteReceivedEventProperties } from 'lib/utils/analytics' import { formatSwapQuoteReceivedEventProperties } from 'lib/utils/analytics'
...@@ -314,8 +314,8 @@ export function Swap({ ...@@ -314,8 +314,8 @@ export function Swap({
[independentField, parsedAmount, showWrap, trade] [independentField, parsedAmount, showWrap, trade]
) )
const fiatValueInput = useLocalCurrencyPrice(parsedAmounts[Field.INPUT], currencies[Field.INPUT] ?? undefined) const fiatValueInput = useUSDPrice(parsedAmounts[Field.INPUT], currencies[Field.INPUT] ?? undefined)
const fiatValueOutput = useLocalCurrencyPrice(parsedAmounts[Field.OUTPUT], currencies[Field.OUTPUT] ?? undefined) const fiatValueOutput = useUSDPrice(parsedAmounts[Field.OUTPUT], currencies[Field.OUTPUT] ?? undefined)
const showFiatValueInput = Boolean(parsedAmounts[Field.INPUT]) const showFiatValueInput = Boolean(parsedAmounts[Field.INPUT])
const showFiatValueOutput = Boolean(parsedAmounts[Field.OUTPUT]) const showFiatValueOutput = Boolean(parsedAmounts[Field.OUTPUT])
...@@ -328,9 +328,9 @@ export function Swap({ ...@@ -328,9 +328,9 @@ export function Swap({
[trade, tradeState] [trade, tradeState]
) )
const fiatValueTradeInput = useLocalCurrencyPrice(trade?.inputAmount) const fiatValueTradeInput = useUSDPrice(trade?.inputAmount)
const fiatValueTradeOutput = useLocalCurrencyPrice(trade?.postTaxOutputAmount) const fiatValueTradeOutput = useUSDPrice(trade?.postTaxOutputAmount)
const preTaxFiatValueTradeOutput = useLocalCurrencyPrice(trade?.outputAmount) const preTaxFiatValueTradeOutput = useUSDPrice(trade?.outputAmount)
const [stablecoinPriceImpact, preTaxStablecoinPriceImpact] = useMemo( const [stablecoinPriceImpact, preTaxStablecoinPriceImpact] = useMemo(
() => () =>
routeIsSyncing || !isClassicTrade(trade) routeIsSyncing || !isClassicTrade(trade)
......
...@@ -6,8 +6,11 @@ import { ...@@ -6,8 +6,11 @@ import {
} from 'constants/localCurrencies' } from 'constants/localCurrencies'
import { DEFAULT_LOCALE, SupportedLocale } from 'constants/locales' import { DEFAULT_LOCALE, SupportedLocale } from 'constants/locales'
import { useCurrencyConversionFlagEnabled } from 'featureFlags/flags/currencyConversion' import { useCurrencyConversionFlagEnabled } from 'featureFlags/flags/currencyConversion'
import { Currency as GqlCurrency } from 'graphql/data/__generated__/types-and-hooks'
import { useLocalCurrencyConversionRate } from 'graphql/data/ConversionRate'
import { useActiveLocalCurrency } from 'hooks/useActiveLocalCurrency' import { useActiveLocalCurrency } from 'hooks/useActiveLocalCurrency'
import { useActiveLocale } from 'hooks/useActiveLocale' import { useActiveLocale } from 'hooks/useActiveLocale'
import usePrevious from 'hooks/usePrevious'
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
type Nullish<T> = T | null | undefined type Nullish<T> = T | null | undefined
...@@ -362,12 +365,15 @@ const TYPE_TO_FORMATTER_RULES = { ...@@ -362,12 +365,15 @@ const TYPE_TO_FORMATTER_RULES = {
[NumberType.NFTCollectionStats]: ntfCollectionStatsFormatter, [NumberType.NFTCollectionStats]: ntfCollectionStatsFormatter,
} }
function getFormatterRule(input: number, type: NumberType): FormatterRule { function getFormatterRule(input: number, type: NumberType, conversionRate?: number): FormatterRule {
const rules = TYPE_TO_FORMATTER_RULES[type] const rules = TYPE_TO_FORMATTER_RULES[type]
for (const rule of rules) { for (const rule of rules) {
const shouldConvertInput = rule.formatterOptions.currency && conversionRate
const convertedInput = shouldConvertInput ? input * conversionRate : input
if ( if (
(rule.exact !== undefined && input === rule.exact) || (rule.exact !== undefined && convertedInput === rule.exact) ||
(rule.upperBound !== undefined && input < rule.upperBound) (rule.upperBound !== undefined && convertedInput < rule.upperBound)
) { ) {
return rule return rule
} }
...@@ -382,6 +388,7 @@ interface FormatNumberOptions { ...@@ -382,6 +388,7 @@ interface FormatNumberOptions {
placeholder?: string placeholder?: string
locale?: SupportedLocale locale?: SupportedLocale
localCurrency?: SupportedLocalCurrency localCurrency?: SupportedLocalCurrency
conversionRate?: number
} }
export function formatNumber({ export function formatNumber({
...@@ -390,14 +397,16 @@ export function formatNumber({ ...@@ -390,14 +397,16 @@ export function formatNumber({
placeholder = '-', placeholder = '-',
locale = DEFAULT_LOCALE, locale = DEFAULT_LOCALE,
localCurrency = DEFAULT_LOCAL_CURRENCY, localCurrency = DEFAULT_LOCAL_CURRENCY,
conversionRate,
}: FormatNumberOptions): string { }: FormatNumberOptions): string {
if (input === null || input === undefined) { if (input === null || input === undefined) {
return placeholder return placeholder
} }
const { hardCodedInput, formatterOptions } = getFormatterRule(input, type) const { hardCodedInput, formatterOptions } = getFormatterRule(input, type, conversionRate)
if (formatterOptions.currency) { if (formatterOptions.currency) {
input = conversionRate ? input * conversionRate : input
formatterOptions.currency = localCurrency formatterOptions.currency = localCurrency
formatterOptions.currencyDisplay = LOCAL_CURRENCY_SYMBOL_DISPLAY_TYPE[localCurrency] formatterOptions.currencyDisplay = LOCAL_CURRENCY_SYMBOL_DISPLAY_TYPE[localCurrency]
} }
...@@ -421,6 +430,7 @@ interface FormatCurrencyAmountOptions { ...@@ -421,6 +430,7 @@ interface FormatCurrencyAmountOptions {
placeholder?: string placeholder?: string
locale?: SupportedLocale locale?: SupportedLocale
localCurrency?: SupportedLocalCurrency localCurrency?: SupportedLocalCurrency
conversionRate?: number
} }
export function formatCurrencyAmount({ export function formatCurrencyAmount({
...@@ -429,6 +439,7 @@ export function formatCurrencyAmount({ ...@@ -429,6 +439,7 @@ export function formatCurrencyAmount({
placeholder, placeholder,
locale = DEFAULT_LOCALE, locale = DEFAULT_LOCALE,
localCurrency = DEFAULT_LOCAL_CURRENCY, localCurrency = DEFAULT_LOCAL_CURRENCY,
conversionRate,
}: FormatCurrencyAmountOptions): string { }: FormatCurrencyAmountOptions): string {
return formatNumber({ return formatNumber({
input: amount ? parseFloat(amount.toSignificant()) : undefined, input: amount ? parseFloat(amount.toSignificant()) : undefined,
...@@ -436,6 +447,7 @@ export function formatCurrencyAmount({ ...@@ -436,6 +447,7 @@ export function formatCurrencyAmount({
placeholder, placeholder,
locale, locale,
localCurrency, localCurrency,
conversionRate,
}) })
} }
...@@ -567,20 +579,61 @@ export function useFormatterLocales(): { ...@@ -567,20 +579,61 @@ export function useFormatterLocales(): {
} }
} }
function handleFallbackCurrency(
selectedCurrency: SupportedLocalCurrency,
previousSelectedCurrency: SupportedLocalCurrency | undefined,
shouldFallbackToUSD: boolean,
shouldFallbackToPrevious: boolean
) {
if (shouldFallbackToUSD) return DEFAULT_LOCAL_CURRENCY
if (shouldFallbackToPrevious) return previousSelectedCurrency
return selectedCurrency
}
// Constructs an object that injects the correct locale and local currency into each of the above formatter functions. // Constructs an object that injects the correct locale and local currency into each of the above formatter functions.
export function useFormatter() { export function useFormatter() {
const activeLocalCurrency = useActiveLocalCurrency()
const { formatterLocale, formatterLocalCurrency } = useFormatterLocales() const { formatterLocale, formatterLocalCurrency } = useFormatterLocales()
const activeLocalCurrencyIsUSD = activeLocalCurrency === GqlCurrency.Usd
const { data: localCurrencyConversionRate, isLoading: localCurrencyConversionRateIsLoading } =
useLocalCurrencyConversionRate(activeLocalCurrency, activeLocalCurrencyIsUSD)
const previousSelectedCurrency = usePrevious(activeLocalCurrency)
const previousConversionRate = usePrevious(localCurrencyConversionRate)
const shouldFallbackToPrevious = !localCurrencyConversionRate && localCurrencyConversionRateIsLoading
const shouldFallbackToUSD = !localCurrencyConversionRate && !localCurrencyConversionRateIsLoading
const currencyToFormatWith = handleFallbackCurrency(
formatterLocalCurrency,
previousSelectedCurrency,
shouldFallbackToUSD,
shouldFallbackToPrevious
)
const localCurrencyConversionRateToFormatWith = shouldFallbackToPrevious
? previousConversionRate
: localCurrencyConversionRate
const formatNumberWithLocales = useCallback( const formatNumberWithLocales = useCallback(
(options: Omit<FormatNumberOptions, 'locale' | 'localCurrency'>) => (options: Omit<FormatNumberOptions, 'locale' | 'localCurrency' | 'conversionRate'>) =>
formatNumber({ ...options, locale: formatterLocale, localCurrency: formatterLocalCurrency }), formatNumber({
[formatterLocalCurrency, formatterLocale] ...options,
locale: formatterLocale,
localCurrency: currencyToFormatWith,
conversionRate: localCurrencyConversionRateToFormatWith,
}),
[currencyToFormatWith, formatterLocale, localCurrencyConversionRateToFormatWith]
) )
const formatCurrencyAmountWithLocales = useCallback( const formatCurrencyAmountWithLocales = useCallback(
(options: Omit<FormatCurrencyAmountOptions, 'locale' | 'localCurrency'>) => (options: Omit<FormatCurrencyAmountOptions, 'locale' | 'localCurrency' | 'conversionRate'>) =>
formatCurrencyAmount({ ...options, locale: formatterLocale, localCurrency: formatterLocalCurrency }), formatCurrencyAmount({
[formatterLocalCurrency, formatterLocale] ...options,
locale: formatterLocale,
localCurrency: currencyToFormatWith,
conversionRate: localCurrencyConversionRateToFormatWith,
}),
[currencyToFormatWith, formatterLocale, localCurrencyConversionRateToFormatWith]
) )
return useMemo( return useMemo(
......
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