@@ -1,25 +1,38 @@
1−import React, { useCallback, useState } from 'react';
1+import React, { useCallback, useEffect, useState } from 'react';
2−import { Nothing } from 'folktale/maybe';
2+import { Just, Nothing } from 'folktale/maybe';
3import { Grid, Text, H5, Flex } from 'indigo-react';
3import { Grid, Text, H5, Flex } from 'indigo-react';
4+import * as azimuth from 'azimuth-js';
5+import { randomHex } from 'web3-utils';
5import { usePointCursor } from 'store/pointCursor';
7import { usePointCursor } from 'store/pointCursor';
6import { usePointCache } from 'store/pointCache';
8import { usePointCache } from 'store/pointCache';
8import { useLocalRouter } from 'lib/LocalRouter';
10import { useLocalRouter } from 'lib/LocalRouter';
9import * as need from 'lib/need';
11import * as need from 'lib/need';
10−import { segmentNetworkKey } from 'lib/keys';
13+ segmentNetworkKey,
14+ attemptNetworkSeedDerivation,
11import { formatDotsWithTime } from 'lib/dateFormat';
17import { formatDotsWithTime } from 'lib/dateFormat';
13import ViewHeader from 'components/ViewHeader';
19import ViewHeader from 'components/ViewHeader';
14import MiniBackButton from 'components/MiniBackButton';
20import MiniBackButton from 'components/MiniBackButton';
19−} from 'components/Buttons';
21+import { BootArvoButton, ForwardButton } from 'components/Buttons';
20import FooterButton from 'components/FooterButton';
22import FooterButton from 'components/FooterButton';
21import WarningBox from 'components/WarningBox';
23import WarningBox from 'components/WarningBox';
22import DownloadKeyfileButton from 'components/DownloadKeyfileButton';
24import DownloadKeyfileButton from 'components/DownloadKeyfileButton';
25+import useEthereumTransaction from 'lib/useEthereumTransaction';
26+import { GAS_LIMITS, ZERO_KEY } from 'lib/constants';
27+import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
28+import { addHexPrefix } from 'lib/wallet';
29+import { useNetwork } from 'store/network';
30+import { useWallet } from 'store/wallet';
32+const CRYPTO_SUITE_VERSION = 1;
34+const chainKeyProp = name => d =>
35+ d[name] === ZERO_KEY ? Nothing() : Just(d[name]);
24const renderNetworkKey = key => {
37const renderNetworkKey = key => {
25 const segments = segmentNetworkKey(key);
38 const segments = segmentNetworkKey(key);
@@ -32,14 +45,81 @@ const renderNetworkKey = key => {
34function useSetKeys() {
47function useSetKeys() {
35− const setting = false;
48+ const { urbitWallet, wallet, authMnemonic } = useWallet();
36− const didSet = false;
49+ const { pointCursor } = usePointCursor();
50+ const { syncOwnedPoint, getDetails } = usePointCache();
51+ const { contracts } = useNetwork();
52+ const _point = need.point(pointCursor);
53+ const _contracts = need.contracts(contracts);
55+ const [isDiscontinuity] = useState(false);
56+ // TODO: set discontinuity with radio check?
57+ const [ndNetworkSeed, setNdNetworkSeed] = useState();
59+ const { construct, broadcasting, confirmed, bind } = useEthereumTransaction(
60+ GAS_LIMITS.CONFIGURE_KEYS
63+ // sync point details after success
66+ syncOwnedPoint(_point);
68+ }, [_point, confirmed, syncOwnedPoint]);
37− const setKeys = useCallback(async () => {}, []);
70+ const setKeys = useCallback(async () => {
71+ const details = need.details(getDetails(_point));
72+ const networkRevision = parseInt(details.keyRevisionNumber, 10);
74+ console.log('setting revision to ', networkRevision + 1);
76+ const seed = await attemptNetworkSeedDerivation({
81+ revision: networkRevision + 1,
84+ const _networkSeed = seed.matchWith({
86+ const ndSeed = randomHex(64);
87+ setNdNetworkSeed(ndSeed);
93+ const pair = deriveNetworkKeys(_networkSeed);
95+ const txn = azimuth.ecliptic.configureKeys(
98+ addHexPrefix(pair.crypt.public),
99+ addHexPrefix(pair.auth.public),
100+ CRYPTO_SUITE_VERSION,
@@ -55,23 +135,29 @@ export default function AdminNetworkingKeys() {
55 Nothing: () => false,
135 Nothing: () => false,
56 Just: ({ value: details }) => parseInt(details.keyRevisionNumber, 10) > 0,
136 Just: ({ value: details }) => parseInt(details.keyRevisionNumber, 10) > 0,
58− const [configuring, setConfiguring] = useState(false);
139+ const [didRequestSetKeys, _setDidRequestSetKeys] = useState(false);
60− const { setKeys, setting, didSet } = useSetKeys();
146+ } = useSetKeys();
62− const goRelocate = useCallback(() => push(names.RELOCATE), [push, names]);
148+ const setDidRequestSetKeys = useCallback(() => {
63− const configureTransaction = useCallback(() => setConfiguring(true), [
149+ setKeys();
64− setConfiguring,
150+ _setDidRequestSetKeys(true);
65− ]);
151+ }, [setKeys, _setDidRequestSetKeys]);
67− const inDefaultState = !configuring && !setting && !didSet;
153+ const goRelocate = useCallback(() => push(names.RELOCATE), [push, names]);
69 const renderTitle = () => {
155 const renderTitle = () => {
70− if (didSet) {
156+ if (confirmed) {
71 return 'Networking keys are now set. Download your Keyfile to authenticate Arvo.';
157 return 'Networking keys are now set. Download your Keyfile to authenticate Arvo.';
74− if (setting) {
160+ if (broadcasting) {
75 return 'Setting Network Keys...';
161 return 'Setting Network Keys...';
@@ -83,19 +169,30 @@ export default function AdminNetworkingKeys() {
85 const renderButton = () => {
171 const renderButton = () => {
86− if (didSet) {
172+ if (!didRequestSetKeys) {
87− return <Grid.Item full as={DownloadKeyfileButton} solid />;
173+ return (
178+ onClick={() => setDidRequestSetKeys(true)}>
179+ {hasKeys ? 'Reset' : 'Set'} Networking Keys
90− if (configuring || setting) {
184+ if (confirmed) {
91− return <Grid.Item full as={GenerateButton} solid onClick={setKeys} />;
185+ return (
188+ as={DownloadKeyfileButton}
190+ networkSeed={ndNetworkSeed}
94− return (
195+ return null;
95− <Grid.Item full as={ForwardButton} solid onClick={configureTransaction}>
96− {hasKeys ? 'Reset' : 'Set'} Networking Keys
101 const renderNetworkKeySection = (title, key) => (
198 const renderNetworkKeySection = (title, key) => (
@@ -105,7 +202,7 @@ export default function AdminNetworkingKeys() {
105 </Grid.Item>
202 </Grid.Item>
106 {key.matchWith({
203 {key.matchWith({
107 Nothing: () => (
204 Nothing: () => (
108− <Grid.Item full as={Text} className="f5 gray4">
205+ <Grid.Item full as="code" className="f5 gray4">
110 </Grid.Item>
207 </Grid.Item>
@@ -144,11 +241,11 @@ export default function AdminNetworkingKeys() {
145 {renderNetworkKeySection(
242 {renderNetworkKeySection(
146 'Authentication',
243 'Authentication',
147− details.map(d => d.authenticationKey)
244+ details.chain(chainKeyProp('authenticationKey'))
149 {renderNetworkKeySection(
246 {renderNetworkKeySection(
150 'Encryption',
247 'Encryption',
151− details.map(d => d.encryptionKey)
248+ details.chain(chainKeyProp('encryptionKey'))
153 <Grid.Item full as={Flex} row justify="between" className="mt3">
250 <Grid.Item full as={Flex} row justify="between" className="mt3">
154 {renderDetail('Revision', details.map(d => d.keyRevisionNumber))}
251 {renderDetail('Revision', details.map(d => d.keyRevisionNumber))}
@@ -184,7 +281,7 @@ export default function AdminNetworkingKeys() {
184 {renderTitle()}
281 {renderTitle()}
185 </Grid.Item>
282 </Grid.Item>
187− {inDefaultState && (
284+ {!didRequestSetKeys && (
188 <Grid.Item full as={Text} className="mb3">
285 <Grid.Item full as={Text} className="mb3">
190 ? 'Here are your public keys that authenticate your Arvo.'
287 ? 'Here are your public keys that authenticate your Arvo.'
@@ -192,7 +289,7 @@ export default function AdminNetworkingKeys() {
192 </Grid.Item>
289 </Grid.Item>
195− {didSet && (
292+ {confirmed && (
196 <Grid.Item full as={WarningBox} className="mb3">
293 <Grid.Item full as={WarningBox} className="mb3">
197 You need this keyfile to authenticate with Arvo.
294 You need this keyfile to authenticate with Arvo.
198 </Grid.Item>
295 </Grid.Item>
@@ -200,9 +297,18 @@ export default function AdminNetworkingKeys() {
201 {renderButton()}
298 {renderButton()}
300+ {didRequestSetKeys && (
303+ as={InlineEthereumTransaction}
305+ onReturn={() => pop()}
203− {inDefaultState && renderDetails()}
309+ {!didRequestSetKeys && renderDetails()}
205− {didSet && (
311+ {confirmed && (
207 <Grid.Item full as={BootArvoButton} disabled />
313 <Grid.Item full as={BootArvoButton} disabled />
208 <Grid.Divider />
314 <Grid.Divider />
@@ -210,7 +316,7 @@ export default function AdminNetworkingKeys() {
213− {inDefaultState && (
319+ {!didRequestSetKeys && (
214 <FooterButton onClick={goRelocate} disabled>
320 <FooterButton onClick={goRelocate} disabled>
216 </FooterButton>
322 </FooterButton>