on d317e13 help sign in
bridge/src/lib/useReticketL2Spawn.ts
134 lines 3.6 kB history raw
1import { EthAddress, Ship } from '@urbit/roller-api';
2import { useCallback } from 'react';
3import Web3 from 'web3';
4import { ITxData } from '@walletconnect/types';
5import { INITIAL_NETWORK_KEY_REVISION } from './constants';
6import { reticketPointBetweenWallets } from './reticket';
7import BridgeWallet from './types/BridgeWallet';
8import { ReticketProgressCallback } from './types/L2Transaction';
9import useRoller from './useRoller';
10import { registerProxyAddress } from './utils/roller';
11import { useWallet } from 'store/wallet';
12import { useWalletConnect } from './useWalletConnect';
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 } = 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 true
126 );
127 },
128 [api, connector, walletType]
129 );
131 return {
132 performL2SpawnReticket,
133 };
134};