on 072c6eb help sign in
bridge/src/lib/useKeyfileGenerator.js
107 lines 2.9 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 { getDetails } = usePointCache();
22 const { urbitWallet, wallet, authMnemonic } = useWallet();
23 const { pointCursor } = usePointCursor();
25 const [downloaded, setDownloaded] = useState(false);
26 const [generating, setGenerating] = useState(true);
27 const [keyfile, setKeyfile] = useState(false);
29 const _point = need.point(pointCursor);
30 const _details = need.details(getDetails(_point));
32 const networkRevision = parseInt(_details.keyRevisionNumber, 10);
33 const { isOwner, isManagementProxy } = useCurrentPermissions();
35 const hasNetworkingKeys = networkRevision > 0;
36 const available =
37 (isOwner || isManagementProxy) && hasNetworkingKeys && !!keyfile;
39 console.log(
40 `keyfile available (${available}) for revision ${networkRevision}`
41 );
43 const generate = useCallback(async () => {
44 console.log('generating for network revision', networkRevision);
46 const networkSeed = manualNetworkSeed
47 ? Just(manualNetworkSeed)
48 : await attemptNetworkSeedDerivation({
49 urbitWallet,
50 wallet,
51 authMnemonic,
52 details: _details,
53 revision: networkRevision,
54 });
56 if (Nothing.hasInstance(networkSeed)) {
57 setGenerating(false);
58 console.log('manual network seed not provided and key not derivable');
59 return;
60 }
62 const _networkSeed = networkSeed.value;
64 const pair = deriveNetworkKeys(_networkSeed);
66 if (!keysMatchChain(pair, _details)) {
67 setGenerating(false);
68 console.log('derived network keys do not match on-chain details');
69 return;
70 }
72 setKeyfile(compileNetworkingKey(pair, _point, networkRevision));
73 setGenerating(false);
74 }, [
75 networkRevision,
76 manualNetworkSeed,
77 urbitWallet,
78 wallet,
79 authMnemonic,
80 _details,
81 _point,
82 ]);
84 const download = useCallback(() => {
85 saveAs(
86 new Blob([keyfile], {
87 type: 'text/plain;charset=utf-8',
88 }),
89 `${ob.patp(_point).slice(1)}-${networkRevision}.key`
90 // TODO: ^ unifiy "remove tilde" calls
91 );
92 setDownloaded(true);
93 }, [_point, keyfile, networkRevision]);
95 useEffect(() => {
96 generate();
97 }, [generate]);
99 const values = {
100 generating,
101 available,
102 downloaded,
103 download,
104 };
106 return { ...values, bind: values };