on master help sign in
Upload Keystore file instead of pasting it in.
a9dc051Jared Tobin
src/lib/error.js+1
@@ -4,6 +4,7 @@ const BRIDGE_ERROR = {
4 MISSING_WALLET: new Error('no wallet found'),
4 MISSING_WALLET: new Error('no wallet found'),
5 MISSING_TXN: new Error('no transaction found'),
5 MISSING_TXN: new Error('no transaction found'),
6 MISSING_CONTRACTS: new Error('no contracts found'),
6 MISSING_CONTRACTS: new Error('no contracts found'),
7+ MISSING_KEYSTORE: new Error('no keystore text found'),
7 MISSING_MNEMONIC: new Error('no authentication mnemonic found'),
8 MISSING_MNEMONIC: new Error('no authentication mnemonic found'),
8 MISSING_URBIT_WALLET: new Error('no urbit wallet found'),
9 MISSING_URBIT_WALLET: new Error('no urbit wallet found'),
9 MISSING_POINT: new Error('no point found'),
10 MISSING_POINT: new Error('no point found'),
src/views/Keystore.js+49−38
@@ -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'
7
8
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'
11
12
12class Keystore extends React.Component {
13class Keystore extends React.Component {
13
14
@@ -15,19 +16,15 @@ class Keystore extends React.Component {
15 super(props)
16 super(props)
16
17
17 this.state = {
18 this.state = {
18− keystore: '',
19+ keystore: Nothing(), // Maybe<Result<String>>
19 password: ''
20 password: ''
20 }
21 }
21
22
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)
25 }
26 }
26
27
27− handleKeystoreInput(keystore) {
28− this.setState({ keystore })
29− }
30−
31 handlePasswordInput(password) {
28 handlePasswordInput(password) {
32 this.setState({ password })
29 this.setState({ password })
33 }
30 }
@@ -37,12 +34,29 @@ class Keystore extends React.Component {
37 const { keystore, password } = this.state
34 const { keystore, password } = this.state
38
35
39 try {
36 try {
37+
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+ })
45+
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)
48+
42 const wallet = new EthereumWallet(privateKey)
49 const wallet = new EthereumWallet(privateKey)
43− setWallet(Maybe.Just(wallet))
50+ setWallet(Just(wallet))
51+
44 } catch (err) {
52 } catch (err) {
45− setWallet(Maybe.Nothing())
53+
54+ const message = 'There was a problem decrypting your Keystore file'
55+ this.setState({
56+ keystore: Just(Error(message))
57+ })
58+ setWallet(Nothing())
59+
46 }
60 }
47 }
61 }
48
62
@@ -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()
52
66
53− reader.readAsText(file)
67+ reader.onload = (e) => {
68+ const keystore = e.target.result
69+ this.setState({ keystore: Just(Ok(keystore)) })
70+ }
54
71
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)) })
75+ }
56
76
57− // const loop = arg =>
77+ reader.onerror = failure
58− // arg.readyState === 2
78+ reader.onabort = failure
59− // ? arg.result
60− // : loop(arg)
61
79
62− // const keystore = loop(reader)
80+ reader.readAsText(file)
63− // this.setState({ keystore })
64 }
81 }
65
82
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
69
86
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'
75− type='text'
92+ })
76− name='keystore'
93+ })
77− onChange={ this.handleKeystoreInput }
78− value={ keystore }
79− autocomplete='off'
80− autoFocus>
81− <InnerLabel>{'Keystore File'}</InnerLabel>
82− </Input>
83
94
84 return (
95 return (
85 <Row>
96 <Row>
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>
88 <Form>
99 <Form>
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>
94
105
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 }
98 >
109 >
99 { 'Upload Keystore file' }
110 { 'Upload Keystore file' }
@@ -115,7 +126,7 @@ class Keystore extends React.Component {
115 <Button
126 <Button
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 }
120 >
131 >
121 { 'Decrypt' }
132 { 'Decrypt' }
@@ -124,7 +135,7 @@ class Keystore extends React.Component {
124 <Button
135 <Button
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)