From 36ef8cc87a3e48cb68cc55f14a1e8539265f8f40 Mon Sep 17 00:00:00 2001 From: Micaela Estabillo Date: Thu, 20 Feb 2025 15:50:31 -0800 Subject: [PATCH] feat: disable CTA button based on balance wip --- ui/hooks/bridge/useIsTxSubmittable.ts | 55 +++++++++++++------ ui/hooks/bridge/useLatestBalance.ts | 29 ++++------ ui/hooks/bridge/useQuoteFetchEvents.ts | 4 +- ui/pages/bridge/prepare/bridge-cta-button.tsx | 4 +- .../bridge/prepare/bridge-input-group.tsx | 4 +- .../bridge/prepare/prepare-bridge-page.tsx | 7 +-- 6 files changed, 58 insertions(+), 45 deletions(-) diff --git a/ui/hooks/bridge/useIsTxSubmittable.ts b/ui/hooks/bridge/useIsTxSubmittable.ts index 8302001c5bf8..258461443703 100644 --- a/ui/hooks/bridge/useIsTxSubmittable.ts +++ b/ui/hooks/bridge/useIsTxSubmittable.ts @@ -1,49 +1,70 @@ import { useSelector } from 'react-redux'; +import { useMemo } from 'react'; import { SWAPS_CHAINID_DEFAULT_TOKEN_MAP } from '../../../shared/constants/swaps'; import { getBridgeQuotes, getFromAmount, - getFromChain, getFromToken, getToChain, getValidationErrors, getToToken, } from '../../ducks/bridge/selectors'; +import { getMultichainCurrentChainId } from '../../selectors/multichain'; +import { useMultichainSelector } from '../useMultichainSelector'; +import { useIsMultichainSwap } from '../../pages/bridge/hooks/useIsMultichainSwap'; import useLatestBalance from './useLatestBalance'; export const useIsTxSubmittable = () => { const fromToken = useSelector(getFromToken); const toToken = useSelector(getToToken); - const fromChain = useSelector(getFromChain); + const fromChainId = useMultichainSelector(getMultichainCurrentChainId); const toChain = useSelector(getToChain); const fromAmount = useSelector(getFromAmount); const { activeQuote } = useSelector(getBridgeQuotes); + const isSwap = useIsMultichainSwap(); const { isInsufficientBalance, isInsufficientGasBalance, isInsufficientGasForQuote, } = useSelector(getValidationErrors); - const { balanceAmount } = useLatestBalance(fromToken, fromChain?.chainId); - const { balanceAmount: nativeAssetBalance } = useLatestBalance( - fromChain?.chainId + const balanceAmount = useLatestBalance(fromToken, fromChainId); + const nativeAssetBalance = useLatestBalance( + fromChainId ? SWAPS_CHAINID_DEFAULT_TOKEN_MAP[ - fromChain.chainId as keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP + fromChainId as keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP ] : null, - fromChain?.chainId, + fromChainId, ); - return Boolean( - fromToken && - toToken && - fromChain && - toChain && - fromAmount && - activeQuote && - !isInsufficientBalance(balanceAmount) && - !isInsufficientGasBalance(nativeAssetBalance) && - !isInsufficientGasForQuote(nativeAssetBalance), + return useMemo( + () => + Boolean( + fromToken && + toToken && + fromChainId && + (isSwap || toChain) && + fromAmount && + activeQuote && + !isInsufficientBalance(balanceAmount) && + !isInsufficientGasBalance(nativeAssetBalance) && + !isInsufficientGasForQuote(nativeAssetBalance), + ), + [ + activeQuote, + balanceAmount, + fromAmount, + fromChainId, + fromToken, + isInsufficientBalance, + isInsufficientGasBalance, + isInsufficientGasForQuote, + nativeAssetBalance, + isSwap, + toChain, + toToken, + ], ); }; diff --git a/ui/hooks/bridge/useLatestBalance.ts b/ui/hooks/bridge/useLatestBalance.ts index b32579b2d166..93139f358a6f 100644 --- a/ui/hooks/bridge/useLatestBalance.ts +++ b/ui/hooks/bridge/useLatestBalance.ts @@ -1,5 +1,5 @@ import { type Hex, type CaipChainId, isCaipChainId } from '@metamask/utils'; -import type { BigNumber } from 'bignumber.js'; +import { useMemo } from 'react'; import { Numeric } from '../../../shared/modules/Numeric'; import { getSelectedInternalAccount } from '../../selectors'; import { calcLatestSrcBalance } from '../../../shared/modules/bridge-utils/balance'; @@ -10,7 +10,6 @@ import { getMultichainBalances, getMultichainCurrentChainId, } from '../../selectors/multichain'; -import { calcTokenValue } from '../../../shared/lib/swaps-utils'; /** * Custom hook to fetch and format the latest balance of a given token or native asset. @@ -38,9 +37,7 @@ const useLatestBalance = ( ); const nonEvmBalances = nonEvmBalancesByAccountId[id]; - const { value: latestBalance } = useAsyncResult< - Numeric | BigNumber | undefined - >(async () => { + const value = useAsyncResult(async () => { if ( token?.address && // TODO check whether chainId is EVM when MultichainNetworkController is integrated @@ -56,11 +53,10 @@ const useLatestBalance = ( ); } - if (isCaipChainId(chainId) && token?.decimals && token?.string) { - return calcTokenValue( - nonEvmBalances?.[`${token.address}`]?.amount ?? token.string, - token.decimals, - ); + if (isCaipChainId(chainId) && token?.decimals) { + return Numeric.from( + nonEvmBalances?.[token.address]?.amount ?? token?.string, + ).shiftedBy(-1 * token.decimals); } return undefined; @@ -79,14 +75,13 @@ const useLatestBalance = ( ); } - const tokenDecimals = token?.decimals ? Number(token.decimals) : 1; - - return { - balanceAmount: - token && latestBalance - ? calcTokenAmount(latestBalance.toString(), tokenDecimals) + return useMemo( + () => + value?.value + ? calcTokenAmount(value.value.toString(), token?.decimals) : undefined, - }; + [value, token?.decimals], + ); }; export default useLatestBalance; diff --git a/ui/hooks/bridge/useQuoteFetchEvents.ts b/ui/hooks/bridge/useQuoteFetchEvents.ts index a272430c3f2a..d890d5b30e60 100644 --- a/ui/hooks/bridge/useQuoteFetchEvents.ts +++ b/ui/hooks/bridge/useQuoteFetchEvents.ts @@ -44,8 +44,8 @@ export const useQuoteFetchEvents = () => { const fromToken = useSelector(getFromToken); const fromChain = useSelector(getFromChain); - const { balanceAmount } = useLatestBalance(fromToken, fromChain?.chainId); - const { balanceAmount: nativeAssetBalance } = useLatestBalance( + const balanceAmount = useLatestBalance(fromToken, fromChain?.chainId); + const nativeAssetBalance = useLatestBalance( fromChain?.chainId ? SWAPS_CHAINID_DEFAULT_TOKEN_MAP[ fromChain.chainId as keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP diff --git a/ui/pages/bridge/prepare/bridge-cta-button.tsx b/ui/pages/bridge/prepare/bridge-cta-button.tsx index 7b8fdf397e5a..303c1f544ea1 100644 --- a/ui/pages/bridge/prepare/bridge-cta-button.tsx +++ b/ui/pages/bridge/prepare/bridge-cta-button.tsx @@ -73,8 +73,8 @@ export const BridgeCTAButton = ({ const wasTxDeclined = useSelector(getWasTxDeclined); - const { balanceAmount } = useLatestBalance(fromToken, fromChain?.chainId); - const { balanceAmount: nativeAssetBalance } = useLatestBalance( + const balanceAmount = useLatestBalance(fromToken, fromChain?.chainId); + const nativeAssetBalance = useLatestBalance( fromChain?.chainId ? SWAPS_CHAINID_DEFAULT_TOKEN_MAP[ fromChain.chainId as keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP diff --git a/ui/pages/bridge/prepare/bridge-input-group.tsx b/ui/pages/bridge/prepare/bridge-input-group.tsx index 9d974ca4dc54..2c9f0950ad32 100644 --- a/ui/pages/bridge/prepare/bridge-input-group.tsx +++ b/ui/pages/bridge/prepare/bridge-input-group.tsx @@ -87,10 +87,10 @@ export const BridgeInputGroup = ({ const locale = useSelector(getIntlLocale); const selectedChainId = networkProps?.network?.chainId; - const { balanceAmount } = useLatestBalance(token, selectedChainId); + const balanceAmount = useLatestBalance(token, selectedChainId); // const currentChainId = useMultichainSelector(getMultichainCurrentChainId); // const selectedChainId = networkProps?.network?.chainId ?? currentChainId; - // const { balanceAmount } = useLatestBalance(token, selectedChainId); + // const balanceAmount = useLatestBalance(token, selectedChainId); const [, handleCopy] = useCopyToClipboard(MINUTE) as [ boolean, diff --git a/ui/pages/bridge/prepare/prepare-bridge-page.tsx b/ui/pages/bridge/prepare/prepare-bridge-page.tsx index 54ba69eeaf39..46beea0a53a1 100644 --- a/ui/pages/bridge/prepare/prepare-bridge-page.tsx +++ b/ui/pages/bridge/prepare/prepare-bridge-page.tsx @@ -175,17 +175,14 @@ const PrepareBridgePage = () => { const { quotesRefreshCount } = useSelector(getBridgeQuotes); const { openBuyCryptoInPdapp } = useRamps(); - const { balanceAmount: nativeAssetBalance } = useLatestBalance( + const nativeAssetBalance = useLatestBalance( SWAPS_CHAINID_DEFAULT_TOKEN_MAP[ fromChain?.chainId as keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP ], fromChain?.chainId, ); - const { balanceAmount: srcTokenBalance } = useLatestBalance( - fromToken, - fromChain?.chainId, - ); + const srcTokenBalance = useLatestBalance(fromToken, fromChain?.chainId); const { filteredTokenListGenerator: toTokenListGenerator,