on 05c1914 help sign in
bridge/src/views/Ticket.js
156 lines 4.2 kB history raw
1import Maybe from 'folktale/maybe'
2import React from 'react'
3import { Button } from '../components/Base'
4import { InnerLabel, ValidatedSigil, PointInput, TicketInput } from '../components/Base'
5import { Row, Col, H1, P } from '../components/Base'
6import * as kg from '../../node_modules/urbit-key-generation/dist/index'
7import * as ob from 'urbit-ob'
9import { ROUTE_NAMES } from '../lib/router'
10import { DEFAULT_HD_PATH, walletFromMnemonic } from '../lib/wallet'
12const placeholder = (len) => {
13 let bytes = window.crypto.getRandomValues(new Uint8Array(len))
14 let hex = bytes.reduce((acc, byt) =>
15 acc + byt.toString(16).padStart(2, '0'),
16 ''
17 )
18 return ob.hex2patq(hex)
21class Ticket extends React.Component {
23 constructor(props) {
24 super(props)
26 this.state = {
27 ticket: '',
28 pointName: '',
29 isUnlocking: false
30 }
32 this.pointPlaceholder = placeholder(4)
33 this.ticketPlaceholder = placeholder(8)
35 this.handleTicketInput = this.handleTicketInput.bind(this)
36 this.handlePointNameInput = this.handlePointNameInput.bind(this)
37 }
39 handleTicketInput(ticket) {
40 this.setState({ ticket })
41 }
43 handlePointNameInput(pointName) {
44 if (pointName.length < 15) {
45 this.setState({ pointName })
46 }
47 }
49 // buttonTriState = (wallet) => {
50 // if (wallet.isNothing()) return 'blue'
51 // if (wallet === false) return 'yellow'
52 // if (Maybe.Nothing.hasInstance(wallet)) return 'green'
53 // }
55 async walletFromTicket(ticket, pointName) {
56 const { setWallet, setUrbitWallet } = this.props
58 this.setState({
59 isUnlocking: true
60 });
62 const urbitWallet = await kg.generateWallet({
63 ticket: ticket,
64 ship: ob.patp2dec(pointName)
65 })
66 const mnemonic = urbitWallet.ownership.seed
67 const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH)
68 setWallet(wallet)
69 setUrbitWallet(Maybe.Just(urbitWallet))
71 this.setState({
72 isUnlocking: false
73 });
74 }
76 render() {
77 const { popRoute, pushRoute, wallet } = this.props
78 const { ticket, pointName } = this.state
80 const phPoint = this.pointPlaceholder
81 const phTick = this.ticketPlaceholder
83 return (
84 <Row>
85 <Col>
86 <H1>{ 'Authenticate' }</H1>
88 <P>
89 { `Please enter your point and Urbit master ticket here. This information is written on your Urbit HD paper wallets.` }
90 </P>
92 <PointInput
93 className='mono mt-8'
94 prop-size='lg'
95 prop-format='innerLabel'
96 type='text'
97 autoFocus
98 placeholder={ `e.g. ${phPoint}` }
99 value={ pointName }
100 onChange={ this.handlePointNameInput }>
101 <InnerLabel>{ 'Point' }</InnerLabel>
102 <ValidatedSigil
103 className={'tr-0 mt-05 mr-0 abs'}
104 patp={pointName}
105 size={68}
106 margin={8} />
107 </PointInput>
110 <TicketInput
111 className='mono mt-8'
112 prop-size='lg'
113 prop-format='innerLabel'
114 type='password'
115 name='ticket'
116 placeholder={ `e.g. ${phTick}` }
117 value={ ticket }
118 onChange={ this.handleTicketInput }>
119 <InnerLabel>{ 'Ticket' }</InnerLabel>
120 </TicketInput>
122 <Button
123 className={'mt-8'}
124 prop-size={'lg wide'}
125 disabled={this.state.isUnlocking || Maybe.Just.hasInstance(wallet)}
126 // prop-color={this.buttonTriState(wallet)}
127 onClick={() => this.walletFromTicket(ticket, pointName)}>
129 <span className="relative">
130 {this.state.isUnlocking &&
131 <span className="btn-spinner"></span>
132 }
133 {'Unlock Wallet →'}
134 </span>
135 </Button>
137 <Button
138 className={'mt-4'}
139 prop-size={'xl wide'}
140 disabled={ Maybe.Nothing.hasInstance(wallet) }
141 onClick={ () => {
142 popRoute()
143 pushRoute(ROUTE_NAMES.SHIPS)
144 }
145 }
146 >
147 { 'Continue →' }
148 </Button>
150 </Col>
151 </Row>
152 )
153 }
156export default Ticket