@@ -1,25 +1,38 @@
1−import React, { useCallback, useState } from 'react';
2−import { Nothing } from 'folktale/maybe';
1+import React, { useCallback, useEffect, useState } from 'react';
2+import { Just, Nothing } from 'folktale/maybe';
33import { Grid, Text, H5, Flex } from 'indigo-react';
4+import * as azimuth from 'azimuth-js';
5+import { randomHex } from 'web3-utils';
46
57import { usePointCursor } from 'store/pointCursor';
68import { usePointCache } from 'store/pointCache';
79
810import { useLocalRouter } from 'lib/LocalRouter';
911import * as need from 'lib/need';
10−import { segmentNetworkKey } from 'lib/keys';
12+import {
13+ segmentNetworkKey,
14+ attemptNetworkSeedDerivation,
15+ deriveNetworkKeys,
16+} from 'lib/keys';
1117import { formatDotsWithTime } from 'lib/dateFormat';
1218
1319import ViewHeader from 'components/ViewHeader';
1420import MiniBackButton from 'components/MiniBackButton';
15−import {
16− GenerateButton,
17− BootArvoButton,
18− ForwardButton,
19−} from 'components/Buttons';
21+import { BootArvoButton, ForwardButton } from 'components/Buttons';
2022import FooterButton from 'components/FooterButton';
2123import WarningBox from 'components/WarningBox';
2224import 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';
31+
32+const CRYPTO_SUITE_VERSION = 1;
33+
34+const chainKeyProp = name => d =>
35+ d[name] === ZERO_KEY ? Nothing() : Just(d[name]);
2336
2437const renderNetworkKey = key => {
2538 const segments = segmentNetworkKey(key);
@@ -32,14 +45,81 @@ const renderNetworkKey = key => {
3245};
3346
3447function useSetKeys() {
35− const setting = false;
36− const didSet = false;
37− const setKeys = useCallback(async () => {}, []);
48+ const { urbitWallet, wallet, authMnemonic } = useWallet();
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);
54+
55+ const [isDiscontinuity] = useState(false);
56+ // TODO: set discontinuity with radio check?
57+ const [ndNetworkSeed, setNdNetworkSeed] = useState();
58+
59+ const { construct, broadcasting, confirmed, bind } = useEthereumTransaction(
60+ GAS_LIMITS.CONFIGURE_KEYS
61+ );
62+
63+ // sync point details after success
64+ useEffect(() => {
65+ if (confirmed) {
66+ syncOwnedPoint(_point);
67+ }
68+ }, [_point, confirmed, syncOwnedPoint]);
69+
70+ const setKeys = useCallback(async () => {
71+ const details = need.details(getDetails(_point));
72+ const networkRevision = parseInt(details.keyRevisionNumber, 10);
73+
74+ console.log('setting revision to ', networkRevision + 1);
75+
76+ const seed = await attemptNetworkSeedDerivation({
77+ urbitWallet,
78+ wallet,
79+ authMnemonic,
80+ details,
81+ revision: networkRevision + 1,
82+ });
83+
84+ const _networkSeed = seed.matchWith({
85+ Nothing: () => {
86+ const ndSeed = randomHex(64);
87+ setNdNetworkSeed(ndSeed);
88+ return ndSeed;
89+ },
90+ Just: p => p.value,
91+ });
92+
93+ const pair = deriveNetworkKeys(_networkSeed);
94+
95+ const txn = azimuth.ecliptic.configureKeys(
96+ _contracts,
97+ _point,
98+ addHexPrefix(pair.crypt.public),
99+ addHexPrefix(pair.auth.public),
100+ CRYPTO_SUITE_VERSION,
101+ isDiscontinuity
102+ );
103+
104+ construct(txn);
105+ }, [
106+ _contracts,
107+ _point,
108+ authMnemonic,
109+ construct,
110+ getDetails,
111+ isDiscontinuity,
112+ urbitWallet,
113+ wallet,
114+ ]);
38115
39116 return {
40− setting,
41− didSet,
42117 setKeys,
118+ construct,
119+ broadcasting,
120+ confirmed,
121+ ndNetworkSeed,
122+ bind,
43123 };
44124}
45125
@@ -55,23 +135,29 @@ export default function AdminNetworkingKeys() {
55135 Nothing: () => false,
56136 Just: ({ value: details }) => parseInt(details.keyRevisionNumber, 10) > 0,
57137 });
58− const [configuring, setConfiguring] = useState(false);
59138
60− const { setKeys, setting, didSet } = useSetKeys();
139+ const [didRequestSetKeys, _setDidRequestSetKeys] = useState(false);
140+ const {
141+ setKeys,
142+ broadcasting,
143+ confirmed,
144+ ndNetworkSeed,
145+ bind,
146+ } = useSetKeys();
61147
62− const goRelocate = useCallback(() => push(names.RELOCATE), [push, names]);
63− const configureTransaction = useCallback(() => setConfiguring(true), [
64− setConfiguring,
65− ]);
148+ const setDidRequestSetKeys = useCallback(() => {
149+ setKeys();
150+ _setDidRequestSetKeys(true);
151+ }, [setKeys, _setDidRequestSetKeys]);
66152
67− const inDefaultState = !configuring && !setting && !didSet;
153+ const goRelocate = useCallback(() => push(names.RELOCATE), [push, names]);
68154
69155 const renderTitle = () => {
70− if (didSet) {
156+ if (confirmed) {
71157 return 'Networking keys are now set. Download your Keyfile to authenticate Arvo.';
72158 }
73159
74− if (setting) {
160+ if (broadcasting) {
75161 return 'Setting Network Keys...';
76162 }
77163
@@ -83,19 +169,30 @@ export default function AdminNetworkingKeys() {
83169 };
84170
85171 const renderButton = () => {
86− if (didSet) {
87− return <Grid.Item full as={DownloadKeyfileButton} solid />;
172+ if (!didRequestSetKeys) {
173+ return (
174+ <Grid.Item
175+ full
176+ as={ForwardButton}
177+ solid
178+ onClick={() => setDidRequestSetKeys(true)}>
179+ {hasKeys ? 'Reset' : 'Set'} Networking Keys
180+ </Grid.Item>
181+ );
88182 }
89183
90− if (configuring || setting) {
91− return <Grid.Item full as={GenerateButton} solid onClick={setKeys} />;
184+ if (confirmed) {
185+ return (
186+ <Grid.Item
187+ full
188+ as={DownloadKeyfileButton}
189+ solid
190+ networkSeed={ndNetworkSeed}
191+ />
192+ );
92193 }
93194
94− return (
95− <Grid.Item full as={ForwardButton} solid onClick={configureTransaction}>
96− {hasKeys ? 'Reset' : 'Set'} Networking Keys
97− </Grid.Item>
98− );
195+ return null;
99196 };
100197
101198 const renderNetworkKeySection = (title, key) => (
@@ -105,7 +202,7 @@ export default function AdminNetworkingKeys() {
105202 </Grid.Item>
106203 {key.matchWith({
107204 Nothing: () => (
108− <Grid.Item full as={Text} className="f5 gray4">
205+ <Grid.Item full as="code" className="f5 gray4">
109206 Unset
110207 </Grid.Item>
111208 ),
@@ -144,11 +241,11 @@ export default function AdminNetworkingKeys() {
144241 <>
145242 {renderNetworkKeySection(
146243 'Authentication',
147− details.map(d => d.authenticationKey)
244+ details.chain(chainKeyProp('authenticationKey'))
148245 )}
149246 {renderNetworkKeySection(
150247 'Encryption',
151− details.map(d => d.encryptionKey)
248+ details.chain(chainKeyProp('encryptionKey'))
152249 )}
153250 <Grid.Item full as={Flex} row justify="between" className="mt3">
154251 {renderDetail('Revision', details.map(d => d.keyRevisionNumber))}
@@ -184,7 +281,7 @@ export default function AdminNetworkingKeys() {
184281 {renderTitle()}
185282 </Grid.Item>
186283
187− {inDefaultState && (
284+ {!didRequestSetKeys && (
188285 <Grid.Item full as={Text} className="mb3">
189286 {hasKeys
190287 ? 'Here are your public keys that authenticate your Arvo.'
@@ -192,7 +289,7 @@ export default function AdminNetworkingKeys() {
192289 </Grid.Item>
193290 )}
194291
195− {didSet && (
292+ {confirmed && (
196293 <Grid.Item full as={WarningBox} className="mb3">
197294 You need this keyfile to authenticate with Arvo.
198295 </Grid.Item>
@@ -200,9 +297,18 @@ export default function AdminNetworkingKeys() {
200297
201298 {renderButton()}
202299
203− {inDefaultState && renderDetails()}
300+ {didRequestSetKeys && (
301+ <Grid.Item
302+ full
303+ as={InlineEthereumTransaction}
304+ {...bind}
305+ onReturn={() => pop()}
306+ />
307+ )}
308+
309+ {!didRequestSetKeys && renderDetails()}
204310
205− {didSet && (
311+ {confirmed && (
206312 <>
207313 <Grid.Item full as={BootArvoButton} disabled />
208314 <Grid.Divider />
@@ -210,7 +316,7 @@ export default function AdminNetworkingKeys() {
210316 )}
211317 </Grid>
212318
213− {inDefaultState && (
319+ {!didRequestSetKeys && (
214320 <FooterButton onClick={goRelocate} disabled>
215321 Relocate
216322 </FooterButton>