import React from 'react'; import PropTypes from 'prop-types'; import { getAccountLink } from '@metamask/etherscan-link'; import { useSelector } from 'react-redux'; import Box from '../../../ui/box'; import Button from '../../../ui/button/button.component'; import Tooltip from '../../../ui/tooltip/tooltip'; import { useI18nContext } from '../../../../hooks/useI18nContext'; import Identicon from '../../../ui/identicon'; import { ellipsify } from '../../../../pages/send/send.utils'; import Popover from '../../../ui/popover'; import Typography from '../../../ui/typography'; import { FONT_WEIGHT, TypographyVariant, DISPLAY, Size, BorderStyle, BorderColor, TextColor, Color, AlignItems, } from '../../../../helpers/constants/design-system'; import { useCopyToClipboard } from '../../../../hooks/useCopyToClipboard'; import { getAddressBookEntry } from '../../../../selectors'; import { TokenStandard } from '../../../../../shared/constants/transaction'; import NftCollectionImage from '../../../ui/nft-collection-image/nft-collection-image'; import { ButtonIcon } from '../../../component-library'; import { ICON_NAMES } from '../../../component-library/icon/deprecated'; export default function ContractDetailsModal({ onClose, tokenName, tokenAddress, toAddress, chainId, rpcPrefs, tokenId, assetName, assetStandard, isContractRequestingSignature, }) { const t = useI18nContext(); const [copiedTokenAddress, handleCopyTokenAddress] = useCopyToClipboard(); const [copiedToAddress, handleCopyToAddress] = useCopyToClipboard(); const addressBookEntry = useSelector((state) => ({ data: getAddressBookEntry(state, toAddress), })); const nft = assetStandard === TokenStandard.ERC721 || assetStandard === TokenStandard.ERC1155 || // if we don't have an asset standard but we do have either both an assetname and a tokenID or both a tokenName and tokenId we assume its an NFT (assetName && tokenId) || (tokenName && tokenId); return ( {t('contractTitle')} {t('contractDescription')} {!isContractRequestingSignature && ( <> {nft ? t('contractNFT') : t('contractToken')} {nft ? ( ) : ( )} {tokenName || ellipsify(tokenAddress)} {tokenName && ( {ellipsify(tokenAddress)} )} handleCopyTokenAddress(tokenAddress)} color={Color.iconMuted} ariaLabel={ copiedTokenAddress ? t('copiedExclamation') : t('copyToClipboard') } /> { const blockExplorerTokenLink = getAccountLink( tokenAddress, chainId, { blockExplorerUrl: rpcPrefs?.blockExplorerUrl ?? null, }, null, ); global.platform.openTab({ url: blockExplorerTokenLink, }); }} ariaLabel={t('openInBlockExplorer')} /> )} {nft && t('contractRequestingAccess')} {isContractRequestingSignature && t('contractRequestingSignature')} {!nft && !isContractRequestingSignature && t('contractRequestingSpendingCap')} {addressBookEntry?.data?.name || ellipsify(toAddress)} {addressBookEntry?.data?.name && ( {ellipsify(toAddress)} )} handleCopyToAddress(toAddress)} color={Color.iconMuted} ariaLabel={ copiedTokenAddress ? t('copiedExclamation') : t('copyToClipboard') } /> { const blockExplorerTokenLink = getAccountLink( toAddress, chainId, { blockExplorerUrl: rpcPrefs?.blockExplorerUrl ?? null, }, null, ); global.platform.openTab({ url: blockExplorerTokenLink, }); }} ariaLabel={t('openInBlockExplorer')} /> ); } ContractDetailsModal.propTypes = { /** * Function that should close the modal */ onClose: PropTypes.func, /** * Name of the token that is waiting to be allowed */ tokenName: PropTypes.string, /** * Address of the token that is waiting to be allowed */ tokenAddress: PropTypes.string, /** * Contract address requesting spending cap */ toAddress: PropTypes.string, /** * Current network chainId */ chainId: PropTypes.string, /** * RPC prefs of the current network */ rpcPrefs: PropTypes.object, /** * The token id of the NFT */ tokenId: PropTypes.string, /** * Token Standard */ assetStandard: PropTypes.string, /** * The name of the collection */ assetName: PropTypes.string, /** * Whether contract requesting signature flow has started */ isContractRequestingSignature: PropTypes.bool, };