From 5e83d417bdc0721bbf93619b982c25cabecbd9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Santana=20Gon=C3=A7alves?= Date: Fri, 12 Apr 2024 09:07:55 -0300 Subject: [PATCH] US-2157: Round USD conversions (#890) * do not show less than a cent if balance is zero * round usd conversions in transaction summary * make all TransactionSummaryScreenProps consistent * create functions for formatting token and usd values * add some other test cases * add formatUsdValueWithDollarSign function * use formatUsdValue and formatTokenValue * remove zero as special case * format fee value * remove precison of 18 decimals places * move formatting numbers into TransactionSummaryComponent * change to formatFiatValue * fix bitcoin transaction status * remove log * handle NaN values * fetch usd token prices first --- src/components/BasicRow/index.tsx | 6 +- src/components/token/index.tsx | 31 ++--- src/redux/slices/transactionsSlice/types.ts | 2 +- src/screens/activity/ActivityRow.tsx | 84 +++++++------- src/screens/home/index.tsx | 4 +- src/screens/rnsManager/SearchDomainScreen.tsx | 4 +- src/screens/send/TransactionForm.tsx | 11 +- .../TransactionSummaryComponent.tsx | 18 +-- src/screens/transactionSummary/index.tsx | 2 +- src/shared/utils/index.test.ts | 68 +++++++++++ src/shared/utils/index.ts | 108 ++++++++++++++++++ src/subscriptions/onSocketChangeEmitted.ts | 2 +- .../ReviewBitcoinTransactionContainer.tsx | 28 ++--- .../ReviewTransactionContainer.tsx | 26 +++-- 14 files changed, 274 insertions(+), 120 deletions(-) create mode 100644 src/shared/utils/index.test.ts diff --git a/src/components/BasicRow/index.tsx b/src/components/BasicRow/index.tsx index 1e083fcce..0bd7bd0e7 100644 --- a/src/components/BasicRow/index.tsx +++ b/src/components/BasicRow/index.tsx @@ -43,7 +43,7 @@ export interface BasicRowProps { amount?: string status?: StatusTextProps['status'] error?: string - usdAmount?: number + usdAmount?: string style?: StyleProp symbol?: string } @@ -110,14 +110,14 @@ export const BasicRow = ({ )} - {usdAmount !== undefined && ( + {usdAmount && ( - {!usdAmount && '< '}${usdAmount ? usdAmount.toFixed(2) : '0.01'} + {usdAmount} )} diff --git a/src/components/token/index.tsx b/src/components/token/index.tsx index 87a133839..cf6294892 100644 --- a/src/components/token/index.tsx +++ b/src/components/token/index.tsx @@ -18,7 +18,7 @@ import { ContactCard } from 'screens/contacts/components' import { TokenImage, TokenSymbol } from 'screens/home/TokenImage' import { noop, sharedColors, sharedStyles, testIDs } from 'shared/constants' import { ContactWithAddressRequired } from 'shared/types' -import { castStyle, formatTokenValues } from 'shared/utils' +import { castStyle, formatTokenValue, formatFiatValue } from 'shared/utils' import { DollarIcon } from '../icons/DollarIcon' import { EyeIcon } from '../icons/EyeIcon' @@ -26,7 +26,7 @@ import { EyeIcon } from '../icons/EyeIcon' export interface CurrencyValue { symbol: TokenSymbol | string symbolType: 'usd' | 'icon' - balance: string + balance: number | string } interface Props { @@ -70,8 +70,8 @@ export const TokenBalance = ({ firstValue.symbol?.toUpperCase() === 'TRIF' const firstValueBalance = editable - ? firstValue.balance - : formatTokenValues(firstValue.balance) + ? firstValue.balance.toString() + : formatTokenValue(firstValue.balance) const onCopyAddress = useCallback(() => { if (contact) { @@ -106,7 +106,7 @@ export const TokenBalance = ({ )} )} - {secondValue?.symbolType === 'usd' && ( - <> - {secondValue.symbol === '<' && ( - - {'<'} - - )} - - - )} - {!isNaN(Number(secondValue?.balance)) && ( + {secondValue && ( {hide - ? '\u002A\u002A\u002A\u002A\u002A\u002A' - : secondValue - ? formatTokenValues(secondValue.balance) - : ''} + ? '\u002A\u002A\u002A\u002A\u002A' + : secondValue.symbolType === 'usd' + ? formatFiatValue(secondValue.balance) + : formatTokenValue(secondValue.balance)} )} {error && ( @@ -235,6 +225,7 @@ const styles = StyleSheet.create({ borderRadius: 10, width: 20, height: 20, + marginRight: 4, }), subTitle: castStyle.text({ color: sharedColors.subTitle, diff --git a/src/redux/slices/transactionsSlice/types.ts b/src/redux/slices/transactionsSlice/types.ts index f5e697bb1..d8ceb251a 100644 --- a/src/redux/slices/transactionsSlice/types.ts +++ b/src/redux/slices/transactionsSlice/types.ts @@ -35,7 +35,7 @@ export interface IBitcoinTransaction { export interface TokenFeeValueObject { tokenValue: string - usdValue: string + usdValue: number | string symbol?: TokenSymbol | string } diff --git a/src/screens/activity/ActivityRow.tsx b/src/screens/activity/ActivityRow.tsx index 98cc37195..9e1b5c69d 100644 --- a/src/screens/activity/ActivityRow.tsx +++ b/src/screens/activity/ActivityRow.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import { StyleProp, ViewStyle } from 'react-native' import { ZERO_ADDRESS } from '@rsksmart/rif-relay-light-sdk' -import { roundBalance, shortAddress } from 'lib/utils' +import { shortAddress } from 'lib/utils' import { isMyAddress } from 'components/address/lib' import { StatusEnum } from 'components/BasicRow' @@ -15,7 +15,9 @@ import { ActivityMainScreenProps } from 'shared/types' import { useAppSelector } from 'store/storeUtils' import { getContactByAddress } from 'store/slices/contactsSlice' import { ActivityRowPresentationObject } from 'store/slices/transactionsSlice' +import { formatTokenValue, formatFiatValue } from 'shared/utils' import { Wallet, useWallet } from 'shared/wallet' +import { TransactionStatus } from 'store/shared/types' const getStatus = (status: string) => { switch (status) { @@ -53,7 +55,7 @@ export const ActivityBasicRow = ({ timeHumanFormatted, from = '', to = '', - price, + price: usdValue, id, } = activityDetails const { address: walletAddress } = useWallet() @@ -76,11 +78,17 @@ export const ActivityBasicRow = ({ label = t('wallet_deployment_label') } - // USD Balance - const usdBalance = roundBalance(price, 2) + const txSummary: TransactionSummaryScreenProps = useMemo(() => { + const totalUsd = isNaN(usdValue) ? '' : usdValue + Number(fee.usdValue) + const feeUsd = isNaN(+fee.usdValue) ? '' : fee.usdValue + const usdAmount = isNaN(usdValue) ? '' : usdValue - const txSummary: TransactionSummaryScreenProps = useMemo( - () => ({ + const totalToken = + symbol === fee.symbol + ? Number(value) + Number(fee.tokenValue) + : Number(value) + + return { transaction: { tokenValue: { symbol, @@ -88,21 +96,18 @@ export const ActivityBasicRow = ({ balance: value, }, usdValue: { - symbol: usdBalance ? '$' : '<', + symbol: '$', symbolType: 'usd', - balance: usdBalance ? usdBalance : '0.01', + balance: usdAmount, }, - totalToken: - symbol === fee.symbol - ? Number(value) + Number(fee.tokenValue) - : Number(value), - totalUsd: Number(value) + Number(fee.usdValue), - status, fee: { - ...fee, symbol: fee.symbol || symbol, - usdValue: fee.usdValue, + tokenValue: fee.tokenValue, + usdValue: feeUsd, }, + totalToken, + totalUsd, + status: status.toUpperCase() as TransactionStatus, amIReceiver, from, to, @@ -110,34 +115,25 @@ export const ActivityBasicRow = ({ hashId: id, }, contact: contact || { address }, - }), - [ - address, - amIReceiver, - contact, - fee, - from, - to, - status, - symbol, - timeHumanFormatted, - usdBalance, - value, - id, - ], - ) - - const amount = useMemo(() => { - if (symbol.startsWith('BTC')) { - return value } - const num = Number(value) - let rounded = roundBalance(num, 4) - if (!rounded) { - rounded = roundBalance(num, 8) - } - return rounded.toString() - }, [value, symbol]) + }, [ + fee, + symbol, + value, + usdValue, + status, + amIReceiver, + from, + to, + timeHumanFormatted, + id, + contact, + address, + ]) + + const amount = symbol.startsWith('BTC') ? value : formatTokenValue(value) + const isUnknownToken = !usdValue && Number(value) > 0 + const usdAmount = isUnknownToken ? '' : formatFiatValue(usdValue) const handlePress = useCallback(() => { if (txSummary) { @@ -158,7 +154,7 @@ export const ActivityBasicRow = ({ status={getStatus(status)} avatar={{ name: 'A' }} secondaryLabel={timeHumanFormatted} - usdAmount={price === 0 ? undefined : usdBalance} + usdAmount={usdAmount} contact={contact} /> diff --git a/src/screens/home/index.tsx b/src/screens/home/index.tsx index 59e662d4d..21ed8fca4 100644 --- a/src/screens/home/index.tsx +++ b/src/screens/home/index.tsx @@ -31,7 +31,7 @@ import { } from 'storage/MainStorage' import { selectTransactions } from 'store/slices/transactionsSlice' import { sharedColors } from 'shared/constants' -import { castStyle } from 'shared/utils' +import { castStyle, formatFiatValue } from 'shared/utils' import { ActivityBasicRow } from 'screens/activity/ActivityRow' import { useWallet } from 'shared/wallet' @@ -187,7 +187,7 @@ export const HomeScreen = ({ setSelectedTokenBalanceUsd({ symbolType: 'usd', symbol, - balance: usdBalance.toFixed(2), + balance: formatFiatValue(usdBalance), }) } }, [selectedToken]) diff --git a/src/screens/rnsManager/SearchDomainScreen.tsx b/src/screens/rnsManager/SearchDomainScreen.tsx index 6d942e763..858a58f8f 100644 --- a/src/screens/rnsManager/SearchDomainScreen.tsx +++ b/src/screens/rnsManager/SearchDomainScreen.tsx @@ -18,7 +18,7 @@ import { ProfileStatus, } from 'navigation/profileNavigator/types' import { sharedColors, sharedStyles } from 'shared/constants' -import { castStyle, formatTokenValues } from 'shared/utils' +import { castStyle, formatTokenValue } from 'shared/utils' import { colors } from 'src/styles' import { recoverAlias, @@ -99,7 +99,7 @@ export const SearchDomainScreen = ({ navigation }: Props) => { const years = watch('years') const hasErrors = Object.keys(errors).length > 0 - const selectedDomainPriceInUsd = formatTokenValues( + const selectedDomainPriceInUsd = formatTokenValue( rifToken.price * Number(selectedDomainPrice), ) diff --git a/src/screens/send/TransactionForm.tsx b/src/screens/send/TransactionForm.tsx index 889b621eb..6cfab17b6 100644 --- a/src/screens/send/TransactionForm.tsx +++ b/src/screens/send/TransactionForm.tsx @@ -32,6 +32,7 @@ import { defaultIconSize, sharedColors, testIDs } from 'shared/constants' import { bitcoinFeeMap, castStyle, + formatTokenValue, getAllowedFees, getDefaultFeeEOA, getDefaultFeeRelay, @@ -219,13 +220,13 @@ export const TransactionForm = ({ setValue('amount', balanceToSet) setSecondBalance(prev => ({ ...prev, - balance: balanceToSet.toString(), + balance: balanceToSet, })) } else { setValue('amount', numberAmount) setSecondBalance(prev => ({ ...prev, - balance: convertTokenToUSD(numberAmount, tokenQuote).toFixed(2), + balance: convertTokenToUSD(numberAmount, tokenQuote), })) } }, @@ -499,9 +500,9 @@ export const TransactionForm = ({ )} - {formatTokenValues(fee.tokenValue)} {fee.symbol} + {formatTokenValue(fee.tokenValue)} {fee.symbol} - - {formatTokenValues(fee.usdValue)} + {formatFiatValue(fee.usdValue)} @@ -209,7 +207,7 @@ export const TransactionSummaryComponent = ({ - {formatTokenValues(totalToken)} {tokenValue.symbol}{' '} + {formatTokenValue(totalToken)} {tokenValue.symbol}{' '} {tokenValue.symbol !== fee.symbol && !amIReceiver && t('transaction_summary_plus_fees')} @@ -217,19 +215,13 @@ export const TransactionSummaryComponent = ({ - {usdValue.symbol === '<' && Number(totalUsd) <= 0.01 && ( - - {'<'} - - )} - - {formatTokenValues(totalUsd)} + {formatFiatValue(totalUsd)} {/* arrive value */} diff --git a/src/screens/transactionSummary/index.tsx b/src/screens/transactionSummary/index.tsx index f3745f6d3..5ea51deab 100644 --- a/src/screens/transactionSummary/index.tsx +++ b/src/screens/transactionSummary/index.tsx @@ -24,7 +24,7 @@ export interface TransactionSummaryScreenProps { fee: TokenFeeValueObject time: string totalToken: number - totalUsd: number + totalUsd: number | string hashId?: string status?: TransactionStatus amIReceiver?: boolean diff --git a/src/shared/utils/index.test.ts b/src/shared/utils/index.test.ts new file mode 100644 index 000000000..5631921ee --- /dev/null +++ b/src/shared/utils/index.test.ts @@ -0,0 +1,68 @@ +import { formatTokenValue, formatFiatValue } from './index' + +describe('formatFiatValue', () => { + test('formats basic USD values correctly', () => { + expect(formatFiatValue('5678.90')).toBe('$5,678.90') + expect(formatFiatValue(1234567.89123)).toBe('$1,234,567.89') + expect(formatFiatValue(1234567.89)).toBe('$1,234,567.89') + expect(formatFiatValue(1234567)).toBe('$1,234,567.00') + expect(formatFiatValue(1234.5)).toBe('$1,234.50') + expect(formatFiatValue(1234)).toBe('$1,234.00') + }) + + test('handles zero as a special case', () => { + expect(formatFiatValue(0)).toBe('$0.00') + expect(formatFiatValue('0')).toBe('$0.00') + }) + + test('formats negative USD values correctly', () => { + expect(formatFiatValue(-1234.56)).toBe('-$1,234.56') + }) + + test('rounds to two decimal places', () => { + expect(formatFiatValue(1234.567)).toBe('$1,234.57') + }) + + test('small amounts', () => { + expect(formatFiatValue(0.0000000099)).toBe('<$0.01') + expect(formatFiatValue(0.009)).toBe('<$0.01') + expect(formatFiatValue(0.0100000001)).toBe('$0.01') + expect(formatFiatValue(0.01)).toBe('$0.01') + expect(formatFiatValue(0.1)).toBe('$0.10') + }) +}) + +describe('formatTokenValue', () => { + test('formats basic token values correctly', () => { + expect(formatTokenValue('5678.901234')).toBe('5,678.901234') + expect(formatTokenValue(1234)).toBe('1,234') + expect(formatTokenValue(1234.5)).toBe('1,234.5') + expect(formatTokenValue(1234.567890123)).toBe('1,234.56789012') + expect(formatTokenValue(1234.567890005)).toBe('1,234.56789') + expect(formatTokenValue(1234.5678900051)).toBe('1,234.56789001') + }) + + test('removes unnecessary trailing zeros', () => { + expect(formatTokenValue('1234.5000')).toBe('1,234.5') + expect(formatTokenValue('1234.50001')).toBe('1,234.50001') + }) + + test('handles zero as a special case', () => { + expect(formatTokenValue(0)).toBe('0') + expect(formatTokenValue('0')).toBe('0') + expect(formatTokenValue('0.000000')).toBe('0') + }) + + test('formats very small token values correctly', () => { + expect(formatTokenValue(0.0000000099)).toBe('<0.00000001') + expect(formatTokenValue(0.000123)).toBe('0.000123') + }) + + test('formats negative token values correctly', () => { + expect(formatTokenValue(-1234.56789)).toBe('-1,234.56789') + }) + + test('rounds to eight decimal places where applicable', () => { + expect(formatTokenValue(1234.567890123)).toBe('1,234.56789012') + }) +}) diff --git a/src/shared/utils/index.ts b/src/shared/utils/index.ts index d3fb90842..6c66f3eb5 100644 --- a/src/shared/utils/index.ts +++ b/src/shared/utils/index.ts @@ -25,6 +25,114 @@ export const delay = (delayMs: number) => { ) } +// this needs to be here because of the failing tests +enum TokenSymbol { + TRBTC = 'TRBTC', + RBTC = 'RBTC', +} + +export const rbtcMap = new Map([ + [TokenSymbol.TRBTC, true], + [TokenSymbol.RBTC, true], + [undefined, false], +]) + +interface FormatNumberOptions { + decimalPlaces?: number + useThousandSeparator?: boolean + isCurrency?: boolean + sign?: string +} + +/** + * Formats a number or a numeric string with the given options. + * @param num The number or string to format. + * @param options The formatting options to use. + * @returns The formatted number as a string. + */ +const formatNumber = ( + num: number | string, + options: FormatNumberOptions = {}, +): string => { + // Attempt to parse if num is a string + if (typeof num === 'string') { + const parsedNum = parseFloat(num) + if (isNaN(parsedNum)) { + return num + } + num = parsedNum + } + + // Destructure with default values + const { + decimalPlaces = 8, + useThousandSeparator = true, + isCurrency = false, + sign = '', + } = options + + // Calculate the minimum value that can be displayed given the number of decimal places + const minValue = 1 / Math.pow(10, decimalPlaces) + + // Check for small positive amounts less than the minimum value + if (num > 0 && num < minValue) { + return `<${sign}0.${'0'.repeat(decimalPlaces - 1)}1` + } + + // Format the number with fixed decimal places + let result = num.toFixed(isCurrency ? 2 : decimalPlaces) + + // For non-currency numbers, remove unnecessary trailing zeros + if (!isCurrency) { + result = result.replace(/(\.\d*?[1-9])0+$|\.0*$/, '$1') + } + + // Add thousand separators if enabled + if (useThousandSeparator) { + const parts = result.split('.') + parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',') + result = parts.join('.') + } + + // Check if the number is negative; if so, format accordingly + if (num < 0) { + return `-${sign}${result.substring(1)}` + } + + return `${sign}${result}` +} + +/** + * Formats a number or a numeric string as a USD value with a dollar sign. + * Should be used only at the end when showing values. + * @param value The number or string to format. + * @param sign The currency sign to use. + * @returns The formatted USD value with a dollar sign as a string. + */ +export const formatFiatValue = (value: number | string, sign = '$'): string => + formatNumber(value, { + decimalPlaces: 2, + useThousandSeparator: true, + isCurrency: true, + sign, + }) + +/** + * Formats a number or a numeric string as a token value. + * Should be used only at the end when showing values. + * @param value The number or string to format. + * @returns The formatted token value as a string. + */ +export const formatTokenValue = ( + value: number | string, + precision = 8, +): string => + formatNumber(value, { + decimalPlaces: precision, + useThousandSeparator: true, + isCurrency: false, + }) + export const errorHandler = (error: unknown) => { if (typeof error === 'object' && Object.hasOwn(error as object, 'message')) { const err = error as ErrorWithMessage diff --git a/src/subscriptions/onSocketChangeEmitted.ts b/src/subscriptions/onSocketChangeEmitted.ts index a3a52a90e..bc9554766 100644 --- a/src/subscriptions/onSocketChangeEmitted.ts +++ b/src/subscriptions/onSocketChangeEmitted.ts @@ -155,10 +155,10 @@ export const onSocketChangeEmitted = const deserializedTransactions = combinedTransactions.map(tx => activityDeserializer(tx, prices, chainId), ) + dispatch(setUsdPrices(prices)) dispatch(fetchBitcoinTransactions({})) dispatch(addNewTransactions(deserializedTransactions)) dispatch(addOrUpdateBalances(tokens)) - dispatch(setUsdPrices(prices)) break default: throw new Error(`${type} not implemented`) diff --git a/src/ux/requestsModal/ReviewBitcoinTransactionContainer.tsx b/src/ux/requestsModal/ReviewBitcoinTransactionContainer.tsx index 9d7f9627c..c1ed7f7da 100644 --- a/src/ux/requestsModal/ReviewBitcoinTransactionContainer.tsx +++ b/src/ux/requestsModal/ReviewBitcoinTransactionContainer.tsx @@ -17,7 +17,6 @@ import { useAppSelector } from 'store/storeUtils' import { sharedColors } from 'shared/constants' import { AppButtonBackgroundVarietyEnum, Input } from 'components/index' import { TransactionSummaryScreenProps } from 'screens/transactionSummary' -import { formatTokenValues } from 'shared/utils' import { BitcoinMiningFeeContainer, @@ -77,14 +76,15 @@ export const ReviewBitcoinTransactionContainer = ({ }, [onCancel, request]) const data: TransactionSummaryScreenProps = useMemo(() => { - const convertToUSD = (amount: string) => - convertTokenToUSD(Number(amount), tokenPrices.BTC.price).toFixed(2) + const convertToUSD = (amount: string): number => + convertTokenToUSD(Number(amount), tokenPrices.BTC.price) // usd values - const amountToPayUsd = convertToUSD(amountToPay) + const amountUsd = convertToUSD(amountToPay) const feeUsd = convertToUSD(miningFee) - const isAmountSmall = !Number(amountToPayUsd) && !!Number(amountToPay) - const totalSent = Number(amountToPay) + Number(miningFee) + const totalUsd = amountUsd + feeUsd + + const totalBtc = Number(amountToPay) + Number(miningFee) return { transaction: { @@ -94,24 +94,18 @@ export const ReviewBitcoinTransactionContainer = ({ symbol: TokenSymbol.BTC, }, usdValue: { - balance: isAmountSmall ? '0.01' : amountToPayUsd, + symbol: '$', symbolType: 'usd', - symbol: isAmountSmall ? '<' : '$', + balance: amountUsd, }, fee: { + symbol: TokenSymbol.BTC, tokenValue: miningFee, usdValue: feeUsd, - symbol: TokenSymbol.BTC, }, + totalToken: totalBtc, + totalUsd: totalUsd, time: 'approx 1 min', - total: { - tokenValue: amountToPay, - usdValue: formatTokenValues(Number(amountToPayUsd) + Number(feeUsd)), - }, - totalToken: totalSent, - totalUsd: Number( - formatTokenValues(Number(amountToPayUsd) + Number(feeUsd)), - ), to: addressToPay, }, buttons: [ diff --git a/src/ux/requestsModal/ReviewRelayTransaction/ReviewTransactionContainer.tsx b/src/ux/requestsModal/ReviewRelayTransaction/ReviewTransactionContainer.tsx index 736add9e6..80f70bf21 100644 --- a/src/ux/requestsModal/ReviewRelayTransaction/ReviewTransactionContainer.tsx +++ b/src/ux/requestsModal/ReviewRelayTransaction/ReviewTransactionContainer.tsx @@ -1,4 +1,4 @@ -import { BigNumber } from 'ethers' +import { BigNumber, BigNumberish } from 'ethers' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { Alert, StyleSheet, View } from 'react-native' @@ -19,6 +19,7 @@ import { sharedColors } from 'shared/constants' import { castStyle, errorHandler, + formatTokenValue, getDefaultTokenContract, getFee, rbtcMap, @@ -187,7 +188,7 @@ export const ReviewTransactionContainer = ({ const feeValue = txCost ? balanceToDisplay(txCost, 18) : '0' const rbtcFeeValue = txCost && rbtcMap.get(fee.symbol as TokenSymbol) - ? txCost.toString() + ? formatTokenValue(txCost.toString()) : undefined let insufficientFunds = false @@ -207,16 +208,19 @@ export const ReviewTransactionContainer = ({ Alert.alert(t('transaction_summary_insufficient_funds')) } - // get usd values - const tokenUsd = convertTokenToUSD(Number(value), tokenQuote) - const feeUsd = convertTokenToUSD(Number(feeValue), feeQuote) - const isAmountSmall = !Number(tokenUsd) && !!Number(value) + const convertToUSD = ( + amount: string | BigNumberish, + quote: number, + ): number => convertTokenToUSD(Number(amount), quote) + + // usd values + const tokenUsd = convertToUSD(value, tokenQuote) + const feeUsd = convertToUSD(feeValue, feeQuote) + const totalUsd = tokenUsd + feeUsd const totalToken = symbol === fee.symbol ? Number(value) + Number(feeValue) : Number(value) - const totalUsd = (Number(tokenUsd) + Number(feeUsd)).toFixed(2) - return { transaction: { tokenValue: { @@ -225,14 +229,14 @@ export const ReviewTransactionContainer = ({ balance: value.toString(), }, usdValue: { - symbol: isAmountSmall ? '<' : '$', + symbol: '$', symbolType: 'usd', - balance: isAmountSmall ? '0.01' : tokenUsd, + balance: tokenUsd, }, fee: { + symbol: fee.symbol, tokenValue: rbtcFeeValue ?? feeValue, usdValue: feeUsd, - symbol: fee.symbol, }, totalToken, totalUsd,