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):