import React, { Component } from 'react'; import PropTypes from 'prop-types'; import copyToClipboard from 'copy-to-clipboard'; import classnames from 'classnames'; import log from 'loglevel'; import AccountListItem from '../../components/app/account-list-item'; import Identicon from '../../components/ui/identicon'; import Tooltip from '../../components/ui/tooltip'; import { PageContainerFooter } from '../../components/ui/page-container'; import { MetaMetricsEventCategory } from '../../../shared/constants/metametrics'; import { SECOND } from '../../../shared/constants/time'; import { Numeric } from '../../../shared/modules/Numeric'; import { EtherDenomination } from '../../../shared/constants/common'; import { Icon, IconName } from '../../components/component-library'; import { IconColor } from '../../helpers/constants/design-system'; import { formatCurrency } from '../../helpers/utils/confirm-tx.util'; import { getValueFromWeiHex } from '../../../shared/modules/conversion.utils'; export default class ConfirmDecryptMessage extends Component { static contextTypes = { t: PropTypes.func.isRequired, trackEvent: PropTypes.func.isRequired, }; static propTypes = { fromAccount: PropTypes.shape({ address: PropTypes.string.isRequired, balance: PropTypes.string, name: PropTypes.string, }).isRequired, clearConfirmTransaction: PropTypes.func.isRequired, cancelDecryptMessage: PropTypes.func.isRequired, decryptMessage: PropTypes.func.isRequired, decryptMessageInline: PropTypes.func.isRequired, history: PropTypes.object.isRequired, mostRecentOverviewPage: PropTypes.string.isRequired, requesterAddress: PropTypes.string, txData: PropTypes.object, subjectMetadata: PropTypes.object, nativeCurrency: PropTypes.string.isRequired, currentCurrency: PropTypes.string.isRequired, conversionRate: PropTypes.number, }; state = { copyToClipboardPressed: false, hasCopied: false, }; copyMessage = () => { copyToClipboard(this.state.rawMessage); this.context.trackEvent({ category: MetaMetricsEventCategory.Messages, event: 'Copy', properties: { action: 'Decrypt Message Copy', legacy_event: true, }, }); this.setState({ hasCopied: true }); setTimeout(() => this.setState({ hasCopied: false }), SECOND * 3); }; renderHeader = () => { return (
{this.context.t('decryptRequest')}
); }; renderAccount = () => { const { fromAccount } = this.props; const { t } = this.context; return (
{`${t('account')}:`}
); }; renderBalance = () => { const { conversionRate, nativeCurrency, currentCurrency, fromAccount: { balance }, } = this.props; const { t } = this.context; const nativeCurrencyBalance = conversionRate ? formatCurrency( getValueFromWeiHex({ value: balance, fromCurrency: nativeCurrency, toCurrency: currentCurrency, conversionRate, numberOfDecimals: 6, toDenomination: EtherDenomination.ETH, }), currentCurrency, ) : new Numeric(balance, 16, EtherDenomination.WEI) .toDenomination(EtherDenomination.ETH) .round(6) .toBase(10) .toString(); return (
{`${t('balance')}:`}
{`${nativeCurrencyBalance} ${ conversionRate ? currentCurrency?.toUpperCase() : nativeCurrency }`}
); }; renderRequestIcon = () => { const { requesterAddress } = this.props; return (
); }; renderAccountInfo = () => { return (
{this.renderAccount()} {this.renderRequestIcon()} {this.renderBalance()}
); }; renderBody = () => { const { decryptMessageInline, subjectMetadata, txData } = this.props; const { t } = this.context; const targetSubjectMetadata = subjectMetadata[txData.msgParams.origin]; const name = targetSubjectMetadata?.name || txData.msgParams.origin; const notice = t('decryptMessageNotice', [txData.msgParams.origin]); const { hasCopied, hasDecrypted, hasError, rawMessage, errorMessage, copyToClipboardPressed, } = this.state; return (
{this.renderAccountInfo()}
{targetSubjectMetadata?.iconUrl ? ( ) : ( {name.charAt(0).toUpperCase()} )}
{notice}
{!hasDecrypted && !hasError ? txData.msgParams.data : rawMessage} {hasError ? errorMessage : ''}
{ decryptMessageInline(txData, event).then((result) => { if (result.error) { this.setState({ hasError: true, errorMessage: this.context.t('decryptInlineError', [ result.error, ]), }); } else { this.setState({ hasDecrypted: true, rawMessage: result.rawSig, }); } }); }} >
{t('decryptMetamask')}
{hasDecrypted ? (
this.copyMessage()} onMouseDown={() => this.setState({ copyToClipboardPressed: true })} onMouseUp={() => this.setState({ copyToClipboardPressed: false })} >
{t('decryptCopy')}
) : (
)}
); }; renderFooter = () => { const { cancelDecryptMessage, clearConfirmTransaction, decryptMessage, history, mostRecentOverviewPage, txData, } = this.props; const { trackEvent, t } = this.context; return ( { await cancelDecryptMessage(txData, event); trackEvent({ category: MetaMetricsEventCategory.Messages, event: 'Cancel', properties: { action: 'Decrypt Message Request', legacy_event: true, }, }); clearConfirmTransaction(); history.push(mostRecentOverviewPage); }} onSubmit={async (event) => { await decryptMessage(txData, event); trackEvent({ category: MetaMetricsEventCategory.Messages, event: 'Confirm', properties: { action: 'Decrypt Message Request', legacy_event: true, }, }); clearConfirmTransaction(); history.push(mostRecentOverviewPage); }} /> ); }; render = () => { if (!this.props.txData) { log.warn('ConfirmDecryptMessage Page: Missing txData prop.'); return null; } return (
{this.renderHeader()} {this.renderBody()} {this.renderFooter()}
); }; }