@@ -1,13 +1,14 @@
1−import Maybe from 'folktale/maybe'
1+import { Just, Nothing } from 'folktale/maybe'
2+import { Ok, Error } from 'folktale/result'
2import React from 'react'
3import React from 'react'
3import * as keythereum from 'keythereum'
4import * as keythereum from 'keythereum'
4−import { Button } from '../components/Base'
5+import { Button, UploadButton } from '../components/Base'
5import { Input, InnerLabel, InputCaption } from '../components/Base'
6import { Input, InnerLabel, InputCaption } from '../components/Base'
6import { Row, Col, H1, Form } from '../components/Base'
7import { Row, Col, H1, Form } from '../components/Base'
9+import { BRIDGE_ERROR } from '../lib/error'
8import { ROUTE_NAMES } from '../lib/router'
10import { ROUTE_NAMES } from '../lib/router'
9import { EthereumWallet } from '../lib/wallet'
11import { EthereumWallet } from '../lib/wallet'
10−import UploadButton from '../components/UploadButton'
12class Keystore extends React.Component {
13class Keystore extends React.Component {
@@ -15,19 +16,15 @@ class Keystore extends React.Component {
15 super(props)
16 super(props)
17 this.state = {
18 this.state = {
18− keystore: '',
19+ keystore: Nothing(), // Maybe<Result<String>>
19 password: ''
20 password: ''
22− this.handleKeystoreInput = this.handleKeystoreInput.bind(this)
23+ this.handleKeystoreUpload = this.handleKeystoreUpload.bind(this)
23 this.handlePasswordInput = this.handlePasswordInput.bind(this)
24 this.handlePasswordInput = this.handlePasswordInput.bind(this)
24 this.constructWallet = this.constructWallet.bind(this)
25 this.constructWallet = this.constructWallet.bind(this)
27− handleKeystoreInput(keystore) {
28− this.setState({ keystore })
31 handlePasswordInput(password) {
28 handlePasswordInput(password) {
32 this.setState({ password })
29 this.setState({ password })
@@ -37,12 +34,29 @@ class Keystore extends React.Component {
37 const { keystore, password } = this.state
34 const { keystore, password } = this.state
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 }
40− const json = JSON.parse(keystore)
46+ const json = JSON.parse(text)
41 const privateKey = keythereum.recover(password, json)
47 const privateKey = keythereum.recover(password, json)
42 const wallet = new EthereumWallet(privateKey)
49 const wallet = new EthereumWallet(privateKey)
43− setWallet(Maybe.Just(wallet))
50+ setWallet(Just(wallet))
44 } catch (err) {
52 } catch (err) {
45− setWallet(Maybe.Nothing())
53+
54+ const message = 'There was a problem decrypting your Keystore file'
56+ keystore: Just(Error(message))
@@ -50,50 +64,47 @@ class Keystore extends React.Component {
50 const file = event.files.item(0)
64 const file = event.files.item(0)
51 const reader = new FileReader()
65 const reader = new FileReader()
53− reader.readAsText(file)
67+ reader.onload = (e) => {
68+ const keystore = e.target.result
69+ this.setState({ keystore: Just(Ok(keystore)) })
55− console.log(reader.readyState)
72+ const failure = _ => {
73+ const message = 'There was a problem uploading your Keystore file'
74+ this.setState({ keystore: Just(Error(message)) })
57− // const loop = arg =>
77+ reader.onerror = failure
58− // arg.readyState === 2
78+ reader.onabort = failure
62− // const keystore = loop(reader)
80+ reader.readAsText(file)
63− // this.setState({ keystore })
66 render() {
83 render() {
67 const { pushRoute, popRoute, wallet } = this.props
84 const { pushRoute, popRoute, wallet } = this.props
68 const { keystore, password } = this.state
85 const { keystore, password } = this.state
70− const keystoreInput =
87+ const uploadButtonClass = keystore.matchWith({
71− <Input
88+ Nothing: _ => 'btn-primary',
72− className='pt-8 mt-8'
89+ Just: ks => ks.value.matchWith({
73− prop-size='md'
90+ Ok: _ => 'btn-success',
74− prop-format='innerLabel'
91+ Error: _ => 'shape-orange'
76− name='keystore'
93+ })
77− onChange={ this.handleKeystoreInput }
81− <InnerLabel>{'Keystore File'}</InnerLabel>
86 <Col className={'measure-md'}>
97 <Col className={'measure-md'}>
87− <H1 className={'mb-4'}>{ 'Enter Your Keystore File' }</H1>
98+ <H1 className={'mb-4'}>{ 'Upload Your Keystore File' }</H1>
89 <InputCaption>
100 <InputCaption>
90− { `Please paste in your Ethereum keystore file. If your keystore
101+ { `Please upload your Ethereum keystore file. If your keystore
91 file is encrypted with a password, you'll also need to enter
102 file is encrypted with a password, you'll also need to enter
92 that below.` }
103 that below.` }
93 </InputCaption>
104 </InputCaption>
95 <UploadButton
106 <UploadButton
96− className={ `btn btn-primary table mt-4` }
107+ className={ `btn ${uploadButtonClass} mt-10` }
97 onChange={ this.handleKeystoreUpload }
108 onChange={ this.handleKeystoreUpload }
99 { 'Upload Keystore file' }
110 { 'Upload Keystore file' }
@@ -115,7 +126,7 @@ class Keystore extends React.Component {
116 className={'mt-10'}
127 className={'mt-10'}
117 prop-size={ 'wide lg' }
128 prop-size={ 'wide lg' }
118− disabled={ keystore === '' }
129+ disabled={ Nothing.hasInstance(keystore) }
119 onClick={ this.constructWallet }
130 onClick={ this.constructWallet }
121 { 'Decrypt' }
132 { 'Decrypt' }
@@ -124,7 +135,7 @@ class Keystore extends React.Component {
125 className={'mt-10'}
136 className={'mt-10'}
126 prop-size={ 'wide lg' }
137 prop-size={ 'wide lg' }
127− disabled={ Maybe.Nothing.hasInstance(wallet) }
138+ disabled={ Nothing.hasInstance(wallet) }
128 onClick={ () => {
139 onClick={ () => {
129 popRoute()
140 popRoute()
130 pushRoute(ROUTE_NAMES.SHIPS)
141 pushRoute(ROUTE_NAMES.SHIPS)