on f7eb6eb help sign in
bridge/src/views/Keystore.js
157 lines 4.3 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/Base'
6import { Input, InnerLabel, InputCaption } from '../components/Base'
7import { Row, Col, H1, Form } from '../components/Base'
9import { BRIDGE_ERROR } from '../lib/error'
10import { ROUTE_NAMES } from '../lib/router'
11import { EthereumWallet } from '../lib/wallet'
13class Keystore extends React.Component {
15 constructor(props) {
16 super(props)
18 this.state = {
19 keystore: Nothing(), // Maybe<Result<String, String>>
20 password: ''
21 }
23 this.handleKeystoreUpload = this.handleKeystoreUpload.bind(this)
24 this.handlePasswordInput = this.handlePasswordInput.bind(this)
25 this.constructWallet = this.constructWallet.bind(this)
26 }
28 handlePasswordInput(password) {
29 this.setState({ password })
30 }
32 constructWallet() {
33 const { setWallet } = this.props
34 const { keystore, password } = this.state
36 try {
38 const text = keystore.matchWith({
39 Nothing: _ => { throw BRIDGE_ERROR.MISSING_KEYSTORE },
40 Just: ks => ks.value.matchWith({
41 Ok: result => result.value,
42 Error: _ => { throw BRIDGE_ERROR.MISSING_KEYSTORE }
43 })
44 })
46 const json = JSON.parse(text)
47 const privateKey = keythereum.recover(password, json)
49 const wallet = new EthereumWallet(privateKey)
50 setWallet(Just(wallet))
52 } catch (err) {
54 const message = 'There was a problem decrypting your Keystore file'
55 this.setState({
56 keystore: Just(Error(message))
57 })
58 setWallet(Nothing())
60 }
61 }
63 handleKeystoreUpload = (event) => {
64 const file = event.files.item(0)
65 const reader = new FileReader()
67 reader.onload = (e) => {
68 const keystore = e.target.result
69 this.setState({ keystore: Just(Ok(keystore)) })
70 }
72 const failure = _ => {
73 const message = 'There was a problem uploading your Keystore file'
74 this.setState({ keystore: Just(Error(message)) })
75 }
77 reader.onerror = failure
78 reader.onabort = failure
80 reader.readAsText(file)
81 }
83 render() {
84 const { pushRoute, popRoute, wallet } = this.props
85 const { keystore, password } = this.state
87 const uploadButtonClass = keystore.matchWith({
88 Nothing: _ => 'bg-blue white',
89 Just: ks => ks.value.matchWith({
90 Ok: _ => 'bg-green white',
91 Error: _ => 'bg-yellow black'
92 })
93 })
95 return (
96 <Row>
97 <Col className={'measure-md'}>
98 <H1 className={'mb-4'}>{ 'Upload Your Keystore File' }</H1>
99 <Form>
100 <InputCaption>
101 { `Please upload your Ethereum keystore file. If your keystore
102 file is encrypted with a password, you'll also need to enter
103 that below.` }
104 </InputCaption>
106 <UploadButton
107 className={ `btn ${uploadButtonClass} mt-10` }
108 onChange={ this.handleKeystoreUpload }
109 >
110 <div className={'flex-center-all fs-4 h-11 pointer'}>{ 'Upload Keystore file' }</div>
111 </UploadButton>
113 <Input
114 className='pt-8 mt-8'
115 prop-size='md'
116 prop-format='innerLabel'
117 type='password'
118 name='password'
119 onChange={ this.handlePasswordInput }
120 value={ password }
121 autocomplete='off'
122 autoFocus>
123 <InnerLabel>{'Password'}</InnerLabel>
124 </Input>
126 <Button
127 className={'mt-10'}
128 prop-size={ 'wide lg' }
129 disabled={ Nothing.hasInstance(keystore) }
130 onClick={ this.constructWallet }
131 >
132 { 'Decrypt' }
133 </Button>
135 <Button
136 className={'mt-10'}
137 prop-size={ 'wide lg' }
138 disabled={ Nothing.hasInstance(wallet) }
139 onClick={ () => {
140 popRoute()
141 pushRoute(ROUTE_NAMES.SHIPS)
142 }
143 }
144 >
145 { 'Continue →' }
146 </Button>
148 </Form>
149 </Col>
150 </Row>
153 )
154 }
157export default Keystore