From fe981bdcf7de936c552ef61e1f5a6b584de43996 Mon Sep 17 00:00:00 2001 From: "Luiz Gomes - LuizAsFight.eth" <8636507+LuizAsFight@users.noreply.github.com> Date: Wed, 15 Nov 2023 20:07:16 -0300 Subject: [PATCH] fix: format units according to asset decimals + unknown asset (#115) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes FE-31 this PR address fully the format of amounts being showed across the explorer. will format to assets decimal config OR format the raw amount if it’s a unknown asset (unknown asset decimals) - update to `fuels/assets@0.1.3` to get new asset utils functions - share assetId with components that didn’t have it - apply correct amount formatted to this pages/components - BalanceItem - Utxos - TxAssetItem - TxInput - TxOutput --- packages/app/package.json | 2 +- .../app/src/systems/Asset/hooks/useAsset.ts | 5 +- .../src/systems/Asset/hooks/useFuelAsset.ts | 12 +++++ .../components/BalanceItem/BalanceItem.tsx | 17 ++++++- .../systems/Core/components/Utxos/Utxos.tsx | 47 +++++++++++++++---- packages/app/src/systems/Core/utils/format.ts | 13 +++++ .../component/TxAssetItem/TxAssetItem.tsx | 41 ++++++++++++---- .../Transaction/component/TxInput/TxInput.tsx | 18 +++++-- .../component/TxOutput/TxOutput.tsx | 16 ++++++- pnpm-lock.yaml | 8 ++-- 10 files changed, 147 insertions(+), 32 deletions(-) create mode 100644 packages/app/src/systems/Asset/hooks/useFuelAsset.ts create mode 100644 packages/app/src/systems/Core/utils/format.ts diff --git a/packages/app/package.json b/packages/app/package.json index 5eb79fafe..d1e809367 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -18,7 +18,7 @@ "@fuel-explorer/graphql": "workspace:*", "@fuel-ts/math": "0.67.0", "@fuel-wallet/sdk": "0.13.7", - "@fuels/assets": "0.1.1", + "@fuels/assets": "0.1.3", "@fuels/ui": "workspace:*", "@tabler/icons-react": "2.40.0", "@tanstack/react-query": "5.8.3", diff --git a/packages/app/src/systems/Asset/hooks/useAsset.ts b/packages/app/src/systems/Asset/hooks/useAsset.ts index 925ba861b..366793cdd 100644 --- a/packages/app/src/systems/Asset/hooks/useAsset.ts +++ b/packages/app/src/systems/Asset/hooks/useAsset.ts @@ -8,8 +8,9 @@ export function useAsset(assetId?: string) { return { assetId, name: found?.name ?? 'Unknown Asset', - symbol: found?.symbol ?? null, - icon: found?.icon ?? null, + symbol: found?.symbol || '', + icon: found?.icon || '', + networks: found?.networks ?? [], }; }, [assetId]); } diff --git a/packages/app/src/systems/Asset/hooks/useFuelAsset.ts b/packages/app/src/systems/Asset/hooks/useFuelAsset.ts new file mode 100644 index 000000000..ad2603473 --- /dev/null +++ b/packages/app/src/systems/Asset/hooks/useFuelAsset.ts @@ -0,0 +1,12 @@ +import { CHAIN_IDS, getAssetFuel } from '@fuels/assets'; +import type { Asset } from '@fuels/assets'; +import { useMemo } from 'react'; + +export const useFuelAsset = (asset?: Asset | null) => { + const fuelAsset = useMemo( + () => (asset ? getAssetFuel(asset, CHAIN_IDS.fuel.beta4) : undefined), + [asset?.symbol, asset?.name, asset?.networks.length], + ); + + return fuelAsset; +}; diff --git a/packages/app/src/systems/Core/components/BalanceItem/BalanceItem.tsx b/packages/app/src/systems/Core/components/BalanceItem/BalanceItem.tsx index 3e4240ad3..e8d669c59 100644 --- a/packages/app/src/systems/Core/components/BalanceItem/BalanceItem.tsx +++ b/packages/app/src/systems/Core/components/BalanceItem/BalanceItem.tsx @@ -12,8 +12,10 @@ import { import { bn } from 'fuels'; import Image from 'next/image'; import { useAsset } from '~/systems/Asset/hooks/useAsset'; +import { useFuelAsset } from '~/systems/Asset/hooks/useFuelAsset'; import { TxIcon } from '~/systems/Transaction/component/TxIcon/TxIcon'; +import { formatZeroUnits } from '../../utils/format'; import type { UtxoItem } from '../Utxos/Utxos'; import { Utxos } from '../Utxos/Utxos'; @@ -31,8 +33,9 @@ export const BalanceItem = createComponent< render: (_, { item, ...props }) => { const assetId = item.assetId; const amount = item.amount; - const asset = useAsset(assetId); const { isMobile } = useBreakpoints(); + const asset = useAsset(assetId); + const fuelAsset = useFuelAsset(asset); if (!asset) return null; const hasUTXOs = !!item.utxos?.length; @@ -66,7 +69,17 @@ export const BalanceItem = createComponent< {amount && ( - {bn(amount).format()} {asset.symbol} + {fuelAsset?.decimals ? ( + <> + {bn(amount).format({ + precision: fuelAsset.decimals, + units: fuelAsset.decimals, + })}{' '} + {asset.symbol} + + ) : ( + formatZeroUnits(amount) + )} )} diff --git a/packages/app/src/systems/Core/components/Utxos/Utxos.tsx b/packages/app/src/systems/Core/components/Utxos/Utxos.tsx index 00fd196d4..9aeb02ad1 100644 --- a/packages/app/src/systems/Core/components/Utxos/Utxos.tsx +++ b/packages/app/src/systems/Core/components/Utxos/Utxos.tsx @@ -17,18 +17,27 @@ import { bn } from 'fuels'; import NextLink from 'next/link'; import { VariableSizeList as List } from 'react-window'; import { tv } from 'tailwind-variants'; +import { useAsset } from '~/systems/Asset/hooks/useAsset'; +import { useFuelAsset } from '~/systems/Asset/hooks/useFuelAsset'; + +import { formatZeroUnits } from '../../utils/format'; export type UtxoItem = Partial>; type UtxoItemProps = { item: UtxoItem; + assetId?: string; style?: React.CSSProperties; }; -function UtxoItem({ item, style }: UtxoItemProps) { +function UtxoItem({ item, style, assetId }: UtxoItemProps) { const { isMobile } = useBreakpoints(); + const asset = useAsset(assetId); + const fuelAsset = useFuelAsset(asset); if (!item.utxoId) return null; + if (!asset) return null; + const classes = styles(); const trim = isMobile ? 8 : 16; return ( @@ -49,7 +58,16 @@ function UtxoItem({ item, style }: UtxoItemProps) { {' '} - {bn(item.amount).format({ precision: isMobile ? 3 : undefined })}{' '} + {fuelAsset?.decimals ? ( + <> + {bn(item.amount).format({ + precision: isMobile ? 3 : undefined, + units: fuelAsset.decimals, + })}{' '} + + ) : ( + formatZeroUnits(item.amount || '') + )} ); @@ -60,7 +78,7 @@ type UtxosProps = BoxProps & { items?: UtxoItem[] | null; }; -function VirtualList({ items }: UtxosProps) { +function VirtualList({ items, assetId }: UtxosProps) { const { isMobile } = useBreakpoints(); return ( {({ index: idx, style }) => { const item = items?.[idx]; - return item && ; + return ( + item && ( + + ) + ); }} ); } -function CommonList({ items }: UtxosProps) { +function CommonList({ items, assetId }: UtxosProps) { return ( - items?.map((item) => ) ?? null + items?.map((item) => ( + + )) ?? null ); } -export function Utxos({ items, ...props }: UtxosProps) { +export function Utxos({ items, assetId, ...props }: UtxosProps) { const len = items?.length ?? 0; return ( @@ -92,9 +121,9 @@ export function Utxos({ items, ...props }: UtxosProps) { {len > 10 ? ( - + ) : ( - + )} diff --git a/packages/app/src/systems/Core/utils/format.ts b/packages/app/src/systems/Core/utils/format.ts new file mode 100644 index 000000000..ec5b3f113 --- /dev/null +++ b/packages/app/src/systems/Core/utils/format.ts @@ -0,0 +1,13 @@ +import type { BNInput } from 'fuels'; +import { bn } from 'fuels'; + +/** + * Formats the given amount by multiplying it by 10 and formatting it with 1 unit. + * This is a workaround because formatting with zero units doesn't work. + * @param amount - The amount to format. + * @returns The formatted amount. + */ +export function formatZeroUnits(amount: BNInput) { + const formatted = bn(amount).mul(10).format({ units: 1, precision: 0 }); + return formatted; +} diff --git a/packages/app/src/systems/Transaction/component/TxAssetItem/TxAssetItem.tsx b/packages/app/src/systems/Transaction/component/TxAssetItem/TxAssetItem.tsx index 74cac239a..ac72bd2a5 100644 --- a/packages/app/src/systems/Transaction/component/TxAssetItem/TxAssetItem.tsx +++ b/packages/app/src/systems/Transaction/component/TxAssetItem/TxAssetItem.tsx @@ -1,11 +1,12 @@ import type { CardProps } from '@fuels/ui'; -import { Text, Card, EntityItem, HStack, cx } from '@fuels/ui'; +import { Text, Card, EntityItem, HStack, cx, useBreakpoints } from '@fuels/ui'; import { IconArrowDown, IconArrowUp } from '@tabler/icons-react'; import { bn } from 'fuels'; import type { BN } from 'fuels'; import Image from 'next/image'; -import { useMemo } from 'react'; -import { findAssetById } from '~/systems/Core/utils/asset'; +import { useAsset } from '~/systems/Asset/hooks/useAsset'; +import { useFuelAsset } from '~/systems/Asset/hooks/useFuelAsset'; +import { formatZeroUnits } from '~/systems/Core/utils/format'; import { TxIcon } from '../TxIcon/TxIcon'; @@ -24,9 +25,11 @@ export function TxAssetItem({ amountOut, ...props }: TxAssetItemProps) { - const asset = useMemo(() => findAssetById(assetId), [assetId]); - const assetName = asset?.name ?? 'Unknown'; - const assetSymbol = asset?.symbol ?? null; + const asset = useAsset(assetId); + const { isMobile } = useBreakpoints(); + const fuelAsset = useFuelAsset(asset); + if (!asset) return null; + return ( @@ -42,7 +45,7 @@ export function TxAssetItem({ )} - + - {bn(amountIn).format()} {assetSymbol} + {fuelAsset?.decimals ? ( + <> + {bn(amountIn).format({ + precision: isMobile ? 3 : undefined, + units: fuelAsset.decimals, + })}{' '} + + ) : ( + formatZeroUnits(amountIn) + )} + {asset.symbol} - {bn(amountOut).format()} {assetSymbol} + {fuelAsset?.decimals ? ( + <> + {bn(amountOut).format({ + precision: isMobile ? 3 : undefined, + units: fuelAsset.decimals, + })}{' '} + + ) : ( + formatZeroUnits(amountOut) + )} + {asset.symbol} diff --git a/packages/app/src/systems/Transaction/component/TxInput/TxInput.tsx b/packages/app/src/systems/Transaction/component/TxInput/TxInput.tsx index 53b37cac9..80c02ff5e 100644 --- a/packages/app/src/systems/Transaction/component/TxInput/TxInput.tsx +++ b/packages/app/src/systems/Transaction/component/TxInput/TxInput.tsx @@ -17,8 +17,10 @@ import Image from 'next/image'; import NextLink from 'next/link'; import { tv } from 'tailwind-variants'; import { useAsset } from '~/systems/Asset/hooks/useAsset'; +import { useFuelAsset } from '~/systems/Asset/hooks/useFuelAsset'; import type { UtxoItem } from '~/systems/Core/components/Utxos/Utxos'; import { Utxos } from '~/systems/Core/components/Utxos/Utxos'; +import { formatZeroUnits } from '~/systems/Core/utils/format'; import { TxIcon } from '../TxIcon/TxIcon'; @@ -36,10 +38,11 @@ const TxInputCoin = createComponent({ const assetId = input.assetId; const amount = input.totalAmount; const inputs = input.inputs as InputCoin[]; - const asset = useAsset(assetId); const { isMobile } = useBreakpoints(); - + const asset = useAsset(assetId); + const fuelAsset = useFuelAsset(asset); if (!asset) return null; + return ( @@ -91,7 +94,16 @@ const TxInputCoin = createComponent({ */} {amount && ( - {bn(amount).format({ precision: isMobile ? 3 : undefined })}{' '} + {fuelAsset?.decimals ? ( + <> + {bn(amount).format({ + precision: isMobile ? 3 : undefined, + units: fuelAsset.decimals, + })}{' '} + + ) : ( + formatZeroUnits(amount) + )} {asset.symbol} )} diff --git a/packages/app/src/systems/Transaction/component/TxOutput/TxOutput.tsx b/packages/app/src/systems/Transaction/component/TxOutput/TxOutput.tsx index 267409040..8ac760b5a 100644 --- a/packages/app/src/systems/Transaction/component/TxOutput/TxOutput.tsx +++ b/packages/app/src/systems/Transaction/component/TxOutput/TxOutput.tsx @@ -16,6 +16,8 @@ import Image from 'next/image'; import NextLink from 'next/link'; import { tv } from 'tailwind-variants'; import { useAsset } from '~/systems/Asset/hooks/useAsset'; +import { useFuelAsset } from '~/systems/Asset/hooks/useFuelAsset'; +import { formatZeroUnits } from '~/systems/Core/utils/format'; import { TxIcon } from '../TxIcon/TxIcon'; @@ -36,8 +38,9 @@ const TxOutputCoin = createComponent({ const assetId = output.assetId; const amount = output.totalAmount; const asset = useAsset(assetId); - + const fuelAsset = useFuelAsset(asset); if (!asset) return null; + return ( @@ -84,7 +87,16 @@ const TxOutputCoin = createComponent({ {amount && ( - {bn(amount).format(isMobile ? { precision: 3 } : undefined)}{' '} + {fuelAsset?.decimals ? ( + <> + {bn(amount).format({ + precision: isMobile ? 3 : undefined, + units: fuelAsset.decimals, + })}{' '} + + ) : ( + formatZeroUnits(amount) + )} {asset.symbol} )} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 872e4a57a..36f53ecc4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -165,8 +165,8 @@ importers: specifier: 0.13.7 version: 0.13.7(fuels@0.67.0) '@fuels/assets': - specifier: 0.1.1 - version: 0.1.1 + specifier: 0.1.3 + version: 0.1.3 '@fuels/ui': specifier: workspace:* version: link:../ui @@ -3421,8 +3421,8 @@ packages: - dexie dev: false - /@fuels/assets@0.1.1: - resolution: {integrity: sha512-1nvpA6xUN1jqk4MH1Pas8XL3wofvRPgFis68XSQfmHOchkRNA82lwoiUaCJ+NlLnQC+3YVVuonwYuWO9dTjkuQ==} + /@fuels/assets@0.1.3: + resolution: {integrity: sha512-8vFsASyp6RCFK2XxoEzUzgHxOUNklpHaqx+FoxlgQILSNCDzla2mwWHJLgJ3Exd2FU2+5UOqXJh3wIkmNMWoyA==} dev: false /@fuels/eslint-plugin@0.1.1(eslint@8.53.0)(typescript@5.2.2):