1import React, { useCallback, useMemo, useRef } from 'react';
2import { Just } from 'folktale/maybe';
3import { Grid, ToggleInput, CheckboxInput } from 'indigo-react';
4import * as azimuth from 'azimuth-js';
5import { randomHex } from 'web3-utils';
7import { usePointCursor } from 'store/pointCursor';
8import { usePointCache } from 'store/pointCache';
9import { useNetwork } from 'store/network';
10import { useWallet } from 'store/wallet';
12import { useLocalRouter } from 'lib/LocalRouter';
13import * as need from 'lib/need';
15 attemptNetworkSeedDerivation,
19import useEthereumTransaction from 'lib/useEthereumTransaction';
20import { GAS_LIMITS } from 'lib/constants';
21import { addHexPrefix } from 'lib/wallet';
22import useKeyfileGenerator from 'lib/useKeyfileGenerator';
24import ViewHeader from 'components/ViewHeader';
25import DownloadKeyfileButton from 'components/DownloadKeyfileButton';
26import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
27import NoticeBox from 'components/NoticeBox';
29import { HexInput } from 'form/Inputs';
32 buildCheckboxValidator,
34} from 'form/validators';
35import BridgeForm from 'form/BridgeForm';
36import Condition from 'form/Condition';
37import FormError from 'form/FormError';
38import convertToInt from 'lib/convertToInt';
40function useSetKeys(manualNetworkSeed, setManualNetworkSeed) {
41 const { urbitWallet, wallet, authMnemonic, authToken } = useWallet();
42 const { pointCursor } = usePointCursor();
43 const { syncDetails, syncRekeyDate, getDetails } = usePointCache();
44 const { contracts } = useNetwork();
46 const _point = need.point(pointCursor);
47 const _contracts = need.contracts(contracts);
48 const _details = need.details(getDetails(_point));
50 const networkRevision = convertToInt(_details.keyRevisionNumber, 10);
51 const randomSeed = useRef();
54 available: keyfileAvailable,
55 generating: keyfileGenerating,
58 } = useKeyfileGenerator(manualNetworkSeed);
60 const buildNetworkSeed = useCallback(
62 if (manualSeed !== undefined) {
63 setManualNetworkSeed(manualSeed);
66 const newNetworkRevision = networkRevision + 1;
67 console.log(`deriving seed with revision ${newNetworkRevision}`);
69 const networkSeed = await attemptNetworkSeedDerivation({
73 revision: newNetworkRevision,
76 if (Just.hasInstance(networkSeed)) {
77 return networkSeed.value;
80 randomSeed.current = randomSeed.current || randomHex(32); // 32 bytes
81 setManualNetworkSeed(randomSeed.current);
83 return randomSeed.current;
86 [setManualNetworkSeed, networkRevision, urbitWallet, _point, authToken]
89 const { completed: _completed, ...rest } = useEthereumTransaction(
91 async (manualSeed, isDiscontinuity) => {
92 const seed = await buildNetworkSeed(manualSeed);
93 const pair = deriveNetworkKeys(seed);
95 return azimuth.ecliptic.configureKeys(
98 addHexPrefix(pair.crypt.public),
99 addHexPrefix(pair.auth.public),
100 CRYPTO_SUITE_VERSION,
104 [_contracts, _point, buildNetworkSeed]
107 () => Promise.all([syncDetails(_point), syncRekeyDate(_point)]),
108 [_point, syncDetails, syncRekeyDate]
110 GAS_LIMITS.CONFIGURE_KEYS
113 // only treat the transaction as completed once we also have keys to download
114 const completed = _completed && keyfileAvailable && !keyfileGenerating;
124export default function UrbitOSNetworkingKeys({
126 setManualNetworkSeed,
128 const { pop } = useLocalRouter();
129 const { pointCursor } = usePointCursor();
130 const { getDetails } = usePointCache();
132 const point = need.point(pointCursor);
133 const details = getDetails(point);
135 const hasKeys = details.matchWith({
136 Nothing: () => false,
137 Just: ({ value: details }) => parseInt(details.keyRevisionNumber, 10) > 0,
138 // we actually don't mind the default NaN behavior of parseInt here,
139 // since NaN > 0 === false and that's a reasonable result
149 } = useSetKeys(manualNetworkSeed, setManualNetworkSeed);
151 const validateForm = useCallback((values, errors) => {
152 if (values.useNetworkSeed && errors.networkSeed) {
157 const validate = useMemo(
161 useNetworkSeed: buildCheckboxValidator(),
162 networkSeed: buildHexValidator(64), // 64 chars
163 useDiscontinuity: buildCheckboxValidator(),
170 const onValues = useCallback(
171 ({ valid, values, form }) => {
174 values.useNetworkSeed ? values.networkSeed : undefined,
175 values.useDiscontinuity
181 if (!values.useNetworkSeed && values.networkSeed) {
182 form.change('networkSeed', '');
185 [construct, unconstruct]
188 const initialValues = useMemo(
190 useNetworkSeed: false,
191 useDiscontinuity: false,
197 'You need this to authenticate with Arvo. Please download';
202 <Grid.Item full as={ViewHeader}>
205 <Grid.Item className="gray4 f6" full>
206 Network Keys solidify the handshake between ID and OS
213 as={DownloadKeyfileButton}
217 <Grid.Item full className="mb3 bg-red3 white t-center p3">
225 initialValues={initialValues}>
233 name="useNetworkSeed"
234 label="Use Custom Network Seed"
235 inverseLabel="Back to Derived Network Seed"
236 disabled={inputsLocked}
238 <Condition when="useNetworkSeed" is={true}>
239 <Grid.Item full as={NoticeBox} className="mb2">
240 When using a custom network seed, you'll need to download
241 your Arvo keyfile immediately after this transaction as
242 Bridge does not store your seed.
248 label="Network Seed (32 bytes)"
249 disabled={inputsLocked}
255 name="useDiscontinuity"
256 label="Breach Continuity"
257 disabled={inputsLocked}
260 <Grid.Item full as={FormError} />
266 as={InlineEthereumTransaction}
268 label={`${hasKeys ? 'Reset' : 'Set'} Networking Keys`}
269 onReturn={() => pop()}
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