diff --git a/common/components/WalletDecrypt/Mnemonic.tsx b/common/components/WalletDecrypt/Mnemonic.tsx index 060e09fc..111bd5aa 100644 --- a/common/components/WalletDecrypt/Mnemonic.tsx +++ b/common/components/WalletDecrypt/Mnemonic.tsx @@ -3,6 +3,7 @@ import DPATHS from 'config/dpaths'; import React, { Component } from 'react'; import translate, { translateRaw } from 'translations'; import DeterministicWalletsModal from './DeterministicWalletsModal'; +import { formatMnemonic } from 'utils/formatters'; const DEFAULT_PATH = DPATHS.MNEMONIC[0].value; @@ -11,6 +12,7 @@ interface Props { } interface State { phrase: string; + formattedPhrase: string; pass: string; seed: string; dPath: string; @@ -19,14 +21,15 @@ interface State { export default class MnemonicDecrypt extends Component { public state: State = { phrase: '', + formattedPhrase: '', pass: '', seed: '', dPath: DEFAULT_PATH }; public render() { - const { phrase, seed, dPath, pass } = this.state; - const isValidMnemonic = validateMnemonic(phrase); + const { phrase, formattedPhrase, seed, dPath, pass } = this.state; + const isValidMnemonic = validateMnemonic(formattedPhrase); return (
@@ -85,19 +88,25 @@ export default class MnemonicDecrypt extends Component { this.setState({ pass: (e.target as HTMLInputElement).value }); }; - public onMnemonicChange = (e: React.SyntheticEvent) => { - this.setState({ phrase: (e.target as HTMLTextAreaElement).value }); + public onMnemonicChange = (e: React.FormEvent) => { + const phrase = e.currentTarget.value; + const formattedPhrase = formatMnemonic(phrase); + + this.setState({ + phrase, + formattedPhrase + }); }; public onDWModalOpen = () => { - const { phrase, pass } = this.state; + const { formattedPhrase, pass } = this.state; - if (!validateMnemonic(phrase)) { + if (!validateMnemonic(formattedPhrase)) { return; } try { - const seed = mnemonicToSeed(phrase.trim(), pass).toString('hex'); + const seed = mnemonicToSeed(formattedPhrase, pass).toString('hex'); this.setState({ seed }); } catch (err) { console.log(err); @@ -113,19 +122,20 @@ export default class MnemonicDecrypt extends Component { }; private handleUnlock = (address, index) => { - const { phrase, pass, dPath } = this.state; + const { formattedPhrase, pass, dPath } = this.state; this.props.onUnlock({ path: `${dPath}/${index}`, pass, - phrase, + phrase: formattedPhrase, address }); this.setState({ seed: '', pass: '', - phrase: '' + phrase: '', + formattedPhrase: '' }); }; } diff --git a/common/utils/formatters.ts b/common/utils/formatters.ts index 7218f192..01ef91be 100644 --- a/common/utils/formatters.ts +++ b/common/utils/formatters.ts @@ -94,3 +94,11 @@ export function formatGasLimit(limit: Wei, transactionUnit: string = 'ether') { return limitStr; } + +// Regex modified from this stackoverflow answer +// https://stackoverflow.com/a/10805198, with the comma character added as a +// delimiter (in the case of csv style mnemonic phrases) as well as any stray +// space characters. it should be fairly easy to add new delimiters as required +export function formatMnemonic(phrase: string) { + return phrase.replace(/(\r\n|\n|\r|\s+|,)/gm," ").trim(); +}; \ No newline at end of file diff --git a/spec/utils/formatters.spec.ts b/spec/utils/formatters.spec.ts index 9a9c29c5..f10bd8fc 100644 --- a/spec/utils/formatters.spec.ts +++ b/spec/utils/formatters.spec.ts @@ -2,7 +2,8 @@ import { Wei } from 'libs/units'; import { toFixedIfLarger, formatNumber, - formatGasLimit + formatGasLimit, + formatMnemonic } from '../../common/utils/formatters'; describe('toFixedIfLarger', () => { @@ -93,3 +94,22 @@ describe('formatGasLimit', () => { expect(formatGasLimit(Wei('1234'))).toEqual('1234'); }); }); + +describe('formatMnemonic', () => { + const testPhraseNewLines = "first\ncatalog\naway\nfaculty\njelly\nnow\nlife\nkingdom\npigeon\nraise\ngain\naccident"; + const testPhraseExtraSpaces = "first catalog away faculty jelly now life kingdom pigeon raise gain accident "; + const testPhraseCommas = "first,catalog,away,faculty,jelly,now,life,kingdom,pigeon,raise,gain,accident"; + const formattedTestPhrase = "first catalog away faculty jelly now life kingdom pigeon raise gain accident"; + + it('should format phrases with new lines as a phrase with just spaces', () => { + expect(formatMnemonic(testPhraseNewLines)).toEqual(formattedTestPhrase); + }) + + it('should remove commas and replace with space characters', () => { + expect(formatMnemonic(testPhraseCommas)).toEqual(formattedTestPhrase); + }) + + it('should trim any stray space characters throughout the phrase', () => { + expect(formatMnemonic(testPhraseExtraSpaces)).toEqual(formattedTestPhrase); + }) +})