import React from 'react';
import * as sigil from 'sigil-js';
import ob from 'urbit-ob';
import classnames from 'classnames';
import * as wg from '../lib/lib';
import Button from '../components/Button';
import ReactSVGComponents from '../components/ReactSVGComponents';
import PaperCollateralRenderer from 'PaperCollateralRenderer';
import { MAX_GALAXY, MIN_STAR, MAX_STAR, GEN_STATES } from '../lib/constants';
const NEXT_STEP_NUM = 6;
const shipInfo = ship => {
const name = ob.patp(ship);
const sig = sigil.pour({
colorway: ['black', 'white'],
patp: name,
renderer: ReactSVGComponents,
size: 233,
});
return ship < MAX_GALAXY
? galaxyInfo(name, sig)
: ship < MAX_STAR
? starInfo(name, sig)
: planetInfo(name, sig);
};
const infoHeader = ship => (
{ship + ' Wallet'}
);
const infoSigil = (ship, sig) => {
return (
{sig}
);
};
const getColor = (classOf, seedType) => {
if (classOf === 'galaxy') {
if (seedType === 'manage') return 'bg-medium';
if (seedType === 'voting') return 'bg-medium';
if (seedType === 'spawn') return 'bg-high';
if (seedType === 'master') return 'bg-very-high';
if (seedType === 'masterShard') return 'bg-very-high';
}
if (classOf === 'star') {
if (seedType === 'manage') return 'bg-low';
if (seedType === 'spawn') return 'bg-medium';
if (seedType === 'master') return 'bg-high';
}
if (classOf === 'planet') {
if (seedType === 'manage') return 'bg-low';
if (seedType === 'master') return 'bg-medium';
}
};
const infoManagementSeed = ship => {
const classOf = ob.clan(ship);
const colorClass = getColor(classOf, 'manage');
return (
);
};
const infoVotingSeed = ship => {
const classOf = ob.clan(ship);
const colorClass = getColor(classOf, 'voting');
return (
);
};
const infoSpawnSeed = ship => {
const classOf = ob.clan(ship);
const colorClass = getColor(classOf, 'spawn');
return (
);
};
const infoMasterTicket = ship => {
const classOf = ob.clan(ship);
const colorClass = getColor(classOf, 'master');
return (
);
};
const infoMasterTicketShard = ship => {
const classOf = ob.clan(ship);
const colorClass = getColor(classOf, 'master');
return [
,
,
,
];
};
const Tile = props => {
return (
{props.col1}
{props.col2}
);
};
const galaxyInfo = (ship, sig) => (
{infoHeader(ship)}
{infoSigil(ship, sig)}
{infoMasterTicketShard(ship)}
{infoSpawnSeed(ship)}
{infoManagementSeed(ship)}
{infoVotingSeed(ship)}
);
const starInfo = (ship, sig) => (
{infoHeader(ship)}
{infoSigil(ship, sig)}
{infoMasterTicket(ship)}
{infoSpawnSeed(ship)}
{infoManagementSeed(ship)}
);
const planetInfo = (ship, sig) => (
{infoHeader(ship)}
{infoSigil(ship, sig)}
{infoMasterTicket(ship)}
{infoManagementSeed(ship)}
);
class Generate extends React.Component {
constructor(props) {
super(props);
this.handleGenerate = this.handleGenerate.bind(this);
}
handleGenerate = async () => {
const { props } = this;
const { setGlobalState } = this.props;
setGlobalState({ 'eny.state': GEN_STATES.ENY_PENDING });
const ships = [
...props['profile.value'].galaxies,
...props['profile.value'].stars,
...props['profile.value'].planets,
];
const enyPromises = ships.map(async ship => {
return {
ship,
ticket: await wg.makeTicket(ship),
};
});
const enyTable = await Promise.all(enyPromises);
setGlobalState({
'eny.value': enyTable,
'eny.state': GEN_STATES.ENY_SUCCESS,
'wallets.state': GEN_STATES.DERIVATION_PENDING,
});
await this.forciblyExecuteArgon2Once(enyTable);
const walletPromises = enyTable.map(async ({ ship, ticket }) => {
const boot = ship < MIN_STAR || ship > MAX_STAR;
return {
ship,
wallet: await wg.generateWallet(ship, ticket, boot),
};
});
const wallets = await Promise.all(walletPromises);
const reshapedWallet = wallets.reduce(
(acc, { ship, wallet }) => ({ ...acc, [ship]: wallet }),
{}
);
setGlobalState({
'wallets.value': reshapedWallet,
'wallets.state': GEN_STATES.DERIVATION_SUCCESS,
'paperCollateral.state': GEN_STATES.PAPER_PENDING,
});
};
forciblyExecuteArgon2Once = async enyTable => {
// NB (jtobin):
//
// following is some insane thing required so as not to run into bizarre
// emscripten errors
if (enyTable.length === 0) {
throw new Error('no ship information provided');
} else {
let throwawayEntry = enyTable[0];
// eslint-disable-next-line
let throwaway = await genWallet(
throwawayEntry.ship,
throwawayEntry.ticket,
() => {}
);
}
};
render() {
const { props } = this;
const { setGlobalState } = this.props;
const {
ENY_NOSTART,
ENY_PENDING,
ENY_SUCCESS,
ENY_FAILURE,
DERIVATION_NOSTART,
DERIVATION_PENDING,
DERIVATION_SUCCESS,
DERIVATION_FAILURE,
PAPER_NOSTART,
PAPER_PENDING,
PAPER_SUCCESS,
PAPER_FAILURE,
} = GEN_STATES;
const es = props['eny.state'];
const ws = props['wallets.state'];
const ps = props['paperCollateral.state'];
const ALL_SUCCESS =
es === ENY_SUCCESS && ws === DERIVATION_SUCCESS && ps === PAPER_SUCCESS;
const NONE_START =
es === ENY_NOSTART && ws === DERIVATION_NOSTART && ps === PAPER_NOSTART;
const ANY_ERROR =
es === ENY_FAILURE || ws === DERIVATION_FAILURE || ps === PAPER_FAILURE;
const ANY_PENDING =
es === ENY_PENDING || ws === DERIVATION_PENDING || ps === PAPER_PENDING;
const genButtonClass = classnames({
'bg-blue white': true,
'bg-green noClick black': ALL_SUCCESS,
});
const entropyBarClassnames = classnames({
'bg-blue': es === ENY_SUCCESS,
'bg-lightBlue': es === ENY_PENDING,
'bg-gray': es === ENY_NOSTART,
'bg-orange': es === ENY_FAILURE,
'bg-green': ALL_SUCCESS,
});
const walletsBarClassnames = classnames({
'bg-blue': ws === DERIVATION_SUCCESS,
'bg-lightBlue': ws === DERIVATION_PENDING,
'bg-gray': ws === DERIVATION_NOSTART,
'bg-orange': ws === DERIVATION_FAILURE,
'bg-green': ALL_SUCCESS,
});
const paperBarClassnames = classnames({
'bg-blue': ps === PAPER_SUCCESS,
'bg-lightBlue': ps === PAPER_PENDING,
'bg-gray': ps === PAPER_NOSTART,
'bg-orange': ps === PAPER_FAILURE,
'bg-green': ALL_SUCCESS,
});
const isGenerateButtonDisabled = () => {
if (NONE_START === true) return false;
if (ANY_PENDING === true) return true;
if (ANY_ERROR === true) return false;
if (ALL_SUCCESS === true) return true;
};
const getGenButtonText = () => {
// const N = props['wallets.genCounter'] + 1;
// const X = props['eny.value'].length;
let r = '';
if (NONE_START === true) r = 'Generate All';
if (es === ENY_PENDING) r = 'Generating Entropy';
// if (ws === DERIVATION_PENDING) r = `Generating Wallet ${N} / ${X}`;
if (ws === DERIVATION_PENDING) r = `Generating Wallets`;
if (ps === PAPER_PENDING) r = 'Making Paper Collateral';
if (ALL_SUCCESS === true) r = 'Success.';
if (ANY_ERROR === true) r = 'Try Again';
return r;
};
const disableGenerateButton = isGenerateButtonDisabled();
const genText = getGenButtonText();
const nextButtonClass = classnames({
'bg-blue white': ALL_SUCCESS === true,
'bg-gray black': ALL_SUCCESS !== true,
});
const nextButtonDisabled = ws !== ALL_SUCCESS;
return (
{`Review your paper wallet storage recommendations.`}
{`Each ship is placed into its own wallet with proxies that differ in
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.`}
{props['profile.value'].galaxies.map(ship => shipInfo(ship))}
{props['profile.value'].stars.map(ship => shipInfo(ship))}
{props['profile.value'].planets.map(ship => shipInfo(ship))}
Very High Friction
Extremely valuable. Cold storage on a 3 part sharded paper wallet.
Store each shard in a separate geographic location with protection
against fire, water and other elements.
High Friction
Very valuable. Cold storage on a paper wallet in a different
location than your computer, such as a safe.
Medium Friction
Store cold in a paper wallet; can be stored in a desk drawer in a
trusted environment.
Low Friction
Ok to store hot on a trusted networked computer.
{"Got it? Then it's time to generate your wallets."}
{
'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.'
}
setGlobalState({
route: '/Download',
currentStep: NEXT_STEP_NUM,
})
}
/>
{'text-300'}
{'text-400'}
{'text-500'}
{'text-600'}
{'text-400 text-mono'}
{'text-600 text-mono'}
{'text-500 h-font'}
{'text-600 h-font'}
{props['wallets.state'] === GEN_STATES.DERIVATION_SUCCESS ? (
setGlobalState({
'paperCollateral.value': data,
'paperCollateral.state': GEN_STATES.PAPER_SUCCESS,
})
}
mode={'REGISTRATION'}
/>
) : (
)}
);
}
}
export default Generate;