on e7c1371 help sign in
bridge/src/lib/useEthereumTransaction.js
177 lines 4.2 kB history raw
1import { useCallback, useEffect, useState } from 'react';
3import { useNetwork } from 'store/network';
4import { useWallet } from 'store/wallet';
6import {
7 signTransaction,
8 sendSignedTransaction,
9 waitForTransactionConfirm,
10} from './txn';
11import * as need from './need';
12import { fromWei } from 'web3-utils';
14const STATE = {
15 NONE: 'NONE',
16 SIGNED: 'SIGNED',
17 BROADCASTED: 'BROADCASTED',
18 CONFIRMED: 'CONFIRMED',
19};
21/**
22 * manage the state around sending and confirming an ethereum transaction
23 * @param {number} initialGasLimit
24 */
25export default function useEthereumTransaction(initialGasLimit = 0) {
26 const { wallet, walletType, walletHdPath } = useWallet();
27 const { web3, networkType } = useNetwork();
28 const _web3 = need.web3(web3);
29 const _wallet = need.wallet(wallet);
31 const [error, _setError] = useState();
32 const setError = useCallback(
33 error => {
34 _setError(error);
35 if (error) {
36 console.error(error);
37 }
38 },
39 [_setError]
40 );
41 const [state, setState] = useState(STATE.NONE);
42 const [chainId, setChainId] = useState();
43 const [nonce, setNonce] = useState();
44 const [gasPrice, setGasPrice] = useState(20); // gwei
45 const [gasLimit] = useState(initialGasLimit);
46 const [unsignedTransaction, setUnsignedTransaction] = useState();
47 const [signedTransaction, setSignedTransaction] = useState();
48 const [txHash, setTxHash] = useState();
50 const initializing = nonce === undefined || chainId === undefined;
51 const constructed = !!unsignedTransaction;
52 const signed = state === STATE.SIGNED;
53 const broadcasted = state === STATE.BROADCASTED;
54 const confirmed = state === STATE.CONFIRMED;
56 const inputsLocked = signed || broadcasted || confirmed;
58 const canSign = !initializing && constructed;
60 const construct = useCallback(txn => setUnsignedTransaction(txn), [
61 setUnsignedTransaction,
62 ]);
64 const generateAndSign = useCallback(async () => {
65 try {
66 setError(undefined);
68 const txn = await signTransaction({
69 wallet: _wallet,
70 walletType,
71 walletHdPath,
72 networkType,
73 txn: unsignedTransaction,
74 nonce,
75 chainId,
76 gasPrice: gasPrice.toFixed(0),
77 gasLimit,
78 });
80 setSignedTransaction(txn);
81 setState(STATE.SIGNED);
82 } catch (error) {
83 setError(error);
84 }
85 }, [
86 _wallet,
87 chainId,
88 gasLimit,
89 gasPrice,
90 networkType,
91 nonce,
92 setError,
93 unsignedTransaction,
94 walletHdPath,
95 walletType,
96 ]);
98 const broadcast = useCallback(async () => {
99 try {
100 setError(undefined);
101 const txHash = await sendSignedTransaction(
102 _web3,
103 signedTransaction,
104 /* doubtNonceError */ false
105 );
107 setState(STATE.BROADCASTED);
108 setTxHash(txHash);
110 await waitForTransactionConfirm(_web3, txHash);
112 setState(STATE.CONFIRMED);
113 } catch (error) {
114 setError(error);
115 }
116 }, [_web3, setError, signedTransaction]);
118 const reset = useCallback(() => {
119 setState(STATE.NONE);
120 setError(undefined);
121 setGasPrice(0);
122 setSignedTransaction(undefined);
123 }, [setError]);
125 useEffect(() => {
126 (async () => {
127 try {
128 setError(undefined);
129 const [nonce, chainId, estimatedGasPrice] = await Promise.all([
130 _web3.eth.getTransactionCount(_wallet.address),
131 _web3.eth.net.getId(),
132 _web3.eth.getGasPrice(),
133 ]);
135 setNonce(nonce);
136 setChainId(chainId);
137 setGasPrice(parseInt(fromWei(estimatedGasPrice, 'gwei'), 10));
138 } catch (error) {
139 setError(error);
140 }
141 })();
142 }, [_wallet.address, _web3.eth, setError]);
144 return {
145 initializing,
146 construct,
147 constructed,
148 canSign,
149 generateAndSign,
150 signed,
151 broadcast,
152 broadcasted,
153 confirmed,
154 reset,
155 error,
156 inputsLocked,
157 txHash,
158 signedTransaction,
159 bind: {
160 constructed,
161 canSign,
162 generateAndSign,
163 signed,
164 broadcast,
165 broadcasted,
166 confirmed,
167 reset,
168 error,
169 gasPrice,
170 setGasPrice,
171 txHash,
172 nonce,
173 chainId,
174 signedTransaction,
175 },
176 };