import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { ethers } from 'ethers'; import { createNewVaultAndRestore, unMarkPasswordForgotten, initializeThreeBox, } from '../../store/actions'; import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; import TextField from '../../components/ui/text-field'; import Button from '../../components/ui/button'; import { clearClipboard } from '../../helpers/utils/util'; const { isValidMnemonic } = ethers.utils; class RestoreVaultPage extends Component { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, }; static propTypes = { createNewVaultAndRestore: PropTypes.func.isRequired, leaveImportSeedScreenState: PropTypes.func, history: PropTypes.object, isLoading: PropTypes.bool, initializeThreeBox: PropTypes.func, }; state = { seedPhrase: '', showSeedPhrase: false, password: '', confirmPassword: '', seedPhraseError: null, passwordError: null, confirmPasswordError: null, }; parseSeedPhrase = (seedPhrase) => (seedPhrase || '').trim().toLowerCase().match(/\w+/gu)?.join(' ') || ''; handleSeedPhraseChange(seedPhrase) { const { t } = this.context; let seedPhraseError = null; const parseSeedPhrase = this.parseSeedPhrase(seedPhrase); const wordCount = parseSeedPhrase.split(/\s/u).length; if ( parseSeedPhrase && (wordCount % 3 !== 0 || wordCount < 12 || wordCount > 24) ) { seedPhraseError = t('seedPhraseReq'); } else if (!isValidMnemonic(parseSeedPhrase)) { seedPhraseError = t('invalidSeedPhrase'); } this.setState({ seedPhrase, seedPhraseError }); } handlePasswordChange(password) { const { confirmPassword } = this.state; let confirmPasswordError = null; let passwordError = null; if (password && password.length < 8) { passwordError = this.context.t('passwordNotLongEnough'); } if (confirmPassword && password !== confirmPassword) { confirmPasswordError = this.context.t('passwordsDontMatch'); } this.setState({ password, passwordError, confirmPasswordError }); } handleConfirmPasswordChange(confirmPassword) { const { password } = this.state; let confirmPasswordError = null; if (password !== confirmPassword) { confirmPasswordError = this.context.t('passwordsDontMatch'); } this.setState({ confirmPassword, confirmPasswordError }); } handleImport = (event) => { event.preventDefault(); const { password, seedPhrase, disabled } = this.state; if (disabled) return; const { // eslint-disable-next-line no-shadow createNewVaultAndRestore, leaveImportSeedScreenState, history, // eslint-disable-next-line no-shadow initializeThreeBox, } = this.props; leaveImportSeedScreenState(); createNewVaultAndRestore(password, this.parseSeedPhrase(seedPhrase)).then( () => { this.context.metricsEvent({ eventOpts: { category: 'Retention', action: 'userEntersSeedPhrase', name: 'onboardingRestoredVault', }, }); initializeThreeBox(); history.push(DEFAULT_ROUTE); }, ); }; hasError() { const { passwordError, confirmPasswordError, seedPhraseError } = this.state; return passwordError || confirmPasswordError || seedPhraseError; } toggleShowSeedPhrase = () => { this.setState(({ showSeedPhrase }) => ({ showSeedPhrase: !showSeedPhrase, })); }; render() { const { seedPhrase, showSeedPhrase, password, confirmPassword, seedPhraseError, passwordError, confirmPasswordError, } = this.state; const { t } = this.context; const { isLoading } = this.props; const disabled = !seedPhrase || !password || !confirmPassword || isLoading || this.hasError(); return (