From d575c72127524ad72b57231ac117512cb003a923 Mon Sep 17 00:00:00 2001 From: Jordan Frankfurt Date: Wed, 2 Nov 2022 16:56:37 -0500 Subject: [PATCH] feat(nft-bag): wrong-network-cta (#5056) * pull warning out into its own component * add wrong network cta * simplify sufficient balance logic * consolidate warning and button text logic --- src/nft/components/bag/Bag.tsx | 16 +--- src/nft/components/bag/BagFooter.tsx | 131 ++++++++++++++++++--------- 2 files changed, 91 insertions(+), 56 deletions(-) diff --git a/src/nft/components/bag/Bag.tsx b/src/nft/components/bag/Bag.tsx index 7ab2387f23..dbafe20e4f 100644 --- a/src/nft/components/bag/Bag.tsx +++ b/src/nft/components/bag/Bag.tsx @@ -1,7 +1,6 @@ import { BigNumber } from '@ethersproject/bignumber' import { formatEther } from '@ethersproject/units' import { useWeb3React } from '@web3-react/core' -import { parseEther } from 'ethers/lib/utils' import { BagFooter } from 'nft/components/bag/BagFooter' import ListingModal from 'nft/components/bag/profile/ListingModal' import { Box } from 'nft/components/Box' @@ -16,7 +15,6 @@ import { useSellAsset, useSendTransaction, useTransactionResponse, - useWalletBalance, } from 'nft/hooks' import { fetchRoute } from 'nft/queries' import { BagItemStatus, BagStatus, ProfilePageStateType, RouteResponse, TxStateType } from 'nft/types' @@ -57,7 +55,8 @@ const ScrollingIndicator = ({ top, show }: SeparatorProps) => ( ) const Bag = () => { - const { account } = useWeb3React() + const { account, provider } = useWeb3React() + const bagStatus = useBag((s) => s.bagStatus) const setBagStatus = useBag((s) => s.setBagStatus) const didOpenUnavailableAssets = useBag((s) => s.didOpenUnavailableAssets) @@ -76,9 +75,6 @@ const Bag = () => { const setTotalEthPrice = useBag((s) => s.setTotalEthPrice) const setTotalUsdPrice = useBag((s) => s.setTotalUsdPrice) - const { address, balance: balanceInEth, provider } = useWalletBalance() - const isConnected = !!provider && !!address - const { pathname } = useLocation() const isProfilePage = pathname.startsWith('/profile') const isNFTPage = pathname.startsWith('/nfts') @@ -126,11 +122,6 @@ const Bag = () => { return { totalEthPrice, totalUsdPrice } }, [itemsInBag, fetchedPriceData]) - const sufficientBalance = useMemo(() => { - const balance = parseEther(balanceInEth.toString()) - return isConnected ? BigNumber.from(balance).gte(totalEthPrice) : true - }, [balanceInEth, totalEthPrice, isConnected]) - const purchaseAssets = async (routingData: RouteResponse) => { if (!provider || !routingData) return const purchaseResponse = await sendTransaction( @@ -279,13 +270,10 @@ const Bag = () => { {hasAssetsToShow && !isProfilePage && ( item.status === BagItemStatus.REVIEWING_PRICE_CHANGE)} eventProperties={{ usd_value: totalUsdPrice, ...formatAssetEventProperties(itemsInBag.map((item) => item.asset)), diff --git a/src/nft/components/bag/BagFooter.tsx b/src/nft/components/bag/BagFooter.tsx index 7b1b513c10..a1349ba6eb 100644 --- a/src/nft/components/bag/BagFooter.tsx +++ b/src/nft/components/bag/BagFooter.tsx @@ -1,18 +1,24 @@ import { BigNumber } from '@ethersproject/bignumber' +import { parseEther } from '@ethersproject/units' import { Trans } from '@lingui/macro' +import { useWeb3React } from '@web3-react/core' import { ElementName, Event, EventName } from 'analytics/constants' import { TraceEvent } from 'analytics/TraceEvent' import Loader from 'components/Loader' +import { SupportedChainId } from 'constants/chains' import { Box } from 'nft/components/Box' import { Column, Row } from 'nft/components/Flex' import { bodySmall } from 'nft/css/common.css' +import { useWalletBalance } from 'nft/hooks/useWalletBalance' import { BagStatus } from 'nft/types' import { ethNumberStandardFormatter, formatWeiToDecimal } from 'nft/utils' +import { PropsWithChildren, useCallback, useMemo } from 'react' import { AlertTriangle } from 'react-feather' import { useModalIsOpen, useToggleWalletModal } from 'state/application/hooks' import { ApplicationModal } from 'state/application/reducer' import styled from 'styled-components/macro' import { ThemedText } from 'theme' +import { switchChain } from 'utils/switchChain' import * as styles from './BagFooter.css' @@ -42,14 +48,36 @@ const WarningText = styled(ThemedText.BodyPrimary)` text-align: center; ` +interface ActionButtonProps { + disabled?: boolean + onClick: () => void +} + +const ActionButton = ({ disabled, children, onClick }: PropsWithChildren) => { + return ( + + {children} + + ) +} + +const Warning = ({ children }: PropsWithChildren) => { + if (!children) { + return null + } + return ( + + + {children} + + ) +} + interface BagFooterProps { - isConnected: boolean - sufficientBalance: boolean totalEthPrice: BigNumber totalUsdPrice: number | undefined bagStatus: BagStatus fetchAssets: () => void - assetsAreInReview: boolean eventProperties: Record } @@ -61,26 +89,72 @@ const PENDING_BAG_STATUSES = [ ] export const BagFooter = ({ - isConnected, - sufficientBalance, totalEthPrice, totalUsdPrice, bagStatus, fetchAssets, - assetsAreInReview, eventProperties, }: BagFooterProps) => { const toggleWalletModal = useToggleWalletModal() const walletModalIsOpen = useModalIsOpen(ApplicationModal.WALLET) + const { account, chainId, connector } = useWeb3React() + const connected = Boolean(account && chainId) + + const handleClick = useCallback(() => { + if (!connected) { + toggleWalletModal() + } else if (connected && chainId !== SupportedChainId.MAINNET) { + switchChain(connector, SupportedChainId.MAINNET) + } else { + fetchAssets() + } + }, [connected, chainId, toggleWalletModal, connector, fetchAssets]) + + const { balance: balanceInEth } = useWalletBalance() + const sufficientBalance = useMemo(() => { + if (!connected || chainId !== SupportedChainId.MAINNET) { + return undefined + } + return parseEther(balanceInEth).gte(totalEthPrice) + }, [connected, chainId, balanceInEth, totalEthPrice]) + + const { buttonText, disabled, warningText } = useMemo(() => { + let buttonText = Something went wrong + let disabled = true + let warningText = null + + if (connected && chainId !== SupportedChainId.MAINNET) { + buttonText = Switch networks + disabled = false + warningText = Wrong network + } else if (sufficientBalance === false) { + buttonText = Pay + disabled = true + warningText = Insufficient funds + } else if (bagStatus === BagStatus.WARNING) { + warningText = Something went wrong. Please try again. + } else if (!connected || walletModalIsOpen) { + disabled = false + buttonText = Connect wallet + } else if (bagStatus === BagStatus.FETCHING_FINAL_ROUTE || bagStatus === BagStatus.CONFIRMING_IN_WALLET) { + disabled = true + buttonText = Proceed in wallet + } else if (bagStatus === BagStatus.PROCESSING_TRANSACTION) { + disabled = true + buttonText = Transaction pending + } else if (sufficientBalance === true) { + disabled = false + buttonText = Pay + } + + return { buttonText, disabled, warningText } + }, [bagStatus, chainId, connected, sufficientBalance, walletModalIsOpen]) const isPending = PENDING_BAG_STATUSES.includes(bagStatus) || walletModalIsOpen - const isDisabled = isConnected && (isPending || !sufficientBalance || assetsAreInReview) - - const showWarning = isConnected && (!sufficientBalance || bagStatus === BagStatus.WARNING) return ( -