on master help sign in
Add keystore file authentication.
commit529b2654642bb42ee718af3ec50f075211b4504b authorJared Tobin <jared@jtobin.io> dateMon 21 Jan 2019, 14:09 (8 years ago) parentb516e1e
4 files changed+138−1
src/lib/router.js+6 src/lib/wallet.js+4−1 src/views/Keystore.js+120 src/views/Wallet.js+8
src/lib/router.js+6
@@ -11,6 +11,7 @@ import Mnemonic from '../views/Mnemonic'
1111import Ledger from '../views/Ledger'
1212import Trezor from '../views/Trezor'
1313import PrivateKey from '../views/PrivateKey'
14+import Keystore from '../views/Keystore'
1415import ViewPoint from '../views/ViewPoint'
1516import SentTransaction from '../views/SentTransaction'
1617import SetKeys from '../views/SetKeys'
@@ -42,6 +43,7 @@ const ROUTE_NAMES = {
4243 LEDGER: Symbol('LEDGER'),
4344 TREZOR: Symbol('TREZOR'),
4445 PRIVATE_KEY: Symbol('PRIVATE_KEY'),
46+ KEYSTORE: Symbol('KEYSTORE'),
4547 VIEW_SHIP: Symbol('VIEW_SHIP'),
4648 SHIPS: Symbol('SHIPS'),
4749 SHIP: Symbol('SHIP'),
@@ -71,6 +73,7 @@ const createRoutes = () => {
7173 routes[ROUTE_NAMES.LEDGER] = Ledger
7274 routes[ROUTE_NAMES.TREZOR] = Trezor
7375 routes[ROUTE_NAMES.PRIVATE_KEY] = PrivateKey
76+ routes[ROUTE_NAMES.KEYSTORE] = Keystore
7477 routes[ROUTE_NAMES.SHIPS] = Points
7578 routes[ROUTE_NAMES.SHIP] = Point
7679 routes[ROUTE_NAMES.SET_MANAGEMENT_PROXY] = SetManagementProxy
@@ -124,6 +127,9 @@ const renderRoute = (props, route) => {
124127 : route === ROUTE_NAMES.PRIVATE_KEY
125128 ? 'Private Key'
126129
130+ : route === ROUTE_NAMES.KEYSTORE
131+ ? 'Keystore File'
132+
127133 : route === ROUTE_NAMES.SHIPS
128134 ? 'Points'
129135
src/lib/wallet.js+4−1
@@ -16,7 +16,8 @@ const WALLET_NAMES = {
1616 SHARDS: Symbol('SHARDS'),
1717 LEDGER: Symbol('LEDGER'),
1818 TREZOR: Symbol('TREZOR'),
19− PRIVATE_KEY: Symbol('PRIVATE_KEY')
19+ PRIVATE_KEY: Symbol('PRIVATE_KEY'),
20+ KEYSTORE: Symbol('KEYSTORE')
2021}
2122
2223function EthereumWallet(privateKey) {
@@ -39,6 +40,8 @@ const renderWalletType = (wallet) =>
3940 ? 'Trezor'
4041 : wallet === WALLET_NAMES.PRIVATE_KEY
4142 ? 'Private Key'
43+ : wallet === WALLET_NAMES.KEYSTORE
44+ ? 'Keystore File'
4245 : 'Wallet'
4346
4447const 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 {
117117 { 'Ethereum Private Key' }
118118 </DropdownItem>
119119
120+ <DropdownItem
121+ onClick={ () => this.selectClose(() => props.setWalletType(WALLET_NAMES.KEYSTORE)) }
122+ >
123+ { 'Ethereum Keystore File' }
124+ </DropdownItem>
125+
120126
121127
122128 </InnerLabelDropdown>
@@ -137,6 +143,8 @@ class Wallet extends React.Component {
137143 ? ROUTE_NAMES.TREZOR
138144 : props.walletType === WALLET_NAMES.PRIVATE_KEY
139145 ? ROUTE_NAMES.PRIVATE_KEY
146+ : props.walletType === WALLET_NAMES.KEYSTORE
147+ ? ROUTE_NAMES.KEYSTORE
140148 : ROUTE_NAMES.DEFAULT
141149 )
142150 }