![[Ethereum] How to send multiple transactions programmatically [Ethereum] How to send multiple transactions programmatically](https://mr-v.fi/wp-content/uploads/2019/05/3bt7zeQH-1024x576.jpg)
[Ethereum] How to send multiple transactions programmatically
If you wanna create your own cryptocurrency trading platform, you will face a challenge which is how to control the hot wallet to send out the token even the gas.
The real problem is that you cannot deliver the ETH immediately, the transaction will pending for a while. but you will send many transactions at the same time, so you have to control the nonce.
Some people say you can call the eth.getTransactionCount() method to get the latest nonce, but it won’t be work, the method only returns the nonce which has been mined by blockchain, the pending transactions are still queued at your local node.
Here are some solutions to solve this problem, and I choose to control the nonce by batch style.
Solutions:
A smart contract is a straightforward way to reduce a transaction from many sender nonces to few sender nonces. Write a contract that sends all your different transactions, then send the budget to that contract. This is a relatively high cost (in terms of time/effort/expertise) way to solve the problem.
Just do it anyway, batch style. When I’ve had to send many transactions manually, I’ve batched them in to sets of 10 or so and gone for it. Incrementing the nonce manually each time (because the transaction is usually not on the network yet) and then waiting sufficiently long for all the transactions to confirm. Don’t rely on pending transactions on Etherscan or similar to determine whether this is working, as things often vanish unpredictably from this level. Never reuse a nonce for a different transaction that isn’t a 0ing high gas transaction – you will screw it up and you’ll end up sending the same transaction twice by mistake.
Serialize. One-by-one you post a transaction, wait for it to confirm, increment your nonce. This is probably the best of the easy-to-implement automated solutions. It will not fail. It might buffer forever if you have a constant stream of transactions. It also assures you can never have more than one transaction per block, limiting your throughput to 4 a minute or so.
Fire and retry. This is a little sketchy because it involves reusing nonces for different transactions. Send all (or some large batch) of your transactions to the network. If any fail, restart from the failure nonce and send again. There’s possibly a more intelligent solution where you just try to swap out the missing nonce. You’ll need to be very careful you never send a transaction that is secretly in the pending-but-not-visible pool.
New address for every transaction. A buffering step of distributing funds to your own addresses ensures you never screw it up for other people. It does double your transaction time and cost though.
Now, we are going to control the nonce by the batch style step by step.
1. Store the row into the database, it would be like this.
{“from”:”0xdbad0057efa8f6a7a6628efefc4e6a9f7bb1fd69″,”gas”:”0xea60″,”gasPrice”:”0x1a13b8600″,”to”:”0x330c31e8f2b14de86d24e9da7483bad4f99b8e37″,”value”:”0x0″,”data”:”0xa9059cbb00000000000000000000000009709f60c98a829fed34134a480ded37cb6083b20000000000000000000000000000000000000000000000000000000000989680″,”chainId”:3}
2. Set the number of concurrency of send token queue to 10, ensuring that only 10 nones are in the queue allocation. (if send the transaction fail, we just have to trace 10 records, resend them manually)
3. start the send token queue, this queue is responsible for reading the transaction row to be sent from the database.
4. Assigned new nonce (nonce ++) to this transaction row, use the web3.eth.sendSignedTransaction() to send this transaction, store the transaction hash after returns.
{“from”:”0xdbad0057efa8f6a7a6628efefc4e6a9f7bb1fd69″,”gas”:”0xea60″,”gasPrice”:”0x1a13b8600″,”to”:”0x330c31e8f2b14de86d24e9da7483bad4f99b8e37″,”value”:”0x0″,”data”:”0xa9059cbb00000000000000000000000009709f60c98a829fed34134a480ded37cb6083b20000000000000000000000000000000000000000000000000000000000989680″,”chainId”:3, “nonce”: 1}
5. get above transactions from database and store to check transaction queue
6. now we can check the status of the transaction by web3.eth.getTransactionReceipt(), if returns true, then going to the next step. if false, just keep this queue to check status till success.
7. after checking the transaction has been sent successfully, now you can update the user wallet amount, no matter increase or decrease.
8. if something wrong, add a script to increase the gas for the specified transaction row and resend it.
If you got any problem or some suggestions, please leave a message below
References:
- sendSignedTransaction错误情况
- How to reliably send signed transactions programmatically?
- 有关以太坊nonce问题
- ETH开发实践——批量发送交易
- 基于区块链的 Dapp 开发笔记(1)-如何解决以太坊中的 nounce 冲突问题
