on 3ecbc24 help sign in
bridge/src/lib/useKeyfileGenerator.js
119 lines 3.3 kB history raw
1import { useCallback, useEffect, useState } from 'react';
2import { Just, Nothing } from 'folktale/maybe';
3import saveAs from 'file-saver';
4import * as ob from 'urbit-ob';
6import { usePointCache } from 'store/pointCache';
7import { useWallet } from 'store/wallet';
8import { usePointCursor } from 'store/pointCursor';
10import * as need from 'lib/need';
12import {
13 attemptNetworkSeedDerivation,
14 keysMatchChain,
15 deriveNetworkKeys,
16 compileNetworkingKey,
17} from './keys';
18import useCurrentPermissions from './useCurrentPermissions';
19import convertToInt from './convertToInt';
21export default function useKeyfileGenerator(manualNetworkSeed) {
22 const { urbitWallet, wallet, authMnemonic } = useWallet();
23 const { pointCursor } = usePointCursor();
24 const { getDetails } = usePointCache();
26 const [notice, setNotice] = useState('Deriving networking keys...');
27 const [downloaded, setDownloaded] = useState(false);
28 const [generating, setGenerating] = useState(true);
29 const [keyfile, setKeyfile] = useState(false);
31 const _point = need.point(pointCursor);
32 const _details = need.details(getDetails(_point));
34 const networkRevision = convertToInt(_details.keyRevisionNumber, 10);
35 const { isOwner, isManagementProxy } = useCurrentPermissions();
37 const hasNetworkingKeys = networkRevision > 0;
38 const available =
39 (isOwner || isManagementProxy) && hasNetworkingKeys && !!keyfile;
41 const generate = useCallback(async () => {
42 if (!hasNetworkingKeys) {
43 setGenerating(false);
44 setNotice('Networking keys not yet set.');
45 console.log(
46 `no networking keys available for revision ${networkRevision}`
47 );
48 return;
49 }
51 const networkSeed = manualNetworkSeed
52 ? Just(manualNetworkSeed)
53 : await attemptNetworkSeedDerivation({
54 urbitWallet,
55 wallet,
56 authMnemonic,
57 details: _details,
58 revision: networkRevision,
59 });
61 if (Nothing.hasInstance(networkSeed)) {
62 setGenerating(false);
63 setNotice(
64 'Custom or nondeterministic networking keys cannot be re-downloaded.'
65 );
66 console.log(`seed is nondeterminable for revision ${networkRevision}`);
67 return;
68 }
70 const _networkSeed = networkSeed.value;
72 const pair = deriveNetworkKeys(_networkSeed);
74 if (!keysMatchChain(pair, _details)) {
75 setGenerating(false);
76 setNotice('Derived networking keys do not match on-chain details.');
77 console.log(`keys do not match details for revision ${networkRevision}`);
78 return;
79 }
81 setNotice();
82 setKeyfile(compileNetworkingKey(pair, _point, networkRevision));
83 setGenerating(false);
84 }, [
85 networkRevision,
86 hasNetworkingKeys,
87 manualNetworkSeed,
88 urbitWallet,
89 wallet,
90 authMnemonic,
91 _details,
92 _point,
93 ]);
95 const download = useCallback(() => {
96 saveAs(
97 new Blob([keyfile], {
98 type: 'text/plain;charset=utf-8',
99 }),
100 `${ob.patp(_point).slice(1)}-${networkRevision}.key`
101 // TODO: ^ unifiy "remove tilde" calls
102 );
103 setDownloaded(true);
104 }, [_point, keyfile, networkRevision]);
106 useEffect(() => {
107 generate();
108 }, [generate]);
110 const values = {
111 generating,
112 available,
113 downloaded,
114 download,
115 notice,
116 };
118 return { ...values, bind: values };