Commit 1f814a6d authored by fro's avatar fro
Browse files

Seed phrase validation on RecoveryScreen impl

parent 8c853815
......@@ -21,14 +21,9 @@ import PropTypes from 'prop-types';
import { Animated, Text, View, StyleSheet } from 'react-native';
import TouchableItem from './TouchableItem';
import TextInput from './TextInput';
import WORDS from '../../res/wordlist.json';
import { WORDS, WORDS_INDEX } from '../util/account';
import colors from '../colors';
const WORDS_INDEX = WORDS.reduce(
(res, w) => Object.assign(res, { [w]: 1 }),
{}
);
export default class AccountSeed extends Component {
state = {
cursorPosition: 0,
......@@ -144,7 +139,9 @@ export default class AccountSeed extends Component {
}
renderSuggestions() {
const { value } = this.props;
const { value, valid } = this.props;
const invalidStyles = !valid ? styles.invalidInput : {};
const words = value.length ? value.split(' ') : [];
const wordPosition = this.getWordPosition();
let searchInput = this.getSearchInput();
......@@ -156,11 +153,10 @@ export default class AccountSeed extends Component {
<Animated.View
style={[styles.suggestions, { height: this.state.suggestionsHeight }]}
>
{/* <View style={styles.suggestion}>suggestion</View> */}
{suggestions.map((suggestion, i) => {
const sepStyle =
!this.state.animation && i !== suggestions.length - 1
? { borderRightWidth: 1, borderColor: colors.card_bg }
? { borderRightWidth: 0.3, borderColor: colors.card_bg_text_sec }
: {};
return (
<TouchableItem
......@@ -181,10 +177,12 @@ export default class AccountSeed extends Component {
render() {
const { keyboard } = this.state;
const { valid } = this.props;
const invalidStyles = !valid ? styles.invalidInput : {};
return (
<View>
<TextInput
style={styles.input}
style={[styles.input, invalidStyles]}
multiline
onBlur={this.keyboardDidHide}
onSelectionChange={this.handleCursorPosition}
......@@ -207,10 +205,16 @@ const styles = StyleSheet.create({
input: {
height: 120,
lineHeight: 26,
fontSize: 20
fontSize: 20,
backgroundColor: '#e4fee4'
},
invalidInput: {
backgroundColor: '#fee3e3'
},
suggestions: {
backgroundColor: '#E5E5E5',
backgroundColor: colors.card_bg,
borderTopWidth: 0.3,
borderColor: colors.card_bg_text_sec,
paddingHorizontal: 5,
height: 35,
flexDirection: 'row',
......
......@@ -48,6 +48,7 @@ import {
NETWORK_COLOR,
DEFAULT_NETWORK_COLOR
} from '../constants';
import { validateSeed } from '../util/account';
import colors from '../colors';
export default class AccountRecover extends React.Component {
......@@ -128,6 +129,7 @@ class AccountRecoverView extends React.Component {
onFocus={e => {
this.scroll.props.scrollToFocusedInput(findNodeHandle(e.target));
}}
valid={validateSeed(selected.seed).valid}
onChangeText={seed => {
accounts.updateNew({ seed });
}}
......@@ -143,6 +145,32 @@ class AccountRecoverView extends React.Component {
buttonStyles={{ marginBottom: 40 }}
title="Next Step"
onPress={() => {
const validation = validateSeed(selected.seed);
if (!validation.valid) {
Alert.alert(
'Warning: seed phrase is not secure',
`${validation.reason}`,
[
{
text: 'I understand risks',
style: 'default',
onPress: () => {
this.props.navigation.navigate('AccountPin', {
isWelcome: this.props.navigation.getParam(
'isWelcome'
),
isNew: true
});
}
},
{
text: 'Back',
style: 'cancel'
}
]
);
return;
}
this.props.navigation.navigate('AccountPin', {
isWelcome: this.props.navigation.getParam('isWelcome'),
isNew: true
......
import { NETWORK_TYPE, NETWORK_ID } from '../constants';
import WORDS from '../../res/wordlist.json';
export { WORDS };
export const WORDS_INDEX = WORDS.reduce(
(res, w) => Object.assign(res, { [w]: 1 }),
{}
);
export function accountId({
address,
......@@ -26,3 +33,45 @@ export function empty(account = {}) {
...account
};
}
export function validateSeed(seed) {
if (seed.length === 0) {
return {
valid: false,
reason: `You're trying to recover from an empty seed phrase`
};
}
const words = seed.split(' ');
const set = new Set();
for (let word of words) {
if (typeof WORDS_INDEX[word] === 'undefined') {
if (set.has(word)) {
return {
valid: false,
reason: `Duplicated word "${word}" found. Words in seed phrase must be unique.`
};
}
if (word === '') {
return {
valid: false,
reason: `Extra whitespace found`
};
}
return {
valid: false,
reason: `Word ${word} is not from the word list`
}
}
set.add(word);
}
if (set.size < 11) {
return {
valid: false,
reason: `Add ${11 - set.size} more unique word(s) to compose a secure seed phrase`
}
}
return {
valid: true,
reason: null
};
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment