on 703ff86 help sign in
bridge/src/lib/useReticketL2Spawn.ts
136 lines 3.7 kB history raw
1import { EthAddress, Ship } from '@urbit/roller-api';
2import { useCallback } from 'react';
3import Web3 from 'web3';
4import { INITIAL_NETWORK_KEY_REVISION } from './constants';
5import { reticketPointBetweenWallets } from './reticket';
6import BridgeWallet from './types/BridgeWallet';
7import { ReticketProgressCallback } from './types/L2Transaction';
8import useRoller from './useRoller';
9import { registerProxyAddress } from './utils/roller';
10import { useWallet } from 'store/wallet';
11import { useWalletConnect } from './useWalletConnect';
12import { ITxData } from './types/ITxData';
14interface ReticketL2SpawnParams {
15 fromWallet: BridgeWallet;
16 fromWalletType: symbol;
17 fromWalletHdPath: string;
18 toWallet: UrbitWallet;
19 point: Ship;
20 web3: Web3;
21 contracts: any; // azimuth contracts
22 networkType: symbol;
23 onUpdate?: ReticketProgressCallback;
24 transferEth?: boolean;
25 nextRevision: number;
26 to: EthAddress;
27 txnSigner?: ({
28 from,
29 to,
30 gas,
31 gasPrice,
32 value,
33 data,
34 nonce,
35 }: ITxData) => Promise<string>;
36 txnSender?: ({
37 from,
38 to,
39 gas,
40 gasPrice,
41 value,
42 data,
43 nonce,
44 }: ITxData) => Promise<string>;
47/**
48 * This hook is used to reticket points that are still on L1 but have the
49 * spawn set to L2. It first performs 3-4 L1 transactions (set keys, set
50 * management / voting proxy, and transfer).
51 *
52 * It then sets the spawn proxy using an L2 transaction.
53 *
54 * Under the hood, it wraps two existing functions:
55 * `reticketPointBetweenWallets` for L1, and `registerProxyAddress` for L2.
56 *
57 */
58export const useReticketL2Spawn = () => {
59 const { api } = useRoller();
60 const { walletType }: any = useWallet();
61 const { connector, signPersonalMessage, isConnected } = useWalletConnect();
63 const performL2SpawnReticket = useCallback(
64 async ({
65 fromWallet,
66 fromWalletType,
67 fromWalletHdPath,
68 toWallet,
69 point,
70 web3,
71 contracts,
72 networkType,
73 onUpdate,
74 transferEth = false,
75 nextRevision = INITIAL_NETWORK_KEY_REVISION,
76 to,
77 txnSigner,
78 txnSender,
79 }: ReticketL2SpawnParams) => {
80 // call reticketPointBetweenWallets, with isL2Spawn set to true; this will
81 // skip setting the L1 spawn proxy
82 await reticketPointBetweenWallets({
83 fromWallet,
84 fromWalletType,
85 fromWalletHdPath,
86 toWallet,
87 point,
88 web3,
89 contracts,
90 networkType,
91 onUpdate,
92 transferEth,
93 nextRevision,
94 txnSigner,
95 txnSender,
96 doSetSpawnProxy: false,
97 });
99 // instead, set spawn proxy on L2
100 // In most TX sending cases, we would use the fromWallet to sign and send
101 // the TX. However, because we are transferring this point during the
102 // reticket, we will instead sign the final set spawn proxy TX with the
103 // receiving wallet's private key.
105 // `registerProxyAddress` expects a toWallet object shaped like a
106 // BridgeWallet with `address` and `privateKey` properties.
107 const toWalletStub = {
108 address: toWallet.ownership.keys.address,
109 privateKey: Buffer.from(toWallet.ownership.keys.private, 'hex'),
110 };
111 const proxy = 'own';
112 const nonce = await api.getNonce({ ship: point, proxy });
114 await registerProxyAddress(
115 api,
116 toWalletStub,
117 point,
118 proxy,
119 'spawn',
120 nonce,
121 toWallet?.spawn?.keys?.address || to,
122 walletType,
123 web3,
124 connector,
125 isConnected,
126 signPersonalMessage,
127 true
128 );
129 },
130 [api, connector, walletType, isConnected, signPersonalMessage]
131 );
133 return {
134 performL2SpawnReticket,
135 };
136};