@@ -66,14 +66,14 @@ export default function useEthereumTransaction(
6666 const [nonce, setNonce] = useState();
6767 const { gasPrice, setGasPrice, resetGasPrice } = useGasPrice(initialGasPrice);
6868 const [gasLimit] = useState(initialGasLimit);
69− const [unsignedTransaction, setUnsignedTransaction] = useState();
70− const [signedTransaction, setSignedTransaction] = useState();
71− const [txHash, setTxHash] = useState();
69+ const [unsignedTransactions, setUnsignedTransactions] = useState();
70+ const [signedTransactions, setSignedTransactions] = useState();
71+ const [txHashes, setTxHashes] = useState();
7272 const [needFunds, setNeedFunds] = useState();
7373 const [confirmationProgress, setConfirmationProgress] = useState(0.0);
7474
7575 const initializing = nonce === undefined || chainId === undefined;
76− const constructed = !!unsignedTransaction;
76+ const constructed = !!unsignedTransactions;
7777 const isDefaultState = state === STATE.NONE;
7878 const signed = state === STATE.SIGNED;
7979 const broadcasted = state === STATE.BROADCASTED;
@@ -88,31 +88,39 @@ export default function useEthereumTransaction(
8888
8989 const construct = useCallback(
9090 async (...args) =>
91− setUnsignedTransaction(await transactionBuilder(...args)),
91+ setUnsignedTransactions(await transactionBuilder(...args)),
9292 [transactionBuilder]
9393 );
9494
95− const unconstruct = useCallback(() => setUnsignedTransaction(undefined), [
96− setUnsignedTransaction,
95+ const unconstruct = useCallback(() => setUnsignedTransactions(undefined), [
96+ setUnsignedTransactions,
9797 ]);
9898
9999 const generateAndSign = useCallback(async () => {
100100 try {
101101 setError(undefined);
102102
103− const txn = await signTransaction({
104− wallet: _wallet,
105− walletType,
106− walletHdPath,
107− networkType,
108− txn: unsignedTransaction,
109− nonce,
110− chainId,
111− gasPrice: gasPrice.toFixed(0),
112− gasLimit,
113− });
114−
115− setSignedTransaction(txn);
103+ const utxs = Array.isArray(unsignedTransactions)
104+ ? unsignedTransactions
105+ : [unsignedTransactions];
106+
107+ const txns = await Promise.all(
108+ utxs.map((utx, i) =>
109+ signTransaction({
110+ wallet: _wallet,
111+ walletType,
112+ walletHdPath,
113+ networkType,
114+ txn: utx,
115+ nonce: nonce + i,
116+ chainId,
117+ gasPrice: gasPrice.toFixed(0),
118+ gasLimit,
119+ })
120+ )
121+ );
122+
123+ setSignedTransactions(txns);
116124 setState(STATE.SIGNED);
117125 } catch (error) {
118126 setError(error);
@@ -125,7 +133,7 @@ export default function useEthereumTransaction(
125133 networkType,
126134 nonce,
127135 setError,
128− unsignedTransaction,
136+ unsignedTransactions,
129137 walletHdPath,
130138 walletType,
131139 ]);
@@ -135,10 +143,12 @@ export default function useEthereumTransaction(
135143 setConfirmationProgress(0.0);
136144 setError(undefined);
137145
138− const rawTx = hexify(signedTransaction.serialize());
139− const costGwei = toBN(gasLimit).mul(toBN(gasPrice));
140− const cost = toWei(costGwei.toString(), 'gwei');
146+ const rawTxs = signedTransactions.map(stx => hexify(stx.serialize()));
141147
148+ const costGwei = toBN(gasLimit)
149+ .mul(toBN(gasPrice))
150+ .mul(toBN(rawTxs.length));
151+ const cost = toWei(costGwei.toString(), 'gwei');
142152 let usedTank = false;
143153 // if this ethereum transaction is being executed by a specific point
144154 // see if we can use the tank
@@ -148,27 +158,35 @@ export default function useEthereumTransaction(
148158 pointCursor.value,
149159 _wallet.address,
150160 cost,
151− [rawTx],
161+ rawTxs,
152162 (address, minBalance, balance) =>
153163 setNeedFunds({ address, minBalance, balance }),
154164 () => setNeedFunds(undefined)
155165 );
156166 }
157167
158− const txHash = await sendSignedTransaction(
159− _web3,
160− signedTransaction,
161− /* doubtNonceError */ usedTank
168+ const txHashes = await signedTransactions.reduce(
169+ (acc, stx) =>
170+ acc.then(hashes =>
171+ sendSignedTransaction(
172+ _web3,
173+ stx,
174+ /* doubtNonceError */ usedTank
175+ ).then(hash => [...hashes, hash])
176+ ),
177+ Promise.resolve([])
162178 );
163179
180+ setTxHashes(txHashes);
164181 setState(STATE.BROADCASTED);
165− setTxHash(txHash);
166182
167183 await timeout(PROGRESS_ANIMATION_DELAY_MS);
168184
169185 setConfirmationProgress(0.2);
170186
171− await waitForTransactionConfirm(_web3, txHash);
187+ await Promise.all(
188+ txHashes.map(txHash => waitForTransactionConfirm(_web3, txHash))
189+ );
172190
173191 setConfirmationProgress(0.9);
174192
@@ -183,12 +201,12 @@ export default function useEthereumTransaction(
183201 gasPrice,
184202 pointCursor,
185203 setError,
186− signedTransaction,
204+ signedTransactions,
187205 ]);
188206
189207 const reset = useCallback(() => {
190− setTxHash(undefined);
191− setSignedTransaction(undefined);
208+ setTxHashes(undefined);
209+ setSignedTransactions(undefined);
192210 setNonce(undefined);
193211 setChainId(undefined);
194212 resetGasPrice();
@@ -283,8 +301,8 @@ export default function useEthereumTransaction(
283301 error,
284302 inputsLocked,
285303 confirmationProgress,
286− txHash,
287− signedTransaction,
304+ txHashes,
305+ signedTransactions,
288306 gasPrice,
289307 setGasPrice,
290308 resetGasPrice,