Skip to content

Commit 6911b90

Browse files
committed
A new component to revoer BIP39 phrases is added
1 parent ebe9f86 commit 6911b90

File tree

3 files changed

+163
-74
lines changed

3 files changed

+163
-74
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// @flow
2+
import React, { useState } from 'react';
3+
import Form from 'react-bootstrap/Form';
4+
import Button from 'react-bootstrap/Button';
5+
import Container from 'react-bootstrap/Container';
6+
import Row from 'react-bootstrap/Row';
7+
import typeof { setAccountFromMnemonic as SetAccountFromMnemonic } from '../actions/account';
8+
import { isValidMnemonic } from '../utils/mnemonic';
9+
10+
type Props = {
11+
setAccountFromMnemonic: SetAccountFromMnemonic
12+
};
13+
14+
// FIXME: this has no error handling, neither while parsing the address
15+
// nor when fetching the balance.
16+
export default ({ setAccountFromMnemonic }: Props) => {
17+
const checkIsValidMnemonicPhrase = function checkIsValidMnemonicPhrase() {
18+
setIsMnemonicValid(isValidMnemonic(newMnemonicPhrase));
19+
};
20+
21+
const handleSubmitMnemonic = function handleSubmitMnemonic(event) {
22+
event.preventDefault();
23+
if (
24+
isValidMnemonic(newMnemonicPhrase) &&
25+
checkValidPassword(password, confirmPassword)
26+
) {
27+
return Promise.all([
28+
setAccountFromMnemonic(newMnemonicPhrase, newMnemonicPassword)
29+
]);
30+
}
31+
setIsMnemonicValid(false);
32+
};
33+
34+
const [isMnemonicValid, setIsMnemonicValid] = useState(true);
35+
36+
const [newMnemonicPhrase, setNewMnemonicPhrase] = useState('');
37+
38+
const [newMnemonicPassword, setNewMnemonicPassword] = useState('');
39+
40+
const checkValidPassword = function checkValidPassword(pass, confirmation) {
41+
if (!pass && !confirmation) return true;
42+
if (pass.length < 8) {
43+
setIsValidPassword(false);
44+
return false;
45+
}
46+
setIsValidPassword(true);
47+
48+
if (pass !== confirmation) {
49+
setArePasswordAndConfirmationEqual(false);
50+
return false;
51+
}
52+
setArePasswordAndConfirmationEqual(true);
53+
return true;
54+
};
55+
56+
const [
57+
arePasswordAndConfirmationEqual,
58+
setArePasswordAndConfirmationEqual
59+
] = useState(true);
60+
61+
const [password, setPassword] = useState('');
62+
const [confirmPassword, setConfirmPassword] = useState('');
63+
const [isValidPassword, setIsValidPassword] = useState(true);
64+
65+
return (
66+
<Container>
67+
<Form onSubmit={handleSubmitMnemonic} className="mt-5">
68+
<Form.Group>
69+
<Form.Label>Wallet Seed:</Form.Label>
70+
<Form.Control
71+
required
72+
type="text"
73+
id="mnemonicPhrase"
74+
name="mnemonicPhrase"
75+
placeholder="Enter your secret word phrase here to restore your vault. The phrase can have 12, 15, 18, 21 or 24 words."
76+
value={newMnemonicPhrase}
77+
isInvalid={!isMnemonicValid}
78+
onChange={event => setNewMnemonicPhrase(event.target.value)}
79+
onBlur={() => checkIsValidMnemonicPhrase()}
80+
/>
81+
<Form.Label className="text-danger" hidden={isMnemonicValid}>
82+
<code>The phrase can have 12, 15, 18, 21 or 24 valid words.</code>
83+
</Form.Label>
84+
<Form.Text>
85+
Example:
86+
<br />
87+
<code>
88+
decade panther require cruise robust mail gadget advice tonight
89+
post inner snack
90+
</code>
91+
</Form.Text>
92+
<Form.Control
93+
type="password"
94+
name="mnemonicPassword"
95+
placeholder="Secret password"
96+
value={newMnemonicPassword}
97+
onChange={event => setNewMnemonicPassword(event.target.value)}
98+
className="mt-3"
99+
/>
100+
<Form.Label>
101+
Create a password to store your settings securely in an encrypted
102+
storage
103+
</Form.Label>
104+
<Form.Control
105+
type="password"
106+
id="password"
107+
name="password"
108+
placeholder="New password (min 8 chars)"
109+
value={password}
110+
isInvalid={!isValidPassword}
111+
onChange={event => setPassword(event.target.value)}
112+
/>
113+
<Form.Label className="text-danger" hidden={isValidPassword}>
114+
<code>The password must have at least 8 chars.</code>
115+
</Form.Label>
116+
<Form.Control
117+
type="password"
118+
name="confirmPassword"
119+
id="confirmPassword"
120+
placeholder="Confirm password"
121+
value={confirmPassword}
122+
onChange={event => setConfirmPassword(event.target.value)}
123+
className="mt-3"
124+
/>
125+
<Form.Label
126+
className="text-danger"
127+
hidden={arePasswordAndConfirmationEqual}
128+
>
129+
<code>password and confirmation must be the same.</code>
130+
</Form.Label>
131+
</Form.Group>
132+
<Row className="justify-content-between">
133+
<Button variant="secondary" type="button">
134+
Go back
135+
</Button>
136+
<Button variant="primary" type="submit">
137+
Initialize wallet using mnemonic phrase
138+
</Button>
139+
</Row>
140+
</Form>
141+
</Container>
142+
);
143+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// @flow
2+
import { bindActionCreators } from 'redux';
3+
import { connect } from 'react-redux';
4+
import RestoreWalletFromMnemonic from '../components/RestoreWalletFromMnemonic';
5+
import { setAccount } from '../actions/account';
6+
7+
function mapDispatchToProps(dispatch) {
8+
return bindActionCreators({ setAccount }, dispatch);
9+
}
10+
11+
export default connect(
12+
undefined,
13+
mapDispatchToProps
14+
)(RestoreWalletFromMnemonic);

examples/wallet/app/pages/InputKeys.js

Lines changed: 6 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
// @flow
2-
import React, { useState } from 'react';
3-
import Form from 'react-bootstrap/Form';
4-
import Button from 'react-bootstrap/Button';
5-
import Container from 'react-bootstrap/Container';
2+
import React from 'react';
63
import Tabs from 'react-bootstrap/Tabs';
74
import Tab from 'react-bootstrap/Tab';
8-
import Row from 'react-bootstrap/Row';
95
import RestoreWalletFromPrivateKey from '../components/RestoreWalletFromPrivateKey';
6+
import RestoreWalletFromMnemonic from '../components/RestoreWalletFromMnemonic';
7+
108
import typeof {
119
setAccountFromMnemonic as SetAccountFromMnemonic,
1210
setAccount as SetAccount
1311
} from '../actions/account';
14-
import { isValidMnemonic } from '../utils/mnemonic';
1512

1613
type Props = {
1714
setAccountFromMnemonic: SetAccountFromMnemonic,
@@ -21,80 +18,15 @@ type Props = {
2118
// FIXME: this has no error handling, neither while parsing the address
2219
// nor when fetching the balance.
2320
export default ({ setAccountFromMnemonic, setAccount }: Props) => {
24-
const checkIsValidMnemonicPhrase = function checkIsValidMnemonicPhrase() {
25-
setIsMnemonicValid(isValidMnemonic(newMnemonicPhrase));
26-
};
27-
28-
const handleSubmitMnemonic = function handleSubmitMnemonic(event) {
29-
event.preventDefault();
30-
if (isValidMnemonic(newMnemonicPhrase)) {
31-
return Promise.all([
32-
setAccountFromMnemonic(newMnemonicPhrase, newMnemonicPassword)
33-
]);
34-
}
35-
setIsMnemonicValid(false);
36-
};
37-
38-
const [isMnemonicValid, setIsMnemonicValid] = useState(true);
39-
40-
const [newMnemonicPhrase, setNewMnemonicPhrase] = useState('');
41-
42-
const [newMnemonicPassword, setNewMnemonicPassword] = useState('');
43-
4421
return (
4522
<Tabs fill defaultActiveKey="keyString" className="justify-content-center">
4623
<Tab eventKey="keyString" title="Use key string">
4724
<RestoreWalletFromPrivateKey setAccount={setAccount} />
4825
</Tab>
4926
<Tab eventKey="mnemonic" title="Use mnemonic phrase">
50-
<Container>
51-
<Form onSubmit={handleSubmitMnemonic} className="mt-5">
52-
<Form.Group>
53-
<Form.Label>Wallet Seed:</Form.Label>
54-
<Form.Control
55-
required
56-
type="text"
57-
id="mnemonicPhrase"
58-
name="mnemonicPhrase"
59-
placeholder="Enter your secret word phrase here to restore your vault. The phrase can have 12, 15, 18, 21 or 24 words."
60-
value={newMnemonicPhrase}
61-
isInvalid={!isMnemonicValid}
62-
onChange={event => setNewMnemonicPhrase(event.target.value)}
63-
onBlur={() => checkIsValidMnemonicPhrase()}
64-
/>
65-
<Form.Label className="text-danger" hidden={isMnemonicValid}>
66-
<code>
67-
The phrase can have 12, 15, 18, 21 or 24 valid words.
68-
</code>
69-
</Form.Label>
70-
<Form.Text>
71-
Example:
72-
<br />
73-
<code>
74-
decade panther require cruise robust mail gadget advice
75-
tonight post inner snack
76-
</code>
77-
</Form.Text>
78-
<Form.Control
79-
type="password"
80-
name="mnemonicPassword"
81-
placeholder="Secret password"
82-
value={newMnemonicPassword}
83-
onChange={event => setNewMnemonicPassword(event.target.value)}
84-
className="mt-3"
85-
/>
86-
</Form.Group>
87-
<Row className="justify-content-between">
88-
{/* TODO: bind this button */}
89-
<Button variant="secondary" type="button">
90-
Go back
91-
</Button>
92-
<Button variant="primary" type="submit">
93-
Initialize wallet using mnemonic phrase
94-
</Button>
95-
</Row>
96-
</Form>
97-
</Container>
27+
<RestoreWalletFromMnemonic
28+
setAccountFromMnemonic={setAccountFromMnemonic}
29+
/>
9830
</Tab>
9931
</Tabs>
10032
);

0 commit comments

Comments
 (0)