@@ -0,0 +1,165 @@
1+import { useCallback, useEffect, useState } from 'react';
2+import { Just } from 'folktale/maybe';
4+import { useNetwork } from 'store/network';
5+import { useWallet } from 'store/wallet';
9+ sendSignedTransaction,
10+ waitForTransactionConfirm,
13+import * as need from './need';
14+import { toHex, toWei, fromWei } from 'web3-utils';
18+ GENERATED: 'GENERATED',
20+ BROADCASTED: 'BROADCASTED',
21+ CONFIRMED: 'CONFIRMED',
25+ * manage the state around sending and confirming an ethereum transaction
26+ * @param {Maybe<EthereumTx>} unsignedTx
27+ * @param {number} initialGasLimit
29+export default function useEthereumTransaction(
33+ const { wallet, walletType, walletHdPath } = useWallet();
34+ const { web3, networkType } = useNetwork();
35+ const _web3 = need.web3(web3);
36+ const _wallet = need.wallet(wallet);
38+ const [error, setError] = useState();
39+ const [state, setState] = useState(STATE.NONE);
40+ const [chainId, setChainId] = useState();
41+ const [nonce, setNonce] = useState();
42+ const [gasPrice, setGasPrice] = useState(20); // gwei
43+ const [gasLimit] = useState(initialGasLimit);
44+ const [unsignedTransaction, setUnsignedTransaction] = useState();
45+ const [signedTransaction, setSignedTransaction] = useState();
47+ const initializing = nonce === undefined || chainId === undefined;
48+ const constructed = Just.hasInstance(unsignedTx);
49+ const generated = state === STATE.GENERATED;
50+ const signed = state === STATE.SIGNED;
51+ const broadcasted = state === STATE.BROADCASTED;
52+ const confirmed = state === STATE.CONFIRMED;
54+ const generate = useCallback(() => {
55+ const txn = unsignedTx.value;
57+ txn.gas = toHex(gasLimit);
58+ txn.gasPrice = toHex(toWei(gasPrice, 'gwei'));
60+ setUnsignedTransaction(txn);
61+ setState(STATE.GENERATED);
65+ }, [gasLimit, gasPrice, unsignedTx.value]);
67+ const sign = useCallback(async () => {
69+ // TODO: sign the transaction
70+ const txn = await signTransaction(
73+ walletHdPath.getOrElse(''),
78+ const stx = hexify(txn.serialize());
80+ setSignedTransaction(stx);
81+ setState(STATE.SIGNED);
94+ const waitForConfirmation = useCallback(
97+ await waitForTransactionConfirm(_web3, txHash);
98+ setState(STATE.CONFIRMED);
106+ const broadcast = useCallback(async () => {
108+ const txHash = await sendSignedTransaction(_web3, signedTransaction);
110+ setState(STATE.BROADCASTED);
111+ waitForConfirmation(txHash);
115+ }, [_web3, signedTransaction, waitForConfirmation]);
117+ const reset = useCallback(() => {
118+ setState(STATE.NONE);
119+ setError(undefined);
121+ setSignedTransaction(undefined);
127+ const [nonce, chainId, estimatedGasPrice] = await Promise.all([
128+ _web3.eth.getTransactionCount(_wallet.address),
129+ _web3.eth.net.getId(),
130+ _web3.eth.getGasPrice(),
134+ setChainId(chainId);
135+ setGasPrice(fromWei(estimatedGasPrice, 'gwei'));
140+ }, [_wallet.address, _web3.eth]);