import React from 'react'; import { generateMnemonic } from 'bip39'; import translate from 'translations'; import shuffle from 'lodash/shuffle'; import Word from './Word'; import FinalSteps from '../FinalSteps'; import Template from '../Template'; import { WalletType } from '../../GenerateWallet'; import './Mnemonic.scss'; interface State { words: string[]; confirmValues: string[]; confirmWords: WordTuple[][]; isConfirming: boolean; isConfirmed: boolean; isRevealingNextWord: boolean; } interface WordTuple { word: string; index: number; } export default class GenerateMnemonic extends React.Component<{}, State> { public state: State = { words: [], confirmValues: [], confirmWords: [], isConfirming: false, isConfirmed: false, isRevealingNextWord: false }; public componentDidMount() { this.regenerateWordArray(); } public render() { const { words, confirmWords, isConfirming, isConfirmed } = this.state; const defaultBtnClassName = 'GenerateMnemonic-buttons-btn btn btn-default'; const canContinue = this.checkCanContinue(); const [firstHalf, lastHalf] = confirmWords.length === 0 ? this.splitWordsIntoHalves(words) : confirmWords; const content = isConfirmed ? ( ) : (

{translate('GENERATE_MNEMONIC_TITLE')}

{isConfirming ? translate('MNEMONIC_DESCRIPTION_1') : translate('MNEMONIC_DESCRIPTION_2')}

{[firstHalf, lastHalf].map((ws, i) => (
{ws.map(this.makeWord)}
))}
{!isConfirming && ( )} {isConfirming && ( )}
); return ; } private regenerateWordArray = () => { this.setState({ words: generateMnemonic().split(' ') }); }; private goToNextStep = () => { if (!this.checkCanContinue()) { return; } if (this.state.isConfirming) { this.setState({ isConfirmed: true }); } else { const shuffledWords = shuffle(this.state.words); const confirmWords = this.splitWordsIntoHalves(shuffledWords); this.setState({ isConfirming: true, confirmWords }); } }; private checkCanContinue = () => { const { isConfirming, words, confirmValues } = this.state; if (isConfirming) { return words.reduce((prev, word, index) => { return word === confirmValues[index] && prev; }, true); } else { return !!words.length; } }; private makeWord = (word: WordTuple) => { const { words, confirmValues, isRevealingNextWord, isConfirming } = this.state; const confirmIndex = words.indexOf(word.word); const nextIndex = confirmValues.length; const isNext = confirmIndex === nextIndex; const isRevealed = isRevealingNextWord && isNext; const hasBeenConfirmed = this.getWordConfirmed(word.word); return ( ); }; private handleWordClick = (_: number, value: string) => { const { confirmValues: previousConfirmValues, words, isConfirming } = this.state; const wordAlreadyConfirmed = previousConfirmValues.includes(value); const activeIndex = previousConfirmValues.length; const isCorrectChoice = words[activeIndex] === value; if (isConfirming && !wordAlreadyConfirmed && isCorrectChoice) { const confirmValues = previousConfirmValues.concat(value); this.setState({ confirmValues }); } }; private getWordConfirmed = (word: string) => this.state.confirmValues.includes(word); private skip = () => { this.setState({ isConfirmed: true }); }; private revealNextWord = () => { const revealDuration = 400; this.setState( { isRevealingNextWord: true }, () => setTimeout( () => this.setState({ isRevealingNextWord: false }), revealDuration ) ); }; private splitWordsIntoHalves = (words: string[]) => { const firstHalf: WordTuple[] = []; const lastHalf: WordTuple[] = []; words.forEach((word: string, index: number) => { const inFirstColumn = index < words.length / 2; const half = inFirstColumn ? firstHalf : lastHalf; half.push({ word, index }); }); return [firstHalf, lastHalf]; }; }