on 3d8d2c7 help sign in
bridge/src/lib/useKeyfileGenerator.js
118 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';
20export default function useKeyfileGenerator(manualNetworkSeed) {
21 const { urbitWallet, wallet, authMnemonic } = useWallet();
22 const { pointCursor } = usePointCursor();
23 const { getDetails } = usePointCache();
25 const [notice, setNotice] = useState('Deriving networking keys...');
26 const [downloaded, setDownloaded] = useState(false);
27 const [generating, setGenerating] = useState(true);
28 const [keyfile, setKeyfile] = useState(false);
30 const _point = need.point(pointCursor);
31 const _details = need.details(getDetails(_point));
33 const networkRevision = parseInt(_details.keyRevisionNumber, 10);
34 const { isOwner, isManagementProxy } = useCurrentPermissions();
36 const hasNetworkingKeys = networkRevision > 0;
37 const available =
38 (isOwner || isManagementProxy) && hasNetworkingKeys && !!keyfile;
40 const generate = useCallback(async () => {
41 if (!hasNetworkingKeys) {
42 setGenerating(false);
43 setNotice('Networking keys not yet set.');
44 console.log(
45 `no networking keys available for revision ${networkRevision}`
46 );
47 return;
48 }
50 const networkSeed = manualNetworkSeed
51 ? Just(manualNetworkSeed)
52 : await attemptNetworkSeedDerivation({
53 urbitWallet,
54 wallet,
55 authMnemonic,
56 details: _details,
57 revision: networkRevision,
58 });
60 if (Nothing.hasInstance(networkSeed)) {
61 setGenerating(false);
62 setNotice(
63 'Custom or nondeterministic networking keys cannot be re-downloaded.'
64 );
65 console.log(`seed is nondeterminable for revision ${networkRevision}`);
66 return;
67 }
69 const _networkSeed = networkSeed.value;
71 const pair = deriveNetworkKeys(_networkSeed);
73 if (!keysMatchChain(pair, _details)) {
74 setGenerating(false);
75 setNotice('Derived networking keys do not match on-chain details.');
76 console.log(`keys do not match details for revision ${networkRevision}`);
77 return;
78 }
80 setNotice();
81 setKeyfile(compileNetworkingKey(pair, _point, networkRevision));
82 setGenerating(false);
83 }, [
84 networkRevision,
85 hasNetworkingKeys,
86 manualNetworkSeed,
87 urbitWallet,
88 wallet,
89 authMnemonic,
90 _details,
91 _point,
92 ]);
94 const download = useCallback(() => {
95 saveAs(
96 new Blob([keyfile], {
97 type: 'text/plain;charset=utf-8',
98 }),
99 `${ob.patp(_point).slice(1)}-${networkRevision}.key`
100 // TODO: ^ unifiy "remove tilde" calls
101 );
102 setDownloaded(true);
103 }, [_point, keyfile, networkRevision]);
105 useEffect(() => {
106 generate();
107 }, [generate]);
109 const values = {
110 generating,
111 available,
112 downloaded,
113 download,
114 notice,
115 };
117 return { ...values, bind: values };