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/utils/address';
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';
28import AlertBox from 'components/AlertBox';
30import { HexInput } from 'form/Inputs';
33 buildCheckboxValidator,
35} from 'form/validators';
36import BridgeForm from 'form/BridgeForm';
37import Condition from 'form/Condition';
38import FormError from 'form/FormError';
39import { convertToInt } from 'lib/convertToInt';
41function useSetKeys(manualNetworkSeed, setManualNetworkSeed) {
42 const { urbitWallet, wallet, authMnemonic, authToken } = useWallet();
43 const { pointCursor } = usePointCursor();
44 const { syncDetails, syncRekeyDate, getDetails } = usePointCache();
45 const { contracts } = useNetwork();
47 const _point = need.point(pointCursor);
48 const _contracts = need.contracts(contracts);
49 const _details = need.details(getDetails(_point));
51 const networkRevision = convertToInt(_details.keyRevisionNumber, 10);
52 const randomSeed = useRef();
55 available: keyfileAvailable,
56 generating: keyfileGenerating,
59 } = useKeyfileGenerator(manualNetworkSeed);
61 const buildNetworkSeed = useCallback(
63 if (manualSeed !== undefined) {
64 setManualNetworkSeed(manualSeed);
67 const newNetworkRevision = networkRevision + 1;
68 console.log(`deriving seed with revision ${newNetworkRevision}`);
70 const networkSeed = await attemptNetworkSeedDerivation({
77 revision: newNetworkRevision,
80 if (Just.hasInstance(networkSeed)) {
81 return networkSeed.value;
84 randomSeed.current = randomSeed.current || randomHex(32); // 32 bytes
85 setManualNetworkSeed(randomSeed.current);
87 return randomSeed.current;
102 const { completed: _completed, ...rest } = useEthereumTransaction(
104 async (manualSeed, isDiscontinuity) => {
105 const seed = await buildNetworkSeed(manualSeed);
106 const pair = deriveNetworkKeys(seed);
108 return azimuth.ecliptic.configureKeys(
111 addHexPrefix(pair.crypt.public),
112 addHexPrefix(pair.auth.public),
113 CRYPTO_SUITE_VERSION,
117 [_contracts, _point, buildNetworkSeed]
120 () => Promise.all([syncDetails(_point), syncRekeyDate(_point)]),
121 [_point, syncDetails, syncRekeyDate]
123 GAS_LIMITS.CONFIGURE_KEYS
126 // only treat the transaction as completed once we also have keys to download
127 const completed = _completed && keyfileAvailable && !keyfileGenerating;
137export default function UrbitOSNetworkingKeys({
139 setManualNetworkSeed,
141 const { pop } = useLocalRouter();
142 const { pointCursor } = usePointCursor();
143 const { getDetails } = usePointCache();
145 const point = need.point(pointCursor);
146 const details = getDetails(point);
148 const hasKeys = details.matchWith({
149 Nothing: () => false,
150 Just: ({ value: details }) => parseInt(details.keyRevisionNumber, 10) > 0,
151 // we actually don't mind the default NaN behavior of parseInt here,
152 // since NaN > 0 === false and that's a reasonable result
162 } = useSetKeys(manualNetworkSeed, setManualNetworkSeed);
164 const validateForm = useCallback((values, errors) => {
165 if (values.useNetworkSeed && errors.networkSeed) {
170 const validate = useMemo(
174 useNetworkSeed: buildCheckboxValidator(),
175 networkSeed: buildHexValidator(64), // 64 chars
176 useDiscontinuity: buildCheckboxValidator(),
183 const onValues = useCallback(
184 ({ valid, values, form }) => {
187 values.useNetworkSeed ? values.networkSeed : undefined,
188 values.useDiscontinuity
194 if (!values.useNetworkSeed && values.networkSeed) {
195 form.change('networkSeed', '');
198 [construct, unconstruct]
201 const initialValues = useMemo(
203 useNetworkSeed: false,
204 useDiscontinuity: false,
209 const viewTitle = completed
210 ? 'Network Keys are now set'
211 : 'Set Networking Keys';
214 'You need this keyfile to authenticate with your OS. Please Download.';
219 <Grid.Item full as={ViewHeader}>
223 <Grid.Item className="gray4 f5" full>
224 Network Keys authenticate Urbit ID with Urbit OS.
232 as={DownloadKeyfileButton}
236 <Grid.Item full as={AlertBox} className="mb8">
244 initialValues={initialValues}>
252 name="useNetworkSeed"
253 label="Use Custom Network Seed"
254 inverseLabel="Back to Derived Network Seed"
255 disabled={inputsLocked}
257 <Condition when="useNetworkSeed" is={true}>
258 <Grid.Item full as={NoticeBox} className="mb2">
259 When using a custom network seed, you'll need to download
260 your Arvo keyfile immediately after this transaction as
261 Bridge does not store your seed.
267 label="Network Seed (32 bytes)"
268 disabled={inputsLocked}
274 name="useDiscontinuity"
275 label="Breach Continuity"
276 disabled={inputsLocked}
279 <Grid.Item full as={FormError} />
285 as={InlineEthereumTransaction}
287 label={`${hasKeys ? 'Reset' : 'Set'} Networking Keys`}
288 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