1import React, { useCallback, useEffect, useState } from 'react';
2import { Just, Nothing } from 'folktale/maybe';
12import * as azimuth from 'azimuth-js';
13import { randomHex } from 'web3-utils';
15import { usePointCursor } from 'store/pointCursor';
16import { usePointCache } from 'store/pointCache';
17import { useNetwork } from 'store/network';
18import { useWallet } from 'store/wallet';
20import { useLocalRouter } from 'lib/LocalRouter';
21import * as need from 'lib/need';
24 attemptNetworkSeedDerivation,
27import { formatDotsWithTime } from 'lib/dateFormat';
28import useEthereumTransaction from 'lib/useEthereumTransaction';
29import { GAS_LIMITS, ZERO_KEY, CRYPTO_SUITE_VERSION } from 'lib/constants';
30import { addHexPrefix } from 'lib/wallet';
32import ViewHeader from 'components/ViewHeader';
33import MiniBackButton from 'components/MiniBackButton';
34import { BootArvoButton } from 'components/Buttons';
35import FooterButton from 'components/FooterButton';
36import DownloadKeyfileButton from 'components/DownloadKeyfileButton';
37import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
38import NoticeBox from 'components/NoticeBox';
39import { useHexInput, useCheckboxInput } from 'lib/useInputs';
41const chainKeyProp = name => d =>
42 d[name] === ZERO_KEY ? Nothing() : Just(d[name]);
44const renderNetworkKey = key => {
45 const segments = segmentNetworkKey(key);
51 return segments.join('\n');
54function useSetKeys() {
55 const { urbitWallet, wallet, authMnemonic } = useWallet();
56 const { pointCursor } = usePointCursor();
57 const { syncOwnedPoint, getDetails } = usePointCache();
58 const { contracts } = useNetwork();
59 const _point = need.point(pointCursor);
60 const _contracts = need.contracts(contracts);
62 const [ndNetworkSeed, setNdNetworkSeed] = useState();
66 construct: _construct,
70 } = useEthereumTransaction(GAS_LIMITS.CONFIGURE_KEYS);
72 // sync point details after success
75 syncOwnedPoint(_point);
77 }, [_point, confirmed, syncOwnedPoint]);
79 const construct = useCallback(
80 async (manualSeed, isDiscontinuity) => {
81 const details = need.details(getDetails(_point));
82 const networkRevision = parseInt(details.keyRevisionNumber, 10);
84 let _seed = manualSeed;
86 const networkSeed = await attemptNetworkSeedDerivation({
91 revision: networkRevision + 1,
94 _seed = networkSeed.matchWith({
96 const ndSeed = randomHex(64);
97 setNdNetworkSeed(ndSeed);
103 const pair = deriveNetworkKeys(_seed);
105 const txn = azimuth.ecliptic.configureKeys(
108 addHexPrefix(pair.crypt.public),
109 addHexPrefix(pair.auth.public),
110 CRYPTO_SUITE_VERSION,
111 isDiscontinuity ? 1 : 0
137export default function AdminNetworkingKeys() {
138 const { push, names, pop } = useLocalRouter();
139 const { pointCursor } = usePointCursor();
140 const { getDetails, getRekeyDate } = usePointCache();
142 const point = need.point(pointCursor);
143 const details = getDetails(point);
145 const hasKeys = details.matchWith({
146 Nothing: () => false,
147 Just: ({ value: details }) => parseInt(details.keyRevisionNumber, 10) > 0,
150 const [showNetworkSeedInput, { data: showNetworkSeed }] = useCheckboxInput({
151 name: 'shownetworkseed',
152 label: 'Use Custom Network Seed',
153 inverseLabel: 'Back to Derived Network Seed',
158 { pass: validNetworkSeed, data: networkSeed },
159 { setValue: setNetworkSeed },
162 label: 'Network Seed (64 bytes)',
163 length: 32, // 64 bytes
168 { pass: validDiscontinuity, data: isDiscontinuity },
169 ] = useCheckboxInput({
170 name: 'discontinuity',
171 label: 'Trigger New Continuity Era',
187 (!showNetworkSeed || (showNetworkSeed && validNetworkSeed)) &&
190 construct(networkSeed, isDiscontinuity);
202 if (!showNetworkSeed) {
205 }, [setNetworkSeed, showNetworkSeed]);
207 const goRelocate = useCallback(() => push(names.RELOCATE), [push, names]);
209 const renderTitle = () => {
211 return 'Networking keys are now set. Download your Keyfile to authenticate Arvo.';
215 return 'Setting Network Keys...';
219 return 'Networking keys have not yet been set.';
225 const renderNetworkKeySection = (title, key) => (
227 <Grid.Item full as={H5} className="mt3 gray4">
232 <Grid.Item full as="code" className="f5 gray4">
236 Just: ({ value: key }) => (
238 <Grid.Item full as="code" className="f5 wrap">
241 <Grid.Item full as="code" className="f5 wrap">
242 {renderNetworkKey(key)}
250 const renderDetail = (title, value) => (
251 <Flex.Item as={Flex} col>
252 <Flex.Item as={H5} className="gray4">
257 <Flex.Item as={Text} className="f5 gray4">
261 Just: ({ value }) => <Flex.Item as={Text}>{value}</Flex.Item>,
266 const renderDetails = () => {
269 {renderNetworkKeySection(
271 details.chain(chainKeyProp('authenticationKey'))
273 {renderNetworkKeySection(
275 details.chain(chainKeyProp('encryptionKey'))
277 <Grid.Item full as={Flex} row justify="between" className="mt3">
278 {renderDetail('Revision', details.map(d => d.keyRevisionNumber))}
279 {renderDetail('Continuity Era', details.map(d => d.continuityNumber))}
282 details.map(d => d.cryptoSuiteVersion)
286 <Grid.Item full as={Flex} row justify="between" className="mt3">
289 getRekeyDate(point).map(date =>
291 Ok: r => formatDotsWithTime(r.value),
292 Error: () => Nothing(),
305 <Grid.Item full as={MiniBackButton} onClick={() => pop()} />
307 <Grid.Item full as={ViewHeader}>
311 <Grid.Item full as={Text} className="mb3">
313 ? 'Here are your public keys that authenticate your Arvo.'
314 : 'Set your networking keys to authenticate with Arvo.'}
319 <Grid.Item full as={NoticeBox} className="mb3">
320 You need this keyfile to authenticate with Arvo.
324 as={DownloadKeyfileButton}
326 networkSeed={ndNetworkSeed}
333 <Grid.Item full as={ToggleInput} {...showNetworkSeedInput} />
334 {showNetworkSeed && (
336 <Grid.Item full as={NoticeBox} className="mb2">
337 When using a custom network seed, you'll need to download your
338 Arvo keyfile immediately after this transaction is
339 confirmed—Multipass does not store your seed.
341 <Grid.Item full as={Input} {...networkSeedInput} />
344 <Grid.Item full as={CheckboxInput} {...discontinuityInput} />
350 as={InlineEthereumTransaction}
352 label={`${hasKeys ? 'Reset' : 'Set'} Networking Keys`}
353 onReturn={() => pop()}
356 {isDefaultState && renderDetails()}
360 <Grid.Item full as={BootArvoButton} disabled />
367 <FooterButton onClick={goRelocate} disabled>
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