on aee35bb help sign in
bridge/src/views/Keystore.js
166 lines 4.6 kB history raw
1import { Just, Nothing } from 'folktale/maybe';
2import { Ok, Error } from 'folktale/result';
3import React from 'react';
4import * as keythereum from 'keythereum';
5import { Button, UploadButton } from '../components/old/Base';
6import { Input, InnerLabel, InputCaption } from '../components/old/Base';
7import { H1, H3, Warning } from '../components/old/Base';
9import { BRIDGE_ERROR } from '../lib/error';
10import { ROUTE_NAMES } from '../lib/routeNames';
11import { withHistory } from '../store/history';
12import { EthereumWallet } from '../lib/wallet';
13import { compose } from '../lib/lib';
14import { withWallet } from '../store/wallet';
15import View from 'components/View';
17class Keystore extends React.Component {
18 constructor(props) {
19 super(props);
21 this.state = {
22 keystore: Nothing(), // Maybe<Result<String, String>>
23 password: '',
24 decryptionProblem: false,
25 };
27 this.handleKeystoreUpload = this.handleKeystoreUpload.bind(this);
28 this.handlePasswordInput = this.handlePasswordInput.bind(this);
29 this.constructWallet = this.constructWallet.bind(this);
30 }
32 handlePasswordInput(password) {
33 this.setState({ password });
34 }
36 constructWallet() {
37 const { setWallet } = this.props;
38 const { keystore, password } = this.state;
40 try {
41 const text = keystore.matchWith({
42 Nothing: _ => {
43 throw BRIDGE_ERROR.MISSING_KEYSTORE;
44 },
45 Just: ks =>
46 ks.value.matchWith({
47 Ok: result => result.value,
48 Error: _ => {
49 throw BRIDGE_ERROR.MISSING_KEYSTORE;
50 },
51 }),
52 });
54 const json = JSON.parse(text);
55 const privateKey = keythereum.recover(password, json);
57 const wallet = new EthereumWallet(privateKey);
58 this.setState({ decryptionProblem: false });
59 setWallet(Just(wallet));
60 } catch (err) {
61 this.setState({ decryptionProblem: true });
62 setWallet(Nothing());
63 }
64 }
66 handleKeystoreUpload = event => {
67 const file = event.files.item(0);
68 const reader = new FileReader();
70 reader.onload = e => {
71 const keystore = e.target.result;
72 this.setState({ keystore: Just(Ok(keystore)) });
73 };
75 const failure = _ => {
76 const message = 'There was a problem uploading your Keystore file';
77 this.setState({ keystore: Just(Error(message)) });
78 };
80 reader.onerror = failure;
81 reader.onabort = failure;
83 reader.readAsText(file);
84 };
86 render() {
87 const { history, wallet } = this.props;
88 const { keystore, password, decryptionProblem } = this.state;
90 const uploadButtonClass = keystore.matchWith({
91 Nothing: _ => 'bg-blue white',
92 Just: ks =>
93 ks.value.matchWith({
94 Ok: _ => 'bg-green white',
95 Error: _ => 'bg-yellow black',
96 }),
97 });
99 const decryptMessage =
100 decryptionProblem === false ? (
101 <div />
102 ) : (
103 <Warning className={'mt-8'}>
104 <H3 style={{ marginTop: 0, paddingTop: 0 }}>
105 {"Couldn't decrypt wallet."}
106 </H3>
107 {'You may have entered an incorrect password.'}
108 </Warning>
109 );
111 return (
112 <View>
113 <H1 className={'mb-4'}>{'Upload Your Keystore File'}</H1>
114 <InputCaption>
115 {`Please upload your Ethereum keystore file. If your keystore
116 file is encrypted with a password, you'll also need to enter
117 that below.`}
118 </InputCaption>
120 <UploadButton
121 className={`btn ${uploadButtonClass} mt-10`}
122 onChange={this.handleKeystoreUpload}>
123 <div className={'flex-center-all fs-4 h-11 pointer'}>
124 {'Upload Keystore file'}
125 </div>
126 </UploadButton>
128 <Input
129 className="pt-8 mt-8"
130 prop-size="md"
131 prop-format="innerLabel"
132 type="password"
133 name="password"
134 onChange={this.handlePasswordInput}
135 value={password}
136 autocomplete="off"
137 autoFocus>
138 <InnerLabel>{'Password'}</InnerLabel>
139 </Input>
141 <Button
142 className={` mt-10`}
143 prop-size={'wide lg'}
144 disabled={Nothing.hasInstance(keystore)}
145 onClick={this.constructWallet}>
146 {'Decrypt'}
147 </Button>
149 {decryptMessage}
151 <Button
152 className={'mt-10'}
153 prop-size={'wide lg'}
154 disabled={Nothing.hasInstance(wallet)}
155 onClick={() => history.popAndPush(ROUTE_NAMES.POINTS)}>
156 {'Continue →'}
157 </Button>
158 </View>
159 );
160 }
163export default compose(
164 withHistory,
165 withWallet
166)(Keystore);