1import React from 'react';
2import * as sigil from 'sigil-js';
3import ob from 'urbit-ob';
4import classnames from 'classnames';
5import * as wg from '../../lib/walletgen';
7import Button from '../components/Button';
8import ReactSVGComponents from '../components/ReactSVGComponents';
9import PaperCollateralRenderer from 'PaperCollateralRenderer';
16} from '../../lib/constants';
18const NEXT_STEP_NUM = 6;
20const shipInfo = ship => {
21 const name = ob.patp(ship);
22 const sig = sigil.pour({
23 colorway: ['black', 'white'],
25 renderer: ReactSVGComponents,
29 return ship < MAX_GALAXY
30 ? galaxyInfo(name, sig)
33 : planetInfo(name, sig);
36const infoHeader = ship => (
37 <div className={'row text-600 text-mono'} key={ship + '-header'}>
42const infoSigil = (ship, sig) => {
44 <div className={''} key={'sigil-' + ship}>
50const getColor = (classOf, seedType) => {
51 if (classOf === 'galaxy') {
52 if (seedType === 'manage') return 'bg-medium';
53 if (seedType === 'voting') return 'bg-medium';
54 if (seedType === 'spawn') return 'bg-high';
55 if (seedType === 'master') return 'bg-very-high';
56 if (seedType === 'masterShard') return 'bg-very-high';
58 if (classOf === 'star') {
59 if (seedType === 'manage') return 'bg-low';
60 if (seedType === 'spawn') return 'bg-medium';
61 if (seedType === 'master') return 'bg-high';
63 if (classOf === 'planet') {
64 if (seedType === 'manage') return 'bg-low';
65 if (seedType === 'master') return 'bg-medium';
69const infoManagementSeed = ship => {
70 const classOf = ob.clan(ship);
71 const colorClass = getColor(classOf, 'manage');
74 colorClass={colorClass}
75 key={`info-${ship}-manage`}
76 col1={`Management Proxy`}
82const infoVotingSeed = ship => {
83 const classOf = ob.clan(ship);
84 const colorClass = getColor(classOf, 'voting');
87 colorClass={colorClass}
88 key={`info-${ship}-voting`}
95const infoSpawnSeed = ship => {
96 const classOf = ob.clan(ship);
97 const colorClass = getColor(classOf, 'spawn');
100 colorClass={colorClass}
101 key={`info-${ship}-spawn`}
108const infoMasterTicket = ship => {
109 const classOf = ob.clan(ship);
110 const colorClass = getColor(classOf, 'master');
113 colorClass={colorClass}
114 key={`info-${ship}-master`}
115 col1={`Master Ticket`}
121const infoMasterTicketShard = ship => {
122 const classOf = ob.clan(ship);
123 const colorClass = getColor(classOf, 'master');
126 colorClass={colorClass}
127 key={`info-${ship}-master-1`}
128 col1={`Master Ticket Shard 1 of 3`}
132 colorClass={colorClass}
133 key={`info-${ship}-master-2`}
134 col1={`Master Ticket Shard 2 of 3`}
138 colorClass={colorClass}
139 key={`info-${ship}-master-3`}
140 col1={`Master Ticket Shard 3 of 3`}
146const Tile = props => {
149 className={`${props.colorClass} white row pl-4 text-mono`}
150 style={{ borderBottom: '2px solid black', height: '39px' }}
152 <div className={'col-md-8 flex align-center text-600'}>{props.col1}</div>
153 <div className={'col-md-4 flex align-center text-500'}>{props.col2}</div>
158const galaxyInfo = (ship, sig) => (
159 <div className={'mt-8'} key={'wallet-' + ship}>
161 <div className={'row'} key={ship + '-body'}>
162 {infoSigil(ship, sig)}
163 <div className={'col-md-7 ml-2'} key={'info-' + ship}>
164 {infoMasterTicketShard(ship)}
165 {infoSpawnSeed(ship)}
166 {infoManagementSeed(ship)}
167 {infoVotingSeed(ship)}
173const starInfo = (ship, sig) => (
174 <div className={'mt-8'} key={'wallet-' + ship}>
176 <div className={'row'} key={ship + '-body'}>
177 {infoSigil(ship, sig)}
178 <div className={'col-md-7 ml-2'} key={'info-' + ship}>
179 {infoMasterTicket(ship)}
180 {infoSpawnSeed(ship)}
181 {infoManagementSeed(ship)}
187const planetInfo = (ship, sig) => (
188 <div className={'mt-8'} key={'wallet-' + ship}>
190 <div className={'row'} key={ship + '-body'}>
191 {infoSigil(ship, sig)}
192 <div className={'col-md-7 ml-2'} key={'info-' + ship}>
193 {infoMasterTicket(ship)}
194 {infoManagementSeed(ship)}
200class Generate extends React.Component {
203 this.handleGenerate = this.handleGenerate.bind(this);
206 handleGenerate = async () => {
207 const { props } = this;
208 const { setGlobalState } = this.props;
210 setGlobalState({ 'eny.state': GEN_STATES.ENY_PENDING });
213 ...props['profile.value'].galaxies,
214 ...props['profile.value'].stars,
215 ...props['profile.value'].planets,
218 const enyPromises = ships.map(async ship => {
221 ticket: await wg.makeTicket(ship),
225 const enyTable = await Promise.all(enyPromises);
228 'eny.value': enyTable,
229 'eny.state': GEN_STATES.ENY_SUCCESS,
230 'wallets.state': GEN_STATES.DERIVATION_PENDING,
233 await this.forciblyExecuteArgon2Once(enyTable);
235 const walletPromises = enyTable.map(async ({ ship, ticket }) => {
236 const boot = ship < MIN_STAR || ship > MAX_STAR;
239 wallet: await wg.generateWallet(ship, ticket, boot),
243 const wallets = await Promise.all(walletPromises);
245 const reshapedWallet = wallets.reduce(
246 (acc, { ship, wallet }) => ({ ...acc, [ship]: wallet }),
251 'wallets.value': reshapedWallet,
252 'wallets.state': GEN_STATES.DERIVATION_SUCCESS,
253 'paperCollateral.state': GEN_STATES.PAPER_PENDING,
257 forciblyExecuteArgon2Once = async enyTable => {
260 // following is some insane thing required so as not to run into bizarre
262 if (enyTable.length === 0) {
263 throw new Error('no ship information provided');
265 let throwawayEntry = enyTable[0];
266 // eslint-disable-next-line
267 let throwaway = await genWallet(
269 throwawayEntry.ticket,
276 const { props } = this;
277 const { setGlobalState } = this.props;
294 const es = props['eny.state'];
295 const ws = props['wallets.state'];
296 const ps = props['paperCollateral.state'];
299 es === ENY_SUCCESS && ws === DERIVATION_SUCCESS && ps === PAPER_SUCCESS;
302 es === ENY_NOSTART && ws === DERIVATION_NOSTART && ps === PAPER_NOSTART;
305 es === ENY_FAILURE || ws === DERIVATION_FAILURE || ps === PAPER_FAILURE;
308 es === ENY_PENDING || ws === DERIVATION_PENDING || ps === PAPER_PENDING;
310 const genButtonClass = classnames({
311 'bg-blue white': true,
312 'bg-green noClick black': ALL_SUCCESS,
315 const entropyBarClassnames = classnames({
316 'bg-blue': es === ENY_SUCCESS,
317 'bg-lightBlue': es === ENY_PENDING,
318 'bg-gray': es === ENY_NOSTART,
319 'bg-orange': es === ENY_FAILURE,
320 'bg-green': ALL_SUCCESS,
323 const walletsBarClassnames = classnames({
324 'bg-blue': ws === DERIVATION_SUCCESS,
325 'bg-lightBlue': ws === DERIVATION_PENDING,
326 'bg-gray': ws === DERIVATION_NOSTART,
327 'bg-orange': ws === DERIVATION_FAILURE,
328 'bg-green': ALL_SUCCESS,
331 const paperBarClassnames = classnames({
332 'bg-blue': ps === PAPER_SUCCESS,
333 'bg-lightBlue': ps === PAPER_PENDING,
334 'bg-gray': ps === PAPER_NOSTART,
335 'bg-orange': ps === PAPER_FAILURE,
336 'bg-green': ALL_SUCCESS,
339 const isGenerateButtonDisabled = () => {
340 if (NONE_START === true) return false;
341 if (ANY_PENDING === true) return true;
342 if (ANY_ERROR === true) return false;
343 if (ALL_SUCCESS === true) return true;
346 const getGenButtonText = () => {
347 // const N = props['wallets.genCounter'] + 1;
348 // const X = props['eny.value'].length;
350 if (NONE_START === true) r = 'Generate All';
351 if (es === ENY_PENDING) r = 'Generating Entropy';
352 // if (ws === DERIVATION_PENDING) r = `Generating Wallet ${N} / ${X}`;
353 if (ws === DERIVATION_PENDING) r = `Generating Wallets`;
354 if (ps === PAPER_PENDING) r = 'Making Paper Collateral';
355 if (ALL_SUCCESS === true) r = 'Success.';
356 if (ANY_ERROR === true) r = 'Try Again';
360 const disableGenerateButton = isGenerateButtonDisabled();
361 const genText = getGenButtonText();
363 const nextButtonClass = classnames({
364 'bg-blue white': ALL_SUCCESS === true,
365 'bg-gray black': ALL_SUCCESS !== true,
368 const nextButtonDisabled = ws !== ALL_SUCCESS;
371 <div className={'row'}>
372 <div className={'col-md-8'}>
373 <div className={'col-md-8'}>
374 <h2>{`Review your paper wallet storage recommendations.`}</h2>
376 {`Each ship is placed into its own wallet with proxies that differ in
377 importance and security requirements. These are listed as examples below. A key to our security recommendations can be found to the right of the page.`}
381 {props['profile.value'].galaxies.map(ship => shipInfo(ship))}
382 {props['profile.value'].stars.map(ship => shipInfo(ship))}
383 {props['profile.value'].planets.map(ship => shipInfo(ship))}
386 <div className="col-md-3 col-md-offset-1 mt-9">
387 <div className="fixed" style={{ width: '230px' }}>
388 <div className="col-md-12 bg-very-high h-2 mt-4" />
389 <h4 className="text-600 mt-2">Very High Friction</h4>
390 <p className="text-sm" style={{ lineHeight: '16px' }}>
391 Extremely valuable. Cold storage on a 3 part sharded paper wallet.
392 Store each shard in a separate geographic location with protection
393 against fire, water and other elements.
395 <div className="col-md-12 bg-high h-2 mt-4" />
396 <h4 className="text-600 mt-2">High Friction</h4>
397 <p className="text-sm" style={{ lineHeight: '16px' }}>
398 Very valuable. Cold storage on a paper wallet in a different
399 location than your computer, such as a safe.
401 <div className="col-md-12 bg-medium h-2 mt-4" />
402 <h4 className="text-600 mt-2">Medium Friction</h4>
403 <p className="text-sm" style={{ lineHeight: '16px' }}>
404 Store cold in a paper wallet; can be stored in a desk drawer in a
407 <div className="col-md-12 bg-low h-2 mt-4" />
408 <h4 className="text-600 mt-2">Low Friction</h4>
409 <p className="text-sm" style={{ lineHeight: '16px' }}>
410 Ok to store hot on a trusted networked computer.
415 <div className={'col-md-9 btn-tray col-'}>
416 <h3>{"Got it? Then it's time to generate your wallets."}</h3>
417 <p className={'col-md-8'}>
419 'If you have a large number of ships, this may take several minutes and the page may hang or become unresponsive. If you close this browser window, you will have to start from the beginning.'
423 <div className={'flex h-12 mt-8 mb-4'}>
425 className={`${genButtonClass} b-r-1-black w-50 m-0`}
427 onClick={this.handleGenerate}
428 disable={disableGenerateButton}
430 <div className={`${entropyBarClassnames} f-1 b-r-1-black`} />
431 <div className={`${walletsBarClassnames} f-3 b-r-1-black`} />
432 <div className={`${paperBarClassnames} f-3 b-r-1-black`} />
434 className={`${nextButtonClass} m-0`}
435 text={'View wallets →'}
436 disable={nextButtonDisabled}
440 currentStep: NEXT_STEP_NUM,
447 <div className={'extremely-hidden'}>
448 <div className={'text-300'}>{'text-300'}</div>
449 <div className={'text-400'}>{'text-400'}</div>
450 <div className={'text-500'}>{'text-500'}</div>
451 <div className={'text-600'}>{'text-600'}</div>
452 <div className={'text-400 text-mono'}>{'text-400 text-mono'}</div>
453 <div className={'text-600 text-mono'}>{'text-600 text-mono'}</div>
454 <div className={'text-500 h-font'}>{'text-500 h-font'}</div>
455 <div className={'text-600 h-font'}>{'text-600 h-font'}</div>
458 {props['wallets.state'] === GEN_STATES.DERIVATION_SUCCESS ? (
459 <PaperCollateralRenderer
460 wallet={props['wallets.value']}
461 className={'extremely-hidden'}
464 'paperCollateral.value': data,
465 'paperCollateral.state': GEN_STATES.PAPER_SUCCESS,
468 mode={'REGISTRATION'}
478export default Generate;
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