From f983923d9e7b6e44c1040023ac046f4e04c8652d Mon Sep 17 00:00:00 2001 From: Max Korsunov Date: Fri, 2 Aug 2024 16:43:11 +0200 Subject: [PATCH] fix(minifront): #1598: display non-native-fee-warning per account (#1614) * fix(minifront): #1593: display non-native-fee-warning per account * fix(minifront): #1598: fix linter * chore: changeset * fix(#1598): check for alt token balances before rendering non-native-fee-warning * chore: format * fix(minifront): #1598: comments * fix(minifront): #1598: fix display of the fee warning * fix(#1598): refactor --- .changeset/chatty-jokes-live.md | 5 + .../src/components/send/send-form/index.tsx | 1 + .../shared/non-native-fee-warning.tsx | 108 ++++++++++++++---- .../swap/swap-form/token-swap-input.tsx | 1 + 4 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 .changeset/chatty-jokes-live.md diff --git a/.changeset/chatty-jokes-live.md b/.changeset/chatty-jokes-live.md new file mode 100644 index 0000000000..11d12efd98 --- /dev/null +++ b/.changeset/chatty-jokes-live.md @@ -0,0 +1,5 @@ +--- +'minifront': patch +--- + +Fix NonNativeFeeWarning not being displayed diff --git a/apps/minifront/src/components/send/send-form/index.tsx b/apps/minifront/src/components/send/send-form/index.tsx index 9d4e99957d..c1a6570f1a 100644 --- a/apps/minifront/src/components/send/send-form/index.tsx +++ b/apps/minifront/src/components/send/send-form/index.tsx @@ -94,6 +94,7 @@ export const SendForm = () => { { + const account = getAddressIndex.optional()(source)?.account; + if (typeof account === 'undefined') { + return false; + } + + // Finds the UM token in the user's account balances + const hasStakingToken = balancesResponses.some( + asset => + getAssetIdFromValueView + .optional()(asset.balanceView) + ?.equals(getAssetId.optional()(stakingAssetMetadata)) && + getAddressIndex.optional()(asset)?.account === account, + ); + + if (hasStakingToken) { + return false; + } -const hasStakingToken = ( - balancesResponses: BalancesResponse[] = [], - stakingAssetMetadata?: Metadata, -): boolean => { - return balancesResponses.some(asset => - getAssetIdFromValueView - .optional()(asset.balanceView) - ?.equals(getAssetId.optional()(stakingAssetMetadata)), + const accountAssets = balancesResponses.filter( + balance => getAddressIndex.optional()(balance)?.account === account, ); + // Finds the alt tokens in the user's account balances that can be used for fees + const hasAltTokens = accountAssets.some(balance => { + const amount = getAmount(balance); + const hasBalance = amount.lo !== 0n || amount.hi !== 0n; + if (!hasBalance) { + return false; + } + + return gasPrices.some(price => + price.assetId?.equals(getAssetIdFromBalancesResponseOptional(balance)), + ); + }); + + return hasAltTokens; }; -export const useShouldRender = (balancesResponses: BalancesResponse[] = [], amount: number) => { - const stakingTokenMetadata = useStakingTokenMetadata(); - const userHasStakingToken = hasStakingToken(balancesResponses, stakingTokenMetadata.data); - const showNonNativeFeeWarning = amount > 0 && !userHasStakingToken; +const useGasPrices = () => { + const [prices, setPrices] = useState([]); + + const fetchGasPrices = useCallback(async () => { + const res = await viewClient.gasPrices({}); + setPrices(res.altGasPrices); + }, []); - return showNonNativeFeeWarning; + useEffect(() => { + void fetchGasPrices(); + }, [fetchGasPrices]); + + return prices; }; /** - * Renders a non-native fee warning if A) the user does not have any balance of - * the staking token to use for fees, and B) the amount the user has entered for - * a transaction (e.g., send or swap) is nonzero -- i.e., a fee will be - * required. + * Renders a non-native fee warning if + * 1. the user does not have any balance (in the selected account) of the staking token to use for fees + * 2. the user does not have sufficient balances in alternative tokens to cover the fees */ export const NonNativeFeeWarning = ({ - balancesResponses, + balancesResponses = [], amount, + source, wrap = children => children, }: { /** @@ -45,6 +96,11 @@ export const NonNativeFeeWarning = ({ * determine whether the warning should render. */ amount: number; + /** + * A source token – helps determine whether the user has UM token + * in the same account as `source` to use for fees. + */ + source?: BalancesResponse; /* * Since this component determines for itself whether to render, a parent * component can't optionally render wrapper markup depending on whether this @@ -57,13 +113,23 @@ export const NonNativeFeeWarning = ({ *
{children}
} * /> * ``` */ wrap?: (children: ReactNode) => ReactNode; }) => { - const shouldRender = useShouldRender(balancesResponses, amount); + const gasPrices = useGasPrices(); + const stakingTokenMetadata = useStakingTokenMetadata(); + const shouldRender = + !!amount && + hasTokenBalance({ + source, + balancesResponses, + gasPrices, + stakingAssetMetadata: stakingTokenMetadata.data, + }); if (!shouldRender) { return null; diff --git a/apps/minifront/src/components/swap/swap-form/token-swap-input.tsx b/apps/minifront/src/components/swap/swap-form/token-swap-input.tsx index e637ba7405..ce92d84f98 100644 --- a/apps/minifront/src/components/swap/swap-form/token-swap-input.tsx +++ b/apps/minifront/src/components/swap/swap-form/token-swap-input.tsx @@ -160,6 +160,7 @@ export const TokenSwapInput = () => { ( <> {/* This div adds an empty line */}