1import { Just, Nothing } from 'folktale/maybe';
2import React from 'react';
3import { Button } from '../components/old/Base';
11} from '../components/old/Base';
12import { Row, Col, H1, P } from '../components/old/Base';
13import * as kg from 'urbit-key-generation/dist';
14import * as ob from 'urbit-ob';
16import { ROUTE_NAMES } from '../lib/routeNames';
17import { withHistory } from '../store/history';
18import { urbitWalletFromTicket } from '../lib/wallet';
19import { compose } from '../lib/lib';
20import { withWallet } from '../store/wallet';
22const placeholder = len => {
23 let bytes = window.crypto.getRandomValues(new Uint8Array(len));
24 let hex = bytes.reduce(
25 (acc, byt) => acc + byt.toString(16).padStart(2, '0'),
28 return ob.hex2patq(hex);
32 SHARD1: Symbol('SHARD1'),
33 SHARD2: Symbol('SHARD2'),
34 SHARD3: Symbol('SHARD3'),
37class Shards extends React.Component {
49 this.pointPlaceholder = placeholder(4);
50 this.ticketPlaceholder = placeholder(16);
52 this.handlePassphraseInput = this.handlePassphraseInput.bind(this);
53 this.handleShardInput = this.handleShardInput.bind(this);
54 this.handlePointNameInput = this.handlePointNameInput.bind(this);
57 handleShardInput(shard, input) {
58 if (shard === SHARDS.SHARD1) {
59 this.setState({ shard1: input });
60 } else if (shard === SHARDS.SHARD2) {
61 this.setState({ shard2: input });
62 } else if (shard === SHARDS.SHARD3) {
63 this.setState({ shard3: input });
67 handlePassphraseInput(passphrase) {
68 this.setState({ passphrase });
71 handlePointNameInput(pointName) {
72 if (pointName.length < 15) {
73 this.setState({ pointName });
77 async walletFromShards(shard1, shard2, shard3, pointName, passphrase) {
78 const s1 = shard1 === '' ? undefined : shard1;
79 const s2 = shard2 === '' ? undefined : shard2;
80 const s3 = shard3 === '' ? undefined : shard3;
82 let ticket = undefined;
84 ticket = kg.combine([s1, s2, s3]);
89 if (ticket !== undefined) {
90 const uhdw = await urbitWalletFromTicket(ticket, pointName, passphrase);
91 this.props.setUrbitWallet(Just(uhdw));
96 const { history, wallet } = this.props;
97 const { shard1, shard2, shard3, pointName, passphrase } = this.state;
99 const phPoint = this.pointPlaceholder;
100 const phTick = this.ticketPlaceholder;
102 const shards = [shard1, shard2, shard3];
103 const ready = shards.filter(x => x !== '').length > 1;
108 <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.`}
117 className="mono mt-8"
119 prop-format="innerLabel"
122 placeholder={`e.g. ${phPoint}`}
124 onChange={this.handlePointNameInput}>
125 <InnerLabel>{'Point'}</InnerLabel>
127 className={'tr-0 mt-05 mr-0 abs'}
135 className="mono mt-8"
137 prop-format="innerLabel"
140 placeholder={`e.g. ${phTick}`}
142 onChange={inp => this.handleShardInput(SHARDS.SHARD1, inp)}>
143 <InnerLabel>{'Shard 1'}</InnerLabel>
147 className="mono mt-8"
149 prop-format="innerLabel"
152 placeholder={`e.g. ${phTick}`}
154 onChange={inp => this.handleShardInput(SHARDS.SHARD2, inp)}>
155 <InnerLabel>{'Shard 2'}</InnerLabel>
159 className="mono mt-8"
161 prop-format="innerLabel"
164 placeholder={`e.g. ${phTick}`}
166 onChange={inp => this.handleShardInput(SHARDS.SHARD3, inp)}>
167 <InnerLabel>{'Shard 3'}</InnerLabel>
171 {'If your wallet requires a passphrase, you may enter it below.'}
177 prop-format="innerLabel"
182 onChange={this.handlePassphraseInput}>
183 <InnerLabel>{'Passphrase'}</InnerLabel>
189 prop-size={'lg wide'}
190 // prop-color={this.buttonTriState(wallet)}
192 this.walletFromShards(
205 prop-size={'xl wide'}
206 disabled={Nothing.hasInstance(wallet)}
207 onClick={() => history.popAndPush(ROUTE_NAMES.SHIPS)}>
216export default compose(
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