on master help sign in
Merged
4a7ff4dChris Johnson
package-lock.json+45−16
@@ -1,6 +1,6 @@
1{
1{
2 "name": "bridge",
2 "name": "bridge",
3− "version": "1.1.0",
3+ "version": "1.2.1",
4 "lockfileVersion": 1,
4 "lockfileVersion": 1,
5 "requires": true,
5 "requires": true,
6 "dependencies": {
6 "dependencies": {
@@ -18700,24 +18700,27 @@
18700 "integrity": "sha512-zbfndGg//cMW4aytXuF4dkBuUu/SUBA94U2zkmDoRwcplS9hCCn/S3VDp4A7CXw5tVxeCm9F6zdfHzWzei6nXg=="
18700 "integrity": "sha512-zbfndGg//cMW4aytXuF4dkBuUu/SUBA94U2zkmDoRwcplS9hCCn/S3VDp4A7CXw5tVxeCm9F6zdfHzWzei6nXg=="
18701 },
18701 },
18702 "trezor-connect": {
18702 "trezor-connect": {
18703− "version": "6.0.3",
18703+ "version": "7.0.2",
18704− "resolved": "https://registry.npmjs.org/trezor-connect/-/trezor-connect-6.0.3.tgz",
18704+ "resolved": "https://registry.npmjs.org/trezor-connect/-/trezor-connect-7.0.2.tgz",
18705− "integrity": "sha512-QqgnulN9uQstVjxYTF9+gcNk01kBUQA4xXy2abyPOgxh8Wio9iiSGftQa12KkFfWLZKkZD1sL03KvQ2ievL05g==",
18705+ "integrity": "sha512-KAFOqxEHHaFvrG8NGLFlM/QxHcwIa3gwfXcgTjCYM0g0zRpwIQBwe35AKsjAQO5yiTJQGa0Cu5MZufGJRGYjjw==",
18706 "requires": {
18706 "requires": {
18707− "babel-runtime": "^6.26.0",
18707+ "@babel/runtime": "^7.3.1",
18708− "events": "^1.1.1",
18708+ "events": "^3.0.0",
18709− "whatwg-fetch": "^2.0.4"
18709+ "whatwg-fetch": "^3.0.0"
18710 },
18710 },
18711 "dependencies": {
18711 "dependencies": {
18712− "events": {
18712+ "@babel/runtime": {
18713− "version": "1.1.1",
18713+ "version": "7.4.3",
18714− "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
18714+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.3.tgz",
18715− "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
18715+ "integrity": "sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==",
18716+ "requires": {
18717+ "regenerator-runtime": "^0.13.2"
18718+ }
18716 },
18719 },
18717− "whatwg-fetch": {
18720+ "regenerator-runtime": {
18718− "version": "2.0.4",
18721+ "version": "0.13.2",
18719− "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
18722+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
18720− "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
18723+ "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA=="
18721 }
18724 }
18722 }
18725 }
18723 },
18726 },
@@ -18791,6 +18794,14 @@
18791 "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
18794 "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
18792 "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
18795 "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
18793 },
18796 },
18797+ "typedarray-to-buffer": {
18798+ "version": "3.1.5",
18799+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
18800+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
18801+ "requires": {
18802+ "is-typedarray": "^1.0.0"
18803+ }
18804+ },
18794 "typeforce": {
18805 "typeforce": {
18795 "version": "1.18.0",
18806 "version": "1.18.0",
18796 "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
18807 "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
@@ -19599,7 +19610,20 @@
19599 "integrity": "sha1-j93qQuGbvyUh7IeVRkV6Yjqdye8=",
19610 "integrity": "sha1-j93qQuGbvyUh7IeVRkV6Yjqdye8=",
19600 "requires": {
19611 "requires": {
19601 "underscore": "1.8.3",
19612 "underscore": "1.8.3",
19602− "web3-core-helpers": "1.0.0-beta.33"
19613+ "web3-core-helpers": "1.0.0-beta.33",
19614+ "websocket": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible"
19615+ },
19616+ "dependencies": {
19617+ "websocket": {
19618+ "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
19619+ "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
19620+ "requires": {
19621+ "debug": "^2.2.0",
19622+ "nan": "^2.3.3",
19623+ "typedarray-to-buffer": "^3.1.2",
19624+ "yaeti": "^0.0.6"
19625+ }
19626+ }
19603 }
19627 }
19604 },
19628 },
19605 "web3-shh": {
19629 "web3-shh": {
@@ -20700,6 +20724,11 @@
20700 "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
20724 "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
20701 "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
20725 "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
20702 },
20726 },
20727+ "yaeti": {
20728+ "version": "0.0.6",
20729+ "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
20730+ "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc="
20731+ },
20703 "yallist": {
20732 "yallist": {
20704 "version": "2.1.2",
20733 "version": "2.1.2",
20705 "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
20734 "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
src/bridge/lib/wallet.js+2−2
@@ -86,10 +86,10 @@ const toChecksumAddress = (address) => {
86const eqAddr = (addr0, addr1) =>
86const eqAddr = (addr0, addr1) =>
87 toChecksumAddress(addr0) === toChecksumAddress(addr1)
87 toChecksumAddress(addr0) === toChecksumAddress(addr1)
88
88
89−const walletFromMnemonic = (mnemonic, hdpath) => {
89+const walletFromMnemonic = (mnemonic, hdpath, passphrase) => {
90 const seed =
90 const seed =
91 bip39.validateMnemonic(mnemonic)
91 bip39.validateMnemonic(mnemonic)
92− ? Maybe.Just(bip39.mnemonicToSeed(mnemonic))
92+ ? Maybe.Just(bip39.mnemonicToSeed(mnemonic, passphrase))
93 : Maybe.Nothing()
93 : Maybe.Nothing()
94
94
95 const toWallet = (sd, path) => {
95 const toWallet = (sd, path) => {
src/bridge/views/Mnemonic.js+53−11
@@ -1,8 +1,13 @@
1import * as bip39 from 'bip39'
1import * as bip39 from 'bip39'
2−import Maybe from 'folktale/maybe'
2+import { Just, Nothing } from 'folktale/maybe'
3import React from 'react'
3import React from 'react'
4import { Button } from '../components/Base'
4import { Button } from '../components/Base'
5+import {
6+ Input,
7+ MnemonicInput,
8+ InnerLabel,
9+ InputCaption
5−import { Input, MnemonicInput, InnerLabel, InputCaption } from '../components/Base'
10+ } from '../components/Base'
6import { Row, Col, H1 } from '../components/Base'
11import { Row, Col, H1 } from '../components/Base'
7
12
8import { ROUTE_NAMES } from '../lib/router'
13import { ROUTE_NAMES } from '../lib/router'
@@ -16,28 +21,47 @@ class Mnemonic extends React.Component {
16
21
17 this.state = {
22 this.state = {
18 mnemonic: '',
23 mnemonic: '',
24+ passphrase: '',
19 hdpath: DEFAULT_HD_PATH,
25 hdpath: DEFAULT_HD_PATH,
20 }
26 }
21
27
22 this.handleMnemonicInput = this.handleMnemonicInput.bind(this)
28 this.handleMnemonicInput = this.handleMnemonicInput.bind(this)
29+ this.handlePassphraseInput = this.handlePassphraseInput.bind(this)
23 this.handleHdPathInput = this.handleHdPathInput.bind(this)
30 this.handleHdPathInput = this.handleHdPathInput.bind(this)
24 }
31 }
25
32
26 componentDidMount() {
33 componentDidMount() {
27− const { mnemonic, hdpath } = this.state
34+ const { mnemonic, hdpath, passphrase } = this.state
28− this.attemptWalletDerivation(mnemonic, hdpath)
35+ this.attemptWalletDerivation(mnemonic, hdpath, passphrase)
29
36
30 this.setState({
37 this.setState({
31 exampleMnemonic: bip39.generateMnemonic(),
38 exampleMnemonic: bip39.generateMnemonic(),
32 })
39 })
33 }
40 }
34
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+
35 handleMnemonicInput(mnemonic) {
57 handleMnemonicInput(mnemonic) {
36 this.setState((state, _) => {
58 this.setState((state, _) => {
37 const hdpath = state.hdpath
59 const hdpath = state.hdpath
60+ const passphrase = state.passphrase
38 this.attemptWalletDerivation(
61 this.attemptWalletDerivation(
39 mnemonic,
62 mnemonic,
40− hdpath === '' ? DEFAULT_HD_PATH : hdpath
63+ hdpath === '' ? DEFAULT_HD_PATH : hdpath,
64+ passphrase
41 )
65 )
42 return {
66 return {
43 mnemonic
67 mnemonic
@@ -48,9 +72,11 @@ class Mnemonic extends React.Component {
48 handleHdPathInput(hdpath) {
72 handleHdPathInput(hdpath) {
49 this.setState((state, _) => {
73 this.setState((state, _) => {
50 const mnemonic = state.mnemonic
74 const mnemonic = state.mnemonic
75+ const passphrase = state.passphrase
51 this.attemptWalletDerivation(
76 this.attemptWalletDerivation(
52 mnemonic,
77 mnemonic,
53− hdpath === '' ? DEFAULT_HD_PATH : hdpath
78+ hdpath === '' ? DEFAULT_HD_PATH : hdpath,
79+ passphrase
54 )
80 )
55 return {
81 return {
56 hdpath
82 hdpath
@@ -58,11 +84,11 @@ class Mnemonic extends React.Component {
58 })
84 })
59 }
85 }
60
86
61− attemptWalletDerivation(mnemonic, hdpath) {
87+ attemptWalletDerivation(mnemonic, hdpath, passphrase) {
62 const { setWallet, setAuthMnemonic, setWalletHdPath } = this.props
88 const { setWallet, setAuthMnemonic, setWalletHdPath } = this.props
63− const wallet = walletFromMnemonic(mnemonic, hdpath)
89+ const wallet = walletFromMnemonic(mnemonic, hdpath, passphrase)
64 setWallet(wallet)
90 setWallet(wallet)
65− setAuthMnemonic(Maybe.Just(mnemonic))
91+ setAuthMnemonic(Just(mnemonic))
66 setWalletHdPath(hdpath)
92 setWalletHdPath(hdpath)
67 }
93 }
68
94
@@ -71,7 +97,8 @@ class Mnemonic extends React.Component {
71 const {
97 const {
72 mnemonic,
98 mnemonic,
73 hdpath,
99 hdpath,
74− exampleMnemonic
100+ exampleMnemonic,
101+ passphrase
75 } = this.state
102 } = this.state
76
103
77 return (
104 return (
@@ -96,6 +123,21 @@ class Mnemonic extends React.Component {
96 <InnerLabel>{'Mnemonic'}</InnerLabel>
123 <InnerLabel>{'Mnemonic'}</InnerLabel>
97 </MnemonicInput>
124 </MnemonicInput>
98
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>
99
141
100 <InputCaption>
142 <InputCaption>
101 {`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.`}
@@ -114,7 +156,7 @@ class Mnemonic extends React.Component {
114
156
115 <Button
157 <Button
116 className={'mt-10'}
158 className={'mt-10'}
117− disabled={ Maybe.Nothing.hasInstance(wallet) }
159+ disabled={ Nothing.hasInstance(wallet) }
118 onClick={ () => {
160 onClick={ () => {
119 popRoute()
161 popRoute()
120 pushRoute(ROUTE_NAMES.SHIPS)
162 pushRoute(ROUTE_NAMES.SHIPS)
src/bridge/views/Shards.js+44−15
@@ -1,7 +1,14 @@
1−import Maybe from 'folktale/maybe'
1+import { Just, Nothing } from 'folktale/maybe'
2import React from 'react'
2import React from 'react'
3import { Button } from '../components/Base'
3import { Button } from '../components/Base'
4+import {
5+ InnerLabel,
6+ ValidatedSigil,
7+ PointInput,
8+ ShardInput,
9+ InputCaption,
10+ Input
4−import { InnerLabel, ValidatedSigil, PointInput, ShardInput } from '../components/Base'
11+ } from '../components/Base'
5import { Row, Col, H1, P } from '../components/Base'
12import { Row, Col, H1, P } from '../components/Base'
6import * as kg from '../../../node_modules/urbit-key-generation/dist/index'
13import * as kg from '../../../node_modules/urbit-key-generation/dist/index'
7import * as ob from 'urbit-ob'
14import * as ob from 'urbit-ob'
@@ -33,12 +40,14 @@ class Shards extends React.Component {
33 shard1: '',
40 shard1: '',
34 shard2: '',
41 shard2: '',
35 shard3: '',
42 shard3: '',
43+ passphrase: '',
36 pointName: ''
44 pointName: ''
37 }
45 }
38
46
39 this.pointPlaceholder = placeholder(4)
47 this.pointPlaceholder = placeholder(4)
40 this.ticketPlaceholder = placeholder(16)
48 this.ticketPlaceholder = placeholder(16)
41
49
50+ this.handlePassphraseInput = this.handlePassphraseInput.bind(this)
42 this.handleShardInput = this.handleShardInput.bind(this)
51 this.handleShardInput = this.handleShardInput.bind(this)
43 this.handlePointNameInput = this.handlePointNameInput.bind(this)
52 this.handlePointNameInput = this.handlePointNameInput.bind(this)
44 }
53 }
@@ -53,19 +62,17 @@ class Shards extends React.Component {
53 }
62 }
54 }
63 }
55
64
65+ handlePassphraseInput(passphrase) {
66+ this.setState({ passphrase })
67+ }
68+
56 handlePointNameInput(pointName) {
69 handlePointNameInput(pointName) {
57 if (pointName.length < 15) {
70 if (pointName.length < 15) {
58 this.setState({ pointName })
71 this.setState({ pointName })
59 }
72 }
60 }
73 }
61
74
62− // buttonTriState = (wallet) => {
63− // if (wallet.isNothing()) return 'blue'
64− // if (wallet === false) return 'yellow'
65− // if (Maybe.Nothing.hasInstance(wallet)) return 'green'
66− // }
67−
68− async walletFromShards(shard1, shard2, shard3, pointName) {
75+ async walletFromShards(shard1, shard2, shard3, pointName, passphrase) {
69 const { setWallet, setUrbitWallet } = this.props
76 const { setWallet, setUrbitWallet } = this.props
70
77
71 const s1 = shard1 === '' ? undefined : shard1
78 const s1 = shard1 === '' ? undefined : shard1
@@ -82,18 +89,19 @@ class Shards extends React.Component {
82 if (ticket !== undefined) {
89 if (ticket !== undefined) {
83 const urbitWallet = await kg.generateWallet({
90 const urbitWallet = await kg.generateWallet({
84 ticket: ticket,
91 ticket: ticket,
85− ship: ob.patp2dec(pointName)
92+ ship: ob.patp2dec(pointName),
93+ passphrase: passphrase
86 })
94 })
87 const mnemonic = urbitWallet.ownership.seed
95 const mnemonic = urbitWallet.ownership.seed
88− const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH)
96+ const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH, passphrase)
89 setWallet(wallet)
97 setWallet(wallet)
90− setUrbitWallet(Maybe.Just(urbitWallet))
98+ setUrbitWallet(Just(urbitWallet))
91 }
99 }
92 }
100 }
93
101
94 render() {
102 render() {
95 const { popRoute, pushRoute, wallet } = this.props
103 const { popRoute, pushRoute, wallet } = this.props
96− const { shard1, shard2, shard3, pointName } = this.state
104+ const { shard1, shard2, shard3, pointName, passphrase } = this.state
97
105
98 const phPoint = this.pointPlaceholder
106 const phPoint = this.pointPlaceholder
99 const phTick = this.ticketPlaceholder
107 const phTick = this.ticketPlaceholder
@@ -169,13 +177,34 @@ class Shards extends React.Component {
169 <InnerLabel>{ 'Shard 3' }</InnerLabel>
177 <InnerLabel>{ 'Shard 3' }</InnerLabel>
170 </ShardInput>
178 </ShardInput>
171
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+
172 <Button
196 <Button
173 disabled={ !ready }
197 disabled={ !ready }
174 className={'mt-8'}
198 className={'mt-8'}
175 prop-size={'lg wide'}
199 prop-size={'lg wide'}
176 // prop-color={this.buttonTriState(wallet)}
200 // prop-color={this.buttonTriState(wallet)}
177 onClick={() =>
201 onClick={() =>
178− this.walletFromShards(shard1, shard2, shard3, pointName)
202+ this.walletFromShards(
203+ shard1,
204+ shard2,
205+ shard3,
206+ pointName,
207+ passphrase)
179 }>
208 }>
180 {'Unlock Wallet →'}
209 {'Unlock Wallet →'}
181 </Button>
210 </Button>
@@ -183,7 +212,7 @@ class Shards extends React.Component {
183 <Button
212 <Button
184 className={'mt-4'}
213 className={'mt-4'}
185 prop-size={'xl wide'}
214 prop-size={'xl wide'}
186− disabled={ Maybe.Nothing.hasInstance(wallet) }
215+ disabled={ Nothing.hasInstance(wallet) }
187 onClick={ () => {
216 onClick={ () => {
188 popRoute()
217 popRoute()
189 pushRoute(ROUTE_NAMES.SHIPS)
218 pushRoute(ROUTE_NAMES.SHIPS)
src/bridge/views/Ticket.js+42−17
@@ -1,7 +1,14 @@
1−import Maybe from 'folktale/maybe'
1+import { Just, Nothing } from 'folktale/maybe'
2import React from 'react'
2import React from 'react'
3import { Button } from '../components/Base'
3import { Button } from '../components/Base'
4+import {
5+ InnerLabel,
6+ ValidatedSigil,
7+ PointInput,
8+ TicketInput,
9+ Input,
10+ InputCaption
4−import { InnerLabel, ValidatedSigil, PointInput, TicketInput } from '../components/Base'
11+ } from '../components/Base'
5import { Row, Col, H1, P } from '../components/Base'
12import { Row, Col, H1, P } from '../components/Base'
6import * as kg from '../../../node_modules/urbit-key-generation/dist/index'
13import * as kg from '../../../node_modules/urbit-key-generation/dist/index'
7import * as ob from 'urbit-ob'
14import * as ob from 'urbit-ob'
@@ -26,6 +33,7 @@ class Ticket extends React.Component {
26 this.state = {
33 this.state = {
27 ticket: '',
34 ticket: '',
28 pointName: '',
35 pointName: '',
36+ passphrase: '',
29 isUnlocking: false
37 isUnlocking: false
30 }
38 }
31
39
@@ -33,6 +41,7 @@ class Ticket extends React.Component {
33 this.ticketPlaceholder = placeholder(8)
41 this.ticketPlaceholder = placeholder(8)
34
42
35 this.handleTicketInput = this.handleTicketInput.bind(this)
43 this.handleTicketInput = this.handleTicketInput.bind(this)
44+ this.handlePassphraseInput = this.handlePassphraseInput.bind(this)
36 this.handlePointNameInput = this.handlePointNameInput.bind(this)
45 this.handlePointNameInput = this.handlePointNameInput.bind(this)
37 }
46 }
38
47
@@ -40,19 +49,17 @@ class Ticket extends React.Component {
40 this.setState({ ticket })
49 this.setState({ ticket })
41 }
50 }
42
51
52+ handlePassphraseInput(passphrase) {
53+ this.setState({ passphrase })
54+ }
55+
43 handlePointNameInput(pointName) {
56 handlePointNameInput(pointName) {
44 if (pointName.length < 15) {
57 if (pointName.length < 15) {
45 this.setState({ pointName })
58 this.setState({ pointName })
46 }
59 }
47 }
60 }
48
61
49− // buttonTriState = (wallet) => {
50− // if (wallet.isNothing()) return 'blue'
51− // if (wallet === false) return 'yellow'
52− // if (Maybe.Nothing.hasInstance(wallet)) return 'green'
53− // }
54−
55− async walletFromTicket(ticket, pointName) {
62+ async walletFromTicket(ticket, pointName, passphrase) {
56 const { setWallet, setUrbitWallet } = this.props
63 const { setWallet, setUrbitWallet } = this.props
57
64
58 this.setState({
65 this.setState({
@@ -61,12 +68,13 @@ class Ticket extends React.Component {
61
68
62 const urbitWallet = await kg.generateWallet({
69 const urbitWallet = await kg.generateWallet({
63 ticket: ticket,
70 ticket: ticket,
64− ship: ob.patp2dec(pointName)
71+ ship: ob.patp2dec(pointName),
72+ passphrase: passphrase
65 })
73 })
66 const mnemonic = urbitWallet.ownership.seed
74 const mnemonic = urbitWallet.ownership.seed
67− const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH)
75+ const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH, passphrase)
68 setWallet(wallet)
76 setWallet(wallet)
69− setUrbitWallet(Maybe.Just(urbitWallet))
77+ setUrbitWallet(Just(urbitWallet))
70
78
71 this.setState({
79 this.setState({
72 isUnlocking: false
80 isUnlocking: false
@@ -75,7 +83,7 @@ class Ticket extends React.Component {
75
83
76 render() {
84 render() {
77 const { popRoute, pushRoute, wallet } = this.props
85 const { popRoute, pushRoute, wallet } = this.props
78− const { ticket, pointName } = this.state
86+ const { ticket, pointName, passphrase } = this.state
79
87
80 const phPoint = this.pointPlaceholder
88 const phPoint = this.pointPlaceholder
81 const phTick = this.ticketPlaceholder
89 const phTick = this.ticketPlaceholder
@@ -119,12 +127,29 @@ class Ticket extends React.Component {
119 <InnerLabel>{ 'Ticket' }</InnerLabel>
127 <InnerLabel>{ 'Ticket' }</InnerLabel>
120 </TicketInput>
128 </TicketInput>
121
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+
122 <Button
146 <Button
123 className={'mt-8'}
147 className={'mt-8'}
124 prop-size={'lg wide'}
148 prop-size={'lg wide'}
125− disabled={this.state.isUnlocking || Maybe.Just.hasInstance(wallet)}
149+ disabled={this.state.isUnlocking || Just.hasInstance(wallet)}
126− // prop-color={this.buttonTriState(wallet)}
150+ onClick={
127− onClick={() => this.walletFromTicket(ticket, pointName)}>
151+ () => this.walletFromTicket(ticket, pointName, passphrase)
152+ }>
128
153
129 <span className="relative">
154 <span className="relative">
130 {this.state.isUnlocking &&
155 {this.state.isUnlocking &&
@@ -137,7 +162,7 @@ class Ticket extends React.Component {
137 <Button
162 <Button
138 className={'mt-4'}
163 className={'mt-4'}
139 prop-size={'xl wide'}
164 prop-size={'xl wide'}
140− disabled={ Maybe.Nothing.hasInstance(wallet) }
165+ disabled={ Nothing.hasInstance(wallet) }
141 onClick={ () => {
166 onClick={ () => {
142 popRoute()
167 popRoute()
143 pushRoute(ROUTE_NAMES.SHIPS)
168 pushRoute(ROUTE_NAMES.SHIPS)