1import Maybe from 'folktale/maybe'
2import React from 'react'
3import { Button } from '../components/Base'
4import { InnerLabel, ValidatedSigil, PointInput, ShardInput } from '../components/Base'
5import { Row, Col, H1, P, Form } 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'),
18 return ob.hex2patq(hex)
22 SHARD1: Symbol('SHARD1'),
23 SHARD2: Symbol('SHARD2'),
24 SHARD3: Symbol('SHARD3')
27class Shards extends React.Component {
39 this.pointPlaceholder = placeholder(4)
40 this.ticketPlaceholder = placeholder(16)
42 this.handleShardInput = this.handleShardInput.bind(this)
43 this.handlePointNameInput = this.handlePointNameInput.bind(this)
46 handleShardInput(shard, input) {
47 if (shard === SHARDS.SHARD1) {
48 this.setState({ shard1: input })
49 } else if (shard === SHARDS.SHARD2) {
50 this.setState({ shard2: input })
51 } else if (shard === SHARDS.SHARD3) {
52 this.setState({ shard3: input })
56 handlePointNameInput(pointName) {
57 if (pointName.length < 15) {
58 this.setState({ pointName })
62 // buttonTriState = (wallet) => {
63 // if (wallet.isNothing()) return 'blue'
64 // if (wallet === false) return 'yellow'
65 // if (Maybe.Nothing.hasInstance(wallet)) return 'green'
68 async walletFromShards(shard1, shard2, shard3, pointName) {
69 const { setWallet, setUrbitWallet } = this.props
71 const s1 = shard1 === '' ? undefined : shard1
72 const s2 = shard2 === '' ? undefined : shard2
73 const s3 = shard3 === '' ? undefined : shard3
75 let ticket = undefined
77 ticket = kg.combine([s1, s2, s3])
82 if (ticket !== undefined) {
83 const urbitWallet = await kg.generateWallet({
85 ship: ob.patp2dec(pointName)
87 const mnemonic = urbitWallet.ownership.seed
88 const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH)
90 setUrbitWallet(Maybe.Just(urbitWallet))
95 const { popRoute, pushRoute, wallet } = this.props
96 const { shard1, shard2, shard3, pointName } = this.state
98 const phPoint = this.pointPlaceholder
99 const phTick = this.ticketPlaceholder
101 const shards = [shard1, shard2, shard3]
102 const ready = shards.filter(x => x !== '').length > 1
107 <H1>{ 'Authenticate' }</H1>
111 `Enter your point and at least two of your three Urbit master
112 ticket shards here. The index of the input field needs to
113 match the index of the shard.`
121 className='mono mt-8'
123 prop-format='innerLabel'
126 placeholder={ `e.g. ${phPoint}` }
128 onChange={ this.handlePointNameInput }>
129 <InnerLabel>{ 'Point' }</InnerLabel>
131 className={'tr-0 mt-05 mr-0 abs'}
139 className='mono mt-8'
141 prop-format='innerLabel'
144 placeholder={ `e.g. ${phTick}` }
146 onChange={ inp => this.handleShardInput(SHARDS.SHARD1, inp) }>
147 <InnerLabel>{ 'Shard 1' }</InnerLabel>
151 className='mono mt-8'
153 prop-format='innerLabel'
156 placeholder={ `e.g. ${phTick}` }
158 onChange={ inp => this.handleShardInput(SHARDS.SHARD2, inp) }>
159 <InnerLabel>{ 'Shard 2' }</InnerLabel>
163 className='mono mt-8'
165 prop-format='innerLabel'
168 placeholder={ `e.g. ${phTick}` }
170 onChange={ inp => this.handleShardInput(SHARDS.SHARD3, inp) }>
171 <InnerLabel>{ 'Shard 3' }</InnerLabel>
177 prop-size={'lg wide'}
178 // prop-color={this.buttonTriState(wallet)}
180 this.walletFromShards(shard1, shard2, shard3, pointName)
187 prop-size={'xl wide'}
188 disabled={ Maybe.Nothing.hasInstance(wallet) }
191 pushRoute(ROUTE_NAMES.SHIPS)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list