import React, { PureComponent } from 'react'; import { memoize } from 'lodash'; import PropTypes from 'prop-types'; import LedgerInstructionField from '../ledger-instruction-field'; import { sanitizeMessage, getURLHostName } from '../../../helpers/utils/util'; import { EVENT } from '../../../../shared/constants/metametrics'; import { conversionUtil } from '../../../../shared/modules/conversion.utils'; import SiteOrigin from '../../ui/site-origin'; import Button from '../../ui/button'; import Typography from '../../ui/typography/typography'; import ContractDetailsModal from '../modals/contract-details-modal/contract-details-modal'; import { TYPOGRAPHY, FONT_WEIGHT, COLORS, TEXT_ALIGN, } from '../../../helpers/constants/design-system'; import NetworkAccountBalanceHeader from '../network-account-balance-header'; import { NETWORK_TYPES } from '../../../../shared/constants/network'; import Footer from './signature-request-footer'; import Message from './signature-request-message'; export default class SignatureRequest extends PureComponent { static propTypes = { /** * The display content of transaction data */ txData: PropTypes.object.isRequired, /** * The display content of sender account */ fromAccount: PropTypes.shape({ address: PropTypes.string.isRequired, balance: PropTypes.string, name: PropTypes.string, }).isRequired, /** * Check if the wallet is ledget wallet or not */ isLedgerWallet: PropTypes.bool, /** * Handler for cancel button */ cancel: PropTypes.func.isRequired, /** * Handler for sign button */ sign: PropTypes.func.isRequired, /** * Whether the hardware wallet requires a connection disables the sign button if true. */ hardwareWalletRequiresConnection: PropTypes.bool.isRequired, /** * Current network chainId */ chainId: PropTypes.string, /** * RPC prefs of the current network */ rpcPrefs: PropTypes.object, /** * Dapp image */ siteImage: PropTypes.string, conversionRate: PropTypes.number, nativeCurrency: PropTypes.string, provider: PropTypes.object, subjectMetadata: PropTypes.object, }; static contextTypes = { t: PropTypes.func, trackEvent: PropTypes.func, }; state = { hasScrolledMessage: false, showContractDetails: false, }; setMessageRootRef(ref) { this.messageRootRef = ref; } formatWallet(wallet) { return `${wallet.slice(0, 8)}...${wallet.slice( wallet.length - 8, wallet.length, )}`; } getNetworkName() { const { provider } = this.props; const providerName = provider.type; const { t } = this.context; switch (providerName) { case NETWORK_TYPES.MAINNET: return t('mainnet'); case NETWORK_TYPES.GOERLI: return t('goerli'); case NETWORK_TYPES.SEPOLIA: return t('sepolia'); case NETWORK_TYPES.LOCALHOST: return t('localhost'); default: return provider.nickname || t('unknownNetwork'); } } memoizedParseMessage = memoize((data) => { const { message, domain = {}, primaryType, types } = JSON.parse(data); const sanitizedMessage = sanitizeMessage(message, primaryType, types); return { sanitizedMessage, domain, primaryType }; }); render() { const { txData: { msgParams: { data, origin, version }, type, }, fromAccount: { address, balance, name }, cancel, sign, isLedgerWallet, hardwareWalletRequiresConnection, chainId, rpcPrefs, siteImage, txData, subjectMetadata, conversionRate, nativeCurrency, } = this.props; const { trackEvent } = this.context; const { sanitizedMessage, domain: { verifyingContract }, primaryType, } = this.memoizedParseMessage(data); const currentNetwork = this.getNetworkName(); const balanceInBaseAsset = conversionUtil(balance, { fromNumericBase: 'hex', toNumericBase: 'dec', fromDenomination: 'WEI', numberOfDecimals: 6, conversionRate, }); const onSign = (event) => { sign(event); trackEvent({ category: EVENT.CATEGORIES.TRANSACTIONS, event: 'Confirm', properties: { action: 'Sign Request', legacy_event: true, type, version, }, }); }; const onCancel = (event) => { cancel(event); trackEvent({ category: EVENT.CATEGORIES.TRANSACTIONS, event: 'Cancel', properties: { action: 'Sign Request', legacy_event: true, type, version, }, }); }; const messageIsScrollable = this.messageRootRef?.scrollHeight > this.messageRootRef?.clientHeight; const targetSubjectMetadata = txData.msgParams.origin ? subjectMetadata?.[txData.msgParams.origin] : null; return (
{this.context.t('sigRequest')} {this.context.t('signatureRequestGuidance')} {verifyingContract ? (
) : null}
{isLedgerWallet ? (
) : null} this.setState({ hasScrolledMessage: true })} setMessageRootRef={this.setMessageRootRef.bind(this)} messageRootRef={this.messageRootRef} messageIsScrollable={messageIsScrollable} primaryType={primaryType} />
); } }