import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { startCase } from 'lodash'; import ToggleButton from '../../../components/ui/toggle-button'; import TextField from '../../../components/ui/text-field'; import { ADD_POPULAR_CUSTOM_NETWORK, REVEAL_SEED_ROUTE, } from '../../../helpers/constants/routes'; import Button from '../../../components/ui/button'; import { getNumberOfSettingsInSection, handleSettingsRefs, } from '../../../helpers/utils/settings-search'; import { MetaMetricsEventCategory, MetaMetricsEventKeyType, MetaMetricsEventName, } from '../../../../shared/constants/metametrics'; import { COINGECKO_LINK, CRYPTOCOMPARE_LINK, PRIVACY_POLICY_LINK, AUTO_DETECT_TOKEN_LEARN_MORE_LINK, CONSENSYS_PRIVACY_LINK, ETHERSCAN_PRIVACY_LINK, } from '../../../../shared/lib/ui-utils'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; import { addUrlProtocolPrefix, getEnvironmentType, } from '../../../../app/scripts/lib/util'; export default class SecurityTab extends PureComponent { static contextTypes = { t: PropTypes.func, trackEvent: PropTypes.func, }; static propTypes = { warning: PropTypes.string, history: PropTypes.object, participateInMetaMetrics: PropTypes.bool.isRequired, setParticipateInMetaMetrics: PropTypes.func.isRequired, showIncomingTransactions: PropTypes.bool.isRequired, setShowIncomingTransactionsFeatureFlag: PropTypes.func.isRequired, setUsePhishDetect: PropTypes.func.isRequired, usePhishDetect: PropTypes.bool.isRequired, useTokenDetection: PropTypes.bool.isRequired, setUseTokenDetection: PropTypes.func.isRequired, setIpfsGateway: PropTypes.func.isRequired, ipfsGateway: PropTypes.string.isRequired, useMultiAccountBalanceChecker: PropTypes.bool.isRequired, setUseMultiAccountBalanceChecker: PropTypes.func.isRequired, useCurrencyRateCheck: PropTypes.bool.isRequired, setUseCurrencyRateCheck: PropTypes.func.isRequired, }; state = { ipfsGateway: this.props.ipfsGateway, ipfsGatewayError: '', }; settingsRefCounter = 0; settingsRefs = Array( getNumberOfSettingsInSection( this.context.t, this.context.t('securityAndPrivacy'), ), ) .fill(undefined) .map(() => { return React.createRef(); }); componentDidUpdate() { const { t } = this.context; handleSettingsRefs(t, t('securityAndPrivacy'), this.settingsRefs); } componentDidMount() { const { t } = this.context; handleSettingsRefs(t, t('securityAndPrivacy'), this.settingsRefs); } toggleSetting(value, eventName, eventAction, toggleMethod) { this.context.trackEvent({ category: MetaMetricsEventCategory.Settings, event: eventName, properties: { action: eventAction, legacy_event: true, }, }); toggleMethod(!value); } renderSeedWords() { const { t } = this.context; const { history } = this.props; return (
{t('revealSeedWords')}
); } renderIncomingTransactionsOptIn() { const { t } = this.context; const { showIncomingTransactions, setShowIncomingTransactionsFeatureFlag } = this.props; return (
{t('showIncomingTransactions')}
{t('showIncomingTransactionsDescription', [ // TODO: Update to use real link {t('etherscan')} , // TODO: Update to use real link {t('privacyMsg')} , ])}
setShowIncomingTransactionsFeatureFlag(!value) } offLabel={t('off')} onLabel={t('on')} />
); } renderPhishingDetectionToggle() { const { t } = this.context; const { usePhishDetect, setUsePhishDetect } = this.props; return (
{t('usePhishingDetection')}
{t('usePhishingDetectionDescription')}
setUsePhishDetect(!value)} offLabel={t('off')} onLabel={t('on')} />
); } renderMetaMetricsOptIn() { const { t } = this.context; const { participateInMetaMetrics, setParticipateInMetaMetrics } = this.props; return (
{t('participateInMetaMetrics')}
{t('participateInMetaMetricsDescription')}
setParticipateInMetaMetrics(!value)} offLabel={t('off')} onLabel={t('on')} />
); } renderChooseYourNetworkButton() { const { t } = this.context; return (
{t('chooseYourNetwork')}
{t('chooseYourNetworkDescription', [ // TODO: Update to use real link {t('privacyMsg')} , ])}
); } renderIpfsGatewayControl() { const { t } = this.context; const { ipfsGatewayError } = this.state; const handleIpfsGatewaySave = (gateway) => { const url = new URL(addUrlProtocolPrefix(gateway)); const { host } = url; this.props.setIpfsGateway(host); }; const handleIpfsGatewayChange = (url) => { this.setState(() => { let ipfsError = ''; try { const urlObj = new URL(addUrlProtocolPrefix(url)); if (!urlObj.host) { throw new Error(); } // don't allow the use of this gateway if (urlObj.host === 'gateway.ipfs.io') { throw new Error('Forbidden gateway'); } } catch (error) { ipfsError = error.message === 'Forbidden gateway' ? t('forbiddenIpfsGateway') : t('invalidIpfsGateway'); } handleIpfsGatewaySave(url); return { ipfsGateway: url, ipfsGatewayError: ipfsError, }; }); }; return (
{t('addCustomIPFSGateway')}
{t('addCustomIPFSGatewayDescription')}
handleIpfsGatewayChange(e.target.value)} error={ipfsGatewayError} fullWidth margin="dense" />
); } renderAutoDectectTokensToggle() { const { t } = this.context; const { useTokenDetection, setUseTokenDetection } = this.props; return (
{t('autoDetectTokens')}
{t('autoDetectTokensDescription', [ // TODO: Update to use real link {startCase(t('learnMore'))} , ])}
{ this.toggleSetting( value, MetaMetricsEventName.KeyAutoDetectTokens, MetaMetricsEventName.KeyAutoDetectTokens, setUseTokenDetection, ); }} offLabel={t('off')} onLabel={t('on')} />
); } renderBatchAccountBalanceRequestsToggle() { const { t } = this.context; const { useMultiAccountBalanceChecker, setUseMultiAccountBalanceChecker } = this.props; return (
{t('useMultiAccountBalanceChecker')}
{t('useMultiAccountBalanceCheckerDescription')}
{ this.toggleSetting( value, MetaMetricsEventName.KeyBatchAccountBalanceRequests, MetaMetricsEventName.KeyBatchAccountBalanceRequests, setUseMultiAccountBalanceChecker, ); }} offLabel={t('off')} onLabel={t('on')} />
); } renderCurrencyRateCheckToggle() { const { t } = this.context; const { useCurrencyRateCheck, setUseCurrencyRateCheck } = this.props; return (
{t('currencyRateCheckToggle')}
{t('currencyRateCheckToggleDescription', [ {t('coingecko')} , {t('cryptoCompare')} , {t('privacyMsg')} , ])}
setUseCurrencyRateCheck(!value)} offLabel={t('off')} onLabel={t('on')} />
); } render() { const { warning } = this.props; return (
{warning ?
{warning}
: null} {this.context.t('security')}
{this.renderSeedWords()}
{this.context.t('privacy')}
Alerts
{this.renderPhishingDetectionToggle()}
{this.context.t('transactions')}
{this.renderCurrencyRateCheckToggle()} {this.renderIncomingTransactionsOptIn()}
{this.context.t('networkProvider')}
{this.renderChooseYourNetworkButton()} {this.renderIpfsGatewayControl()}
{this.context.t('tokenAutoDetection')}
{this.renderAutoDectectTokensToggle()} {this.renderBatchAccountBalanceRequestsToggle()}
{this.context.t('metrics')}
{this.renderMetaMetricsOptIn()}
); } }