on master help sign in
Add keystore file authentication.
529b265Jared Tobin
src/lib/router.js+6
@@ -11,6 +11,7 @@ import Mnemonic from '../views/Mnemonic'
11import Ledger from '../views/Ledger'
11import Ledger from '../views/Ledger'
12import Trezor from '../views/Trezor'
12import Trezor from '../views/Trezor'
13import PrivateKey from '../views/PrivateKey'
13import PrivateKey from '../views/PrivateKey'
14+import Keystore from '../views/Keystore'
14import ViewPoint from '../views/ViewPoint'
15import ViewPoint from '../views/ViewPoint'
15import SentTransaction from '../views/SentTransaction'
16import SentTransaction from '../views/SentTransaction'
16import SetKeys from '../views/SetKeys'
17import SetKeys from '../views/SetKeys'
@@ -42,6 +43,7 @@ const ROUTE_NAMES = {
42 LEDGER: Symbol('LEDGER'),
43 LEDGER: Symbol('LEDGER'),
43 TREZOR: Symbol('TREZOR'),
44 TREZOR: Symbol('TREZOR'),
44 PRIVATE_KEY: Symbol('PRIVATE_KEY'),
45 PRIVATE_KEY: Symbol('PRIVATE_KEY'),
46+ KEYSTORE: Symbol('KEYSTORE'),
45 VIEW_SHIP: Symbol('VIEW_SHIP'),
47 VIEW_SHIP: Symbol('VIEW_SHIP'),
46 SHIPS: Symbol('SHIPS'),
48 SHIPS: Symbol('SHIPS'),
47 SHIP: Symbol('SHIP'),
49 SHIP: Symbol('SHIP'),
@@ -71,6 +73,7 @@ const createRoutes = () => {
71 routes[ROUTE_NAMES.LEDGER] = Ledger
73 routes[ROUTE_NAMES.LEDGER] = Ledger
72 routes[ROUTE_NAMES.TREZOR] = Trezor
74 routes[ROUTE_NAMES.TREZOR] = Trezor
73 routes[ROUTE_NAMES.PRIVATE_KEY] = PrivateKey
75 routes[ROUTE_NAMES.PRIVATE_KEY] = PrivateKey
76+ routes[ROUTE_NAMES.KEYSTORE] = Keystore
74 routes[ROUTE_NAMES.SHIPS] = Points
77 routes[ROUTE_NAMES.SHIPS] = Points
75 routes[ROUTE_NAMES.SHIP] = Point
78 routes[ROUTE_NAMES.SHIP] = Point
76 routes[ROUTE_NAMES.SET_MANAGEMENT_PROXY] = SetManagementProxy
79 routes[ROUTE_NAMES.SET_MANAGEMENT_PROXY] = SetManagementProxy
@@ -124,6 +127,9 @@ const renderRoute = (props, route) => {
124 : route === ROUTE_NAMES.PRIVATE_KEY
127 : route === ROUTE_NAMES.PRIVATE_KEY
125 ? 'Private Key'
128 ? 'Private Key'
126
129
130+ : route === ROUTE_NAMES.KEYSTORE
131+ ? 'Keystore File'
132+
127 : route === ROUTE_NAMES.SHIPS
133 : route === ROUTE_NAMES.SHIPS
128 ? 'Points'
134 ? 'Points'
129
135
src/lib/wallet.js+4−1
@@ -16,7 +16,8 @@ const WALLET_NAMES = {
16 SHARDS: Symbol('SHARDS'),
16 SHARDS: Symbol('SHARDS'),
17 LEDGER: Symbol('LEDGER'),
17 LEDGER: Symbol('LEDGER'),
18 TREZOR: Symbol('TREZOR'),
18 TREZOR: Symbol('TREZOR'),
19− PRIVATE_KEY: Symbol('PRIVATE_KEY')
19+ PRIVATE_KEY: Symbol('PRIVATE_KEY'),
20+ KEYSTORE: Symbol('KEYSTORE')
20}
21}
21
22
22function EthereumWallet(privateKey) {
23function EthereumWallet(privateKey) {
@@ -39,6 +40,8 @@ const renderWalletType = (wallet) =>
39 ? 'Trezor'
40 ? 'Trezor'
40 : wallet === WALLET_NAMES.PRIVATE_KEY
41 : wallet === WALLET_NAMES.PRIVATE_KEY
41 ? 'Private Key'
42 ? 'Private Key'
43+ : wallet === WALLET_NAMES.KEYSTORE
44+ ? 'Keystore File'
42 : 'Wallet'
45 : 'Wallet'
43
46
44const addressFromSecp256k1Public = pub => {
47const addressFromSecp256k1Public = pub => {
src/views/Keystore.jsnew file+120
@@ -0,0 +1,120 @@
1+import Maybe from 'folktale/maybe'
2+import React from 'react'
3+import * as keythereum from 'keythereum'
4+import { Button } from '../components/Base'
5+import { Input, InnerLabel, InputCaption } from '../components/Base'
6+import { Row, Col, H1, Form } from '../components/Base'
7+
8+import { ROUTE_NAMES } from '../lib/router'
9+import { EthereumWallet } from '../lib/wallet'
10+
11+class Keystore extends React.Component {
12+
13+ constructor(props) {
14+ super(props)
15+
16+ this.state = {
17+ keystore: '',
18+ password: ''
19+ }
20+
21+ this.handleKeystoreInput = this.handleKeystoreInput.bind(this)
22+ this.handlePasswordInput = this.handlePasswordInput.bind(this)
23+ this.constructWallet = this.constructWallet.bind(this)
24+ }
25+
26+ handleKeystoreInput(keystore) {
27+ this.setState({ keystore })
28+ }
29+
30+ handlePasswordInput(password) {
31+ this.setState({ password })
32+ }
33+
34+ constructWallet() {
35+ const { setWallet } = this.props
36+ const { keystore, password } = this.state
37+
38+ try {
39+ const json = JSON.parse(keystore)
40+ const privateKey = keythereum.recover(password, json)
41+ const wallet = new EthereumWallet(privateKey)
42+ setWallet(Maybe.Just(wallet))
43+ } catch (err) {
44+ setWallet(Maybe.Nothing())
45+ }
46+ }
47+
48+ render() {
49+ const { pushRoute, popRoute, wallet } = this.props
50+ const { keystore, password } = this.state
51+
52+ return (
53+ <Row>
54+ <Col className={'measure-md'}>
55+ <H1 className={'mb-4'}>{ 'Enter Your Keystore File' }</H1>
56+ <Form>
57+ <InputCaption>
58+ { `Please paste in your Ethereum keystore file. If your keystore
59+ file is encrypted with a password, you'll also need to enter
60+ that below.` }
61+ </InputCaption>
62+
63+ <Input
64+ className='pt-8 mt-8'
65+ prop-size='md'
66+ prop-format='innerLabel'
67+ type='text'
68+ name='keystore'
69+ onChange={ this.handleKeystoreInput }
70+ value={ keystore }
71+ autocomplete='off'
72+ autoFocus>
73+ <InnerLabel>{'Keystore File'}</InnerLabel>
74+ </Input>
75+
76+ <Input
77+ className='pt-8 mt-8'
78+ prop-size='md'
79+ prop-format='innerLabel'
80+ type='password'
81+ name='password'
82+ onChange={ this.handlePasswordInput }
83+ value={ password }
84+ autocomplete='off'
85+ autoFocus>
86+ <InnerLabel>{'Password'}</InnerLabel>
87+ </Input>
88+
89+ <Button
90+ className={'mt-10'}
91+ prop-size={ 'wide lg' }
92+ disabled={ keystore === '' }
93+ onClick={ this.constructWallet }
94+ >
95+ { 'Decrypt' }
96+ </Button>
97+
98+ <Button
99+ className={'mt-10'}
100+ prop-size={ 'wide lg' }
101+ disabled={ Maybe.Nothing.hasInstance(wallet) }
102+ onClick={ () => {
103+ popRoute()
104+ pushRoute(ROUTE_NAMES.SHIPS)
105+ }
106+ }
107+ >
108+ { 'Continue →' }
109+ </Button>
110+
111+ </Form>
112+ </Col>
113+ </Row>
114+
115+
116+ )
117+ }
118+}
119+
120+export default Keystore
src/views/Wallet.js+8
@@ -117,6 +117,12 @@ class Wallet extends React.Component {
117 { 'Ethereum Private Key' }
117 { 'Ethereum Private Key' }
118 </DropdownItem>
118 </DropdownItem>
119
119
120+ <DropdownItem
121+ onClick={ () => this.selectClose(() => props.setWalletType(WALLET_NAMES.KEYSTORE)) }
122+ >
123+ { 'Ethereum Keystore File' }
124+ </DropdownItem>
125+
120
126
121
127
122 </InnerLabelDropdown>
128 </InnerLabelDropdown>
@@ -137,6 +143,8 @@ class Wallet extends React.Component {
137 ? ROUTE_NAMES.TREZOR
143 ? ROUTE_NAMES.TREZOR
138 : props.walletType === WALLET_NAMES.PRIVATE_KEY
144 : props.walletType === WALLET_NAMES.PRIVATE_KEY
139 ? ROUTE_NAMES.PRIVATE_KEY
145 ? ROUTE_NAMES.PRIVATE_KEY
146+ : props.walletType === WALLET_NAMES.KEYSTORE
147+ ? ROUTE_NAMES.KEYSTORE
140 : ROUTE_NAMES.DEFAULT
148 : ROUTE_NAMES.DEFAULT
141 )
149 )
142 }
150 }