Skip to content

Commit

Permalink
Allow for 24 length seedphrase on import (#1848)
Browse files Browse the repository at this point in the history
* Allow for 24 length seedphrase on import, closes #1838

* call toggleHideSeedPhraseInput onScanError

* Update broken seed phrase translation keys

* Add proper logging for when seed phrase does fail

* Validate mnemonic with ethers

* Add tests for failedSeedPhraseRequirements
  • Loading branch information
rickycodes authored Sep 28, 2020
1 parent f575ff4 commit 82f8f77
Show file tree
Hide file tree
Showing 7 changed files with 442 additions and 31 deletions.
29 changes: 23 additions & 6 deletions app/components/Views/ImportFromSeed/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import TermsAndConditions from '../TermsAndConditions';
import zxcvbn from 'zxcvbn';
import Icon from 'react-native-vector-icons/FontAwesome';
import Device from '../../../util/Device';
import { failedSeedPhraseRequirements } from '../../../util/validators';
import { OutlinedTextField } from 'react-native-material-textfield';
import {
BIOMETRY_CHOICE,
Expand All @@ -41,6 +42,10 @@ import {
METRICS_OPT_IN,
TRUE
} from '../../../constants/storage';
import { ethers } from 'ethers';
import Logger from '../../../util/Logger';

const { isValidMnemonic } = ethers.utils;

const styles = StyleSheet.create({
mainWrapper: {
Expand Down Expand Up @@ -232,16 +237,20 @@ class ImportFromSeed extends PureComponent {
}

onPressImport = async () => {
if (this.state.loading) return;
const { loading, seed, password, confirmPassword } = this.state;

if (loading) return;
let error = null;
if (this.state.password.length < 8) {
if (password.length < 8) {
error = strings('import_from_seed.password_length_error');
} else if (this.state.password !== this.state.confirmPassword) {
} else if (password !== confirmPassword) {
error = strings('import_from_seed.password_dont_match');
}

if (this.state.seed.split(' ').length !== 12) {
error = strings('import_from_seed.seed_word_count_error');
if (failedSeedPhraseRequirements(seed)) {
error = strings('import_from_seed.seed_phrase_requirements');
} else if (!isValidMnemonic(seed)) {
error = strings('import_from_seed.invalid_seed_phrase');
}

if (error) {
Expand Down Expand Up @@ -314,6 +323,7 @@ class ImportFromSeed extends PureComponent {
this.setState({ loading: false });
} else {
this.setState({ loading: false, error: error.toString() });
Logger.log('Error with seed phrase import', error);
}
}
}
Expand Down Expand Up @@ -427,6 +437,9 @@ class ImportFromSeed extends PureComponent {
);
}
this.toggleHideSeedPhraseInput();
},
onScanError: error => {
this.toggleHideSeedPhraseInput();
}
});
};
Expand Down Expand Up @@ -584,7 +597,11 @@ class ImportFromSeed extends PureComponent {
onPress={this.onPressImport}
testID={'submit'}
disabled={
!(password !== '' && password === confirmPassword && seed.split(' ').length === 12)
!(
password !== '' &&
password === confirmPassword &&
!failedSeedPhraseRequirements(seed)
)
}
>
{loading ? (
Expand Down
5 changes: 5 additions & 0 deletions app/util/validators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// eslint-disable-next-line import/prefer-default-export
export const failedSeedPhraseRequirements = seed => {
const wordCount = seed.split(/\s/u).length;
return wordCount % 3 !== 0 || wordCount > 24 || wordCount < 12;
};
24 changes: 24 additions & 0 deletions app/util/validators.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { failedSeedPhraseRequirements } from './validators';

const VALID_24 =
'verb middle giant soon wage common wide tool gentle garlic issue nut retreat until album recall expire bronze bundle live accident expect dry cook';
const VALID_12 = VALID_24.split(' ')
.splice(0, 12)
.join(' ');

describe('failedSeedPhraseRequirements', () => {
it('Should pass for 12 word mnemonic', () => {
expect(failedSeedPhraseRequirements(VALID_12)).toEqual(false);
});
it('Should pass for 24 word mnemonic', () => {
expect(failedSeedPhraseRequirements(VALID_24)).toEqual(false);
});
it('Should fail for 12 + 1 word mnemonic', () => {
const plus_one = VALID_12 + ' lol';
expect(failedSeedPhraseRequirements(plus_one)).toEqual(true);
});
it('Should fail for 24 + 1 word mnemonic', () => {
const plus_one = VALID_24 + ' lol';
expect(failedSeedPhraseRequirements(plus_one)).toEqual(true);
});
});
3 changes: 2 additions & 1 deletion locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@
"cancel_button": "Cancel",
"password_length_error": "The password needs to be at least 8 characters long",
"password_dont_match": "Passwords don't match",
"seed_word_count_error": "The seed needs to be 12 words",
"seed_phrase_requirements": "Seed phrases contain 12, 15, 18, 21, or 24 words",
"invalid_seed_phrase": "Invalid seed phrase",
"error": "Error",
"invalid_qr_code_title": "Invalid QR Code",
"invalid_qr_code_message": "This QR code doesn't represent a valid seed phrase"
Expand Down
3 changes: 2 additions & 1 deletion locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@
"cancel_button": "Cancelar",
"password_length_error": "La contraseña debe contener al menos 8 caracteres",
"password_dont_match": "Las contraseñas no coinciden",
"seed_word_count_error": "La frase debe contener 12 palabras",
"seed_phrase_requirements": "las frases semilla tienen doce (12) palabras de largo",
"invalid_seed_phrase": "Frase semilla no válida.",
"error": "Error",
"invalid_qr_code_title": "Código QR Inválido",
"invalid_qr_code_message": "Este código QR no representa una frase semilla válida"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"eth-url-parser": "1.0.2",
"ethereumjs-abi": "0.6.6",
"ethereumjs-util": "6.1.0",
"ethers": "4.0.27",
"ethers": "^5.0.14",
"ethjs-contract": "0.2.3",
"ethjs-ens": "2.0.1",
"ethjs-query": "0.3.8",
Expand Down
Loading

0 comments on commit 82f8f77

Please sign in to comment.