on f660f7b help sign in
bridge/src/lib/useKeyfileGenerator.js
97 lines 2.6 kB history raw
1import { useCallback, useState } from 'react';
2import saveAs from 'file-saver';
3import * as ob from 'urbit-ob';
5import { usePointCache } from 'store/pointCache';
6import { useWallet } from 'store/wallet';
8import * as need from 'lib/need';
10import {
11 attemptNetworkSeedDerivation,
12 keysMatchChain,
13 deriveNetworkKeys,
14 compileNetworkingKey,
15} from './keys';
16import usePermissionsForPoint from './usePermissionsForPoint';
18export default function useKeyfileGenerator(point) {
19 const { getDetails, getOptimisticDetails } = usePointCache();
20 const { urbitWallet, wallet, authMnemonic } = useWallet();
22 const [generating, setGenerating] = useState(false);
23 const [keyfile, setKeyfile] = useState();
25 const details = need.details(getDetails(point));
26 const optimisticDetails = getOptimisticDetails(point);
28 // use the optimistic key revision number if available
29 // (because we may have set networking keys earlier)
30 const networkRevision = optimisticDetails.keyRevisionNumber.matchWith({
31 Nothing: () => parseInt(details.keyRevisionNumber, 10),
32 Just: p => p.value,
33 });
35 const { isOwner, isManagementProxy } = usePermissionsForPoint(point);
36 const hasNetworkingKeys = networkRevision > 0;
37 const available = (isOwner || isManagementProxy) && hasNetworkingKeys;
39 const generate = useCallback(async () => {
40 setGenerating(true);
42 const networkSeed = await attemptNetworkSeedDerivation({
43 urbitWallet,
44 wallet,
45 authMnemonic,
46 details,
47 revision: networkRevision,
48 });
50 const _networkSeed = need.value(networkSeed, () => {
51 setGenerating(false);
52 throw new Error('Could not derive networking seed.');
53 });
55 const pair = deriveNetworkKeys(_networkSeed);
57 if (!keysMatchChain(pair, details)) {
58 setGenerating(false);
59 throw new Error(
60 'Derived networking keys do not match public keys on chain.'
61 );
62 }
64 setKeyfile(compileNetworkingKey(pair, point, networkRevision));
65 setGenerating(false);
66 }, [
67 setGenerating,
68 setKeyfile,
69 urbitWallet,
70 wallet,
71 authMnemonic,
72 details,
73 networkRevision,
74 point,
75 ]);
77 const download = useCallback(() => {
78 saveAs(
79 new Blob([keyfile], {
80 type: 'text/plain;charset=utf-8',
81 }),
82 `${ob.patp(point).slice(1)}-${networkRevision}.key`
83 // TODO: ^ unifiy "remove tilde" calls
84 );
85 }, [point, keyfile, networkRevision]);
87 const generateAndDownload = useCallback(async () => {
88 await generate();
89 download();
90 }, [generate, download]);
92 return {
93 generating,
94 available,
95 generateAndDownload,
96 };