on master help sign in
Support optional BIP39 passphrases in auth views.
18ec1b6Jared Tobin
src/bridge/views/Mnemonic.js+42−5
@@ -21,28 +21,47 @@ class Mnemonic extends React.Component {
21
21
22 this.state = {
22 this.state = {
23 mnemonic: '',
23 mnemonic: '',
24+ passphrase: '',
24 hdpath: DEFAULT_HD_PATH,
25 hdpath: DEFAULT_HD_PATH,
25 }
26 }
26
27
27 this.handleMnemonicInput = this.handleMnemonicInput.bind(this)
28 this.handleMnemonicInput = this.handleMnemonicInput.bind(this)
29+ this.handlePassphraseInput = this.handlePassphraseInput.bind(this)
28 this.handleHdPathInput = this.handleHdPathInput.bind(this)
30 this.handleHdPathInput = this.handleHdPathInput.bind(this)
29 }
31 }
30
32
31 componentDidMount() {
33 componentDidMount() {
32− const { mnemonic, hdpath } = this.state
34+ const { mnemonic, hdpath, passphrase } = this.state
33− this.attemptWalletDerivation(mnemonic, hdpath)
35+ this.attemptWalletDerivation(mnemonic, hdpath, passphrase)
34
36
35 this.setState({
37 this.setState({
36 exampleMnemonic: bip39.generateMnemonic(),
38 exampleMnemonic: bip39.generateMnemonic(),
37 })
39 })
38 }
40 }
39
41
42+ handlePassphraseInput(passphrase) {
43+ this.setState((state, _) => {
44+ const mnemonic = state.mnemonic
45+ const hdpath = state.hdpath
46+ this.attemptWalletDerivation(
47+ mnemonic,
48+ hdpath === '' ? DEFAULT_HD_PATH : hdpath,
49+ passphrase
50+ )
51+ return {
52+ passphrase
53+ }
54+ })
55+ }
56+
40 handleMnemonicInput(mnemonic) {
57 handleMnemonicInput(mnemonic) {
41 this.setState((state, _) => {
58 this.setState((state, _) => {
42 const hdpath = state.hdpath
59 const hdpath = state.hdpath
60+ const passphrase = state.passphrase
43 this.attemptWalletDerivation(
61 this.attemptWalletDerivation(
44 mnemonic,
62 mnemonic,
45− hdpath === '' ? DEFAULT_HD_PATH : hdpath
63+ hdpath === '' ? DEFAULT_HD_PATH : hdpath,
64+ passphrase
46 )
65 )
47 return {
66 return {
48 mnemonic
67 mnemonic
@@ -53,9 +72,11 @@ class Mnemonic extends React.Component {
53 handleHdPathInput(hdpath) {
72 handleHdPathInput(hdpath) {
54 this.setState((state, _) => {
73 this.setState((state, _) => {
55 const mnemonic = state.mnemonic
74 const mnemonic = state.mnemonic
75+ const passphrase = state.passphrase
56 this.attemptWalletDerivation(
76 this.attemptWalletDerivation(
57 mnemonic,
77 mnemonic,
58− hdpath === '' ? DEFAULT_HD_PATH : hdpath
78+ hdpath === '' ? DEFAULT_HD_PATH : hdpath,
79+ passphrase
59 )
80 )
60 return {
81 return {
61 hdpath
82 hdpath
@@ -76,7 +97,8 @@ class Mnemonic extends React.Component {
76 const {
97 const {
77 mnemonic,
98 mnemonic,
78 hdpath,
99 hdpath,
79− exampleMnemonic
100+ exampleMnemonic,
101+ passphrase
80 } = this.state
102 } = this.state
81
103
82 return (
104 return (
@@ -101,6 +123,21 @@ class Mnemonic extends React.Component {
101 <InnerLabel>{'Mnemonic'}</InnerLabel>
123 <InnerLabel>{'Mnemonic'}</InnerLabel>
102 </MnemonicInput>
124 </MnemonicInput>
103
125
126+ <InputCaption>
127+ {`If your wallet requires a passphrase, you may enter it below.`}
128+ </InputCaption>
129+
130+ <Input
131+ className='pt-8'
132+ prop-size='md'
133+ prop-format='innerLabel'
134+ name='passphrase'
135+ type='password'
136+ value={ passphrase }
137+ autocomplete='off'
138+ onChange={ this.handlePassphraseInput }>
139+ <InnerLabel>{'Passphrase'}</InnerLabel>
140+ </Input>
104
141
105 <InputCaption>
142 <InputCaption>
106 {`If you'd like to use a custom derivation path, you may enter it below.`}
143 {`If you'd like to use a custom derivation path, you may enter it below.`}
src/bridge/views/Shards.js+33−11
@@ -40,12 +40,14 @@ class Shards extends React.Component {
40 shard1: '',
40 shard1: '',
41 shard2: '',
41 shard2: '',
42 shard3: '',
42 shard3: '',
43+ passphrase: '',
43 pointName: ''
44 pointName: ''
44 }
45 }
45
46
46 this.pointPlaceholder = placeholder(4)
47 this.pointPlaceholder = placeholder(4)
47 this.ticketPlaceholder = placeholder(16)
48 this.ticketPlaceholder = placeholder(16)
48
49
50+ this.handlePassphraseInput = this.handlePassphraseInput.bind(this)
49 this.handleShardInput = this.handleShardInput.bind(this)
51 this.handleShardInput = this.handleShardInput.bind(this)
50 this.handlePointNameInput = this.handlePointNameInput.bind(this)
52 this.handlePointNameInput = this.handlePointNameInput.bind(this)
51 }
53 }
@@ -60,19 +62,17 @@ class Shards extends React.Component {
60 }
62 }
61 }
63 }
62
64
65+ handlePassphraseInput(passphrase) {
66+ this.setState({ passphrase })
67+ }
68+
63 handlePointNameInput(pointName) {
69 handlePointNameInput(pointName) {
64 if (pointName.length < 15) {
70 if (pointName.length < 15) {
65 this.setState({ pointName })
71 this.setState({ pointName })
66 }
72 }
67 }
73 }
68
74
69− // buttonTriState = (wallet) => {
70− // if (wallet.isNothing()) return 'blue'
71− // if (wallet === false) return 'yellow'
72− // if (Maybe.Nothing.hasInstance(wallet)) return 'green'
73− // }
74−
75− async walletFromShards(shard1, shard2, shard3, pointName) {
75+ async walletFromShards(shard1, shard2, shard3, pointName, passphrase) {
76 const { setWallet, setUrbitWallet } = this.props
76 const { setWallet, setUrbitWallet } = this.props
77
77
78 const s1 = shard1 === '' ? undefined : shard1
78 const s1 = shard1 === '' ? undefined : shard1
@@ -89,10 +89,11 @@ class Shards extends React.Component {
89 if (ticket !== undefined) {
89 if (ticket !== undefined) {
90 const urbitWallet = await kg.generateWallet({
90 const urbitWallet = await kg.generateWallet({
91 ticket: ticket,
91 ticket: ticket,
92− ship: ob.patp2dec(pointName)
92+ ship: ob.patp2dec(pointName),
93+ passphrase: passphrase
93 })
94 })
94 const mnemonic = urbitWallet.ownership.seed
95 const mnemonic = urbitWallet.ownership.seed
95− const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH)
96+ const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH, passphrase)
96 setWallet(wallet)
97 setWallet(wallet)
97 setUrbitWallet(Just(urbitWallet))
98 setUrbitWallet(Just(urbitWallet))
98 }
99 }
@@ -100,7 +101,7 @@ class Shards extends React.Component {
100
101
101 render() {
102 render() {
102 const { popRoute, pushRoute, wallet } = this.props
103 const { popRoute, pushRoute, wallet } = this.props
103− const { shard1, shard2, shard3, pointName } = this.state
104+ const { shard1, shard2, shard3, pointName, passphrase } = this.state
104
105
105 const phPoint = this.pointPlaceholder
106 const phPoint = this.pointPlaceholder
106 const phTick = this.ticketPlaceholder
107 const phTick = this.ticketPlaceholder
@@ -176,13 +177,34 @@ class Shards extends React.Component {
176 <InnerLabel>{ 'Shard 3' }</InnerLabel>
177 <InnerLabel>{ 'Shard 3' }</InnerLabel>
177 </ShardInput>
178 </ShardInput>
178
179
180+ <InputCaption>
181+ { 'If your wallet requires a passphrase, you may enter it below.' }
182+ </InputCaption>
183+
184+ <Input
185+ className='pt-8'
186+ prop-size='md'
187+ prop-format='innerLabel'
188+ name='passphrase'
189+ type='password'
190+ value={ passphrase }
191+ autocomplete='off'
192+ onChange={ this.handlePassphraseInput }>
193+ <InnerLabel>{'Passphrase'}</InnerLabel>
194+ </Input>
195+
179 <Button
196 <Button
180 disabled={ !ready }
197 disabled={ !ready }
181 className={'mt-8'}
198 className={'mt-8'}
182 prop-size={'lg wide'}
199 prop-size={'lg wide'}
183 // prop-color={this.buttonTriState(wallet)}
200 // prop-color={this.buttonTriState(wallet)}
184 onClick={() =>
201 onClick={() =>
185− this.walletFromShards(shard1, shard2, shard3, pointName)
202+ this.walletFromShards(
203+ shard1,
204+ shard2,
205+ shard3,
206+ pointName,
207+ passphrase)
186 }>
208 }>
187 {'Unlock Wallet →'}
209 {'Unlock Wallet →'}
188 </Button>
210 </Button>
src/bridge/views/Ticket.js+30−12
@@ -33,6 +33,7 @@ class Ticket extends React.Component {
33 this.state = {
33 this.state = {
34 ticket: '',
34 ticket: '',
35 pointName: '',
35 pointName: '',
36+ passphrase: '',
36 isUnlocking: false
37 isUnlocking: false
37 }
38 }
38
39
@@ -40,6 +41,7 @@ class Ticket extends React.Component {
40 this.ticketPlaceholder = placeholder(8)
41 this.ticketPlaceholder = placeholder(8)
41
42
42 this.handleTicketInput = this.handleTicketInput.bind(this)
43 this.handleTicketInput = this.handleTicketInput.bind(this)
44+ this.handlePassphraseInput = this.handlePassphraseInput.bind(this)
43 this.handlePointNameInput = this.handlePointNameInput.bind(this)
45 this.handlePointNameInput = this.handlePointNameInput.bind(this)
44 }
46 }
45
47
@@ -47,19 +49,17 @@ class Ticket extends React.Component {
47 this.setState({ ticket })
49 this.setState({ ticket })
48 }
50 }
49
51
52+ handlePassphraseInput(passphrase) {
53+ this.setState({ passphrase })
54+ }
55+
50 handlePointNameInput(pointName) {
56 handlePointNameInput(pointName) {
51 if (pointName.length < 15) {
57 if (pointName.length < 15) {
52 this.setState({ pointName })
58 this.setState({ pointName })
53 }
59 }
54 }
60 }
55
61
56− // buttonTriState = (wallet) => {
57− // if (wallet.isNothing()) return 'blue'
58− // if (wallet === false) return 'yellow'
59− // if (Maybe.Nothing.hasInstance(wallet)) return 'green'
60− // }
61−
62− async walletFromTicket(ticket, pointName) {
62+ async walletFromTicket(ticket, pointName, passphrase) {
63 const { setWallet, setUrbitWallet } = this.props
63 const { setWallet, setUrbitWallet } = this.props
64
64
65 this.setState({
65 this.setState({
@@ -68,10 +68,11 @@ class Ticket extends React.Component {
68
68
69 const urbitWallet = await kg.generateWallet({
69 const urbitWallet = await kg.generateWallet({
70 ticket: ticket,
70 ticket: ticket,
71− ship: ob.patp2dec(pointName)
71+ ship: ob.patp2dec(pointName),
72+ passphrase: passphrase
72 })
73 })
73 const mnemonic = urbitWallet.ownership.seed
74 const mnemonic = urbitWallet.ownership.seed
74− const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH)
75+ const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH, passphrase)
75 setWallet(wallet)
76 setWallet(wallet)
76 setUrbitWallet(Just(urbitWallet))
77 setUrbitWallet(Just(urbitWallet))
77
78
@@ -82,7 +83,7 @@ class Ticket extends React.Component {
82
83
83 render() {
84 render() {
84 const { popRoute, pushRoute, wallet } = this.props
85 const { popRoute, pushRoute, wallet } = this.props
85− const { ticket, pointName } = this.state
86+ const { ticket, pointName, passphrase } = this.state
86
87
87 const phPoint = this.pointPlaceholder
88 const phPoint = this.pointPlaceholder
88 const phTick = this.ticketPlaceholder
89 const phTick = this.ticketPlaceholder
@@ -126,12 +127,29 @@ class Ticket extends React.Component {
126 <InnerLabel>{ 'Ticket' }</InnerLabel>
127 <InnerLabel>{ 'Ticket' }</InnerLabel>
127 </TicketInput>
128 </TicketInput>
128
129
130+ <InputCaption>
131+ { 'If your wallet requires a passphrase, you may enter it below.' }
132+ </InputCaption>
133+
134+ <Input
135+ className='pt-8'
136+ prop-size='md'
137+ prop-format='innerLabel'
138+ name='passphrase'
139+ type='password'
140+ value={ passphrase }
141+ autocomplete='off'
142+ onChange={ this.handlePassphraseInput }>
143+ <InnerLabel>{'Passphrase'}</InnerLabel>
144+ </Input>
145+
129 <Button
146 <Button
130 className={'mt-8'}
147 className={'mt-8'}
131 prop-size={'lg wide'}
148 prop-size={'lg wide'}
132 disabled={this.state.isUnlocking || Just.hasInstance(wallet)}
149 disabled={this.state.isUnlocking || Just.hasInstance(wallet)}
133− // prop-color={this.buttonTriState(wallet)}
150+ onClick={
134− onClick={() => this.walletFromTicket(ticket, pointName)}>
151+ () => this.walletFromTicket(ticket, pointName, passphrase)
152+ }>
135
153
136 <span className="relative">
154 <span className="relative">
137 {this.state.isUnlocking &&
155 {this.state.isUnlocking &&