on master help sign in
Make /views/Login/Keystore functional/stateless
70873a2Fang
src/views/Login/Keystore.js+88−112
@@ -1,66 +1,60 @@
1import { Just, Nothing } from 'folktale/maybe';
1import { Just, Nothing } from 'folktale/maybe';
2import { Ok, Error } from 'folktale/result';
2import { Ok, Error } from 'folktale/result';
3−import React from 'react';
3+import React, { useState } from 'react';
4import * as keythereum from 'keythereum';
4import * as keythereum from 'keythereum';
5+
6+import View from '../../components/View';
7+import { PassphraseInput } from '../../components/Inputs';
8+import { ForwardButton } from '../../components/Buttons';
9+import {
10+ InputCaption,
5−import { Button, UploadButton } from '../../components/old/Base';
11+ UploadButton,
6−import { Input, InnerLabel, InputCaption } from '../../components/old/Base';
12+ H3,
13+ Warning,
7−import { Row, Col, H1, H3, Warning } from '../../components/old/Base';
14+} from '../../components/old/Base';
8
15
9import * as need from '../../lib/need';
16import * as need from '../../lib/need';
10import { EthereumWallet } from '../../lib/wallet';
17import { EthereumWallet } from '../../lib/wallet';
11−import { compose } from '../../lib/lib';
12−import { withWallet } from '../../store/wallet';
18+import { useWallet } from '../../store/wallet';
13−
14−class Keystore extends React.Component {
15− constructor(props) {
16− super(props);
17−
18− this.state = {
19− keystore: Nothing(), // Maybe<Result<String, String>>
20− password: '',
21− decryptionProblem: false,
22− };
23
19
24− this.handleKeystoreUpload = this.handleKeystoreUpload.bind(this);
20+export default function Keystore({ loginCompleted }) {
25− this.handlePasswordInput = this.handlePasswordInput.bind(this);
21+ // globals
26− this.constructWallet = this.constructWallet.bind(this);
22+ const { wallet, setWallet } = useWallet();
27− }
28
23
29− handlePasswordInput(password) {
24+ // inputs
30− this.setState({ password });
25+ // keystore: Maybe<Result<String, String>>
31− }
26+ const [keystore, setKeystore] = useState(Nothing());
32−
27+ const [password, setPassword] = useState('');
33− constructWallet() {
28+ const [decryptionProblem, setDecryptionProblem] = useState(false);
34− const { setWallet } = this.props;
35− const { password } = this.state;
36
29
30+ const constructWallet = () => {
37 try {
31 try {
38− const text = need.keystore(this.state);
32+ const text = need.keystore(keystore);
39
33
40 const json = JSON.parse(text);
34 const json = JSON.parse(text);
41 const privateKey = keythereum.recover(password, json);
35 const privateKey = keythereum.recover(password, json);
42
36
43 const wallet = new EthereumWallet(privateKey);
37 const wallet = new EthereumWallet(privateKey);
44− this.setState({ decryptionProblem: false });
38+ setDecryptionProblem(false);
45 setWallet(Just(wallet));
39 setWallet(Just(wallet));
46 } catch (err) {
40 } catch (err) {
47− this.setState({ decryptionProblem: true });
41+ setDecryptionProblem(true);
48 setWallet(Nothing());
42 setWallet(Nothing());
49 }
43 }
50− }
44+ };
51
45
52− handleKeystoreUpload = event => {
46+ const handleKeystoreUpload = event => {
53 const file = event.files.item(0);
47 const file = event.files.item(0);
54 const reader = new FileReader();
48 const reader = new FileReader();
55
49
56 reader.onload = e => {
50 reader.onload = e => {
57 const keystore = e.target.result;
51 const keystore = e.target.result;
58− this.setState({ keystore: Just(Ok(keystore)) });
52+ setKeystore(Just(Ok(keystore)));
59 };
53 };
60
54
61 const failure = _ => {
55 const failure = _ => {
62 const message = 'There was a problem uploading your Keystore file';
56 const message = 'There was a problem uploading your Keystore file';
63− this.setState({ keystore: Just(Error(message)) });
57+ setKeystore(Just(Error(message)));
64 };
58 };
65
59
66 reader.onerror = failure;
60 reader.onerror = failure;
@@ -69,83 +63,65 @@ class Keystore extends React.Component {
69 reader.readAsText(file);
63 reader.readAsText(file);
70 };
64 };
71
65
72− render() {
73− const { wallet } = this.props;
74− const { keystore, password, decryptionProblem } = this.state;
75−
76− const uploadButtonClass = keystore.matchWith({
66+ const uploadButtonClass = keystore.matchWith({
77− Nothing: _ => 'bg-blue white',
67+ Nothing: _ => 'bg-blue white',
78− Just: ks =>
68+ Just: ks =>
79− ks.value.matchWith({
69+ ks.value.matchWith({
80− Ok: _ => 'bg-green white',
70+ Ok: _ => 'bg-green white',
81− Error: _ => 'bg-yellow black',
71+ Error: _ => 'bg-yellow black',
82− }),
72+ }),
83− });
73+ });
84−
74+
85− const decryptMessage =
75+ const decryptMessage =
86− decryptionProblem === false ? (
76+ decryptionProblem === false ? (
87− <div />
77+ <div />
88− ) : (
78+ ) : (
89− <Warning className={'mt-8'}>
79+ <Warning className={'mt-8'}>
90− <H3 style={{ marginTop: 0, paddingTop: 0 }}>
80+ <H3 style={{ marginTop: 0, paddingTop: 0 }}>
91− {"Couldn't decrypt wallet."}
81+ {"Couldn't decrypt wallet."}
92− </H3>
82+ </H3>
93− {'You may have entered an incorrect password.'}
83+ {'You may have entered an incorrect password.'}
94− </Warning>
84+ </Warning>
95− );
96−
97− return (
98− <Row>
99− <Col className={'measure-md'}>
100− <H1 className={'mb-4'}>{'Upload Your Keystore File'}</H1>
101− <InputCaption>
102− {`Please upload your Ethereum keystore file. If your keystore
103− file is encrypted with a password, you'll also need to enter
104− that below.`}
105− </InputCaption>
106−
107− <UploadButton
108− className={`btn ${uploadButtonClass} mt-10`}
109− onChange={this.handleKeystoreUpload}>
110− <div className={'flex-center-all fs-4 h-11 pointer'}>
111− {'Upload Keystore file'}
112− </div>
113− </UploadButton>
114−
115− <Input
116− className="pt-8 mt-8"
117− prop-size="md"
118− prop-format="innerLabel"
119− type="password"
120− name="password"
121− onChange={this.handlePasswordInput}
122− value={password}
123− autocomplete="off"
124− autoFocus>
125− <InnerLabel>{'Password'}</InnerLabel>
126− </Input>
127−
128− <Button
129− className={` mt-10`}
130− prop-size={'wide lg'}
131− disabled={Nothing.hasInstance(keystore)}
132− onClick={this.constructWallet}>
133− {'Decrypt'}
134− </Button>
135−
136− {decryptMessage}
137−
138− <Button
139− className={'mt-10'}
140− prop-size={'wide lg'}
141− disabled={Nothing.hasInstance(wallet)}
142− onClick={this.props.loginCompleted}>
143− {'Continue →'}
144− </Button>
145− </Col>
146− </Row>
147 );
85 );
148− }
149−}
150
86
151−export default compose(withWallet)(Keystore);
87+ return (
88+ <View>
89+ <InputCaption>
90+ {`Please upload your Ethereum keystore file. If your keystore
91+ file is encrypted with a password, you'll also need to enter
92+ that below.`}
93+ </InputCaption>
94+
95+ <UploadButton
96+ className={`${uploadButtonClass} mt3`}
97+ onChange={handleKeystoreUpload}>
98+ <div className={'flex-center-all fs-4 h-11 pointer'}>
99+ {'Upload Keystore file'}
100+ </div>
101+ </UploadButton>
102+
103+ <PassphraseInput
104+ name="password"
105+ label="Keystore password"
106+ initialValue={password}
107+ onValue={setPassword}
108+ autoFocus></PassphraseInput>
109+
110+ <ForwardButton
111+ className={`mt3`}
112+ disabled={Nothing.hasInstance(keystore)}
113+ onClick={constructWallet}>
114+ Decrypt
115+ </ForwardButton>
116+
117+ {decryptMessage}
118+
119+ <ForwardButton
120+ className={'mt3'}
121+ disabled={Nothing.hasInstance(wallet)}
122+ onClick={loginCompleted}>
123+ Continue
124+ </ForwardButton>
125+ </View>
126+ );
127+}