Clap your hands (or just give me a clap!) if you’re building a dapp for Ethereum and you’re annoyed by the tooling around it. Geth is a pain to setup, INFURA is down more often than it’s up, the gas prices sometimes get crazy, and Web3.js doesn’t always work as its documentation states that it should.

Like having multiple transactions out at once.

I’ve had transactions pending in the blockchain for 4+ hours. When that happens, web3 should be able to queue up another pending tx, but it can’t. The problem is with the nonce.

I use web3.eth.sendTransaction to send transactions, and according to the web3 documentation website:

web3.eth.sendTransaction:

nonce: Number - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.

This should be an optional parameter to overwrite your own pending tx’s. And if you don’t give nonce as a parameter, web3.eth.sendTransaction should auto increment your nonce. For those who aren’t familiar with the term, nonce is basically your transaction count, the number of transactions you’ve done. Your first transaction will start with nonce 0 and increment.

The problem is: when you have a pending transaction out, the nonce doesn’t auto increment correctly. It increments from your previous transaction so then it tries to send a transaction with the same nonce as the current pending transaction.

Solution

So there’s a couple solutions to this issue. The easy way, but not entirely ideal is that you can keep track of the nonce into a database. If a user makes a transaction, send over the nonce of the transaction and keep track of the nonce yourself. This solution is super simple, but it comes with a couple issues: it’s not entirely decentralized and your transaction can drop (not processed by the blockchain and lost in memory). When your transaction drops, your nonce count will be off and then you won’t be able to make any more transactions.

The better way is to store each transaction for each user. Because each transaction is public anyways, we could get the last transaction from the user through the blockchain, but for ease of use, we’ll just store the transaction hashes for each user in a db.

Then to get the correct nonce, all we need to do is check the nonce of that last transaction, and then increment it.

var lastTxHash = await getLatestTx(ethereumAddress); if (lastTxHash) { var tx = web3.eth.getTransaction(lastTxHash); var txCount = web3.eth.getTransactionCount(ethereumAddress); if (tx) { nonce = txCount > (tx.nonce + 1) ? txCount + 1 : tx.nonce + 1; } else if (txCount === 0) { nonce = 0; } else { nonce = txCount + 1; } } else { nonce = web3.eth.getTransactionCount(ethereumAddress); }

We get the latest tx from the user. If it doesn’t exist, then we can just use web3 to get the number of transactions they have (probably 0).

Then we get the transaction object for the last transaction with web3.eth.getTransaction(lastTxHash) and the transaction count with web3.eth.getTransactionCount(ethereumAddress) .

We compare the nonce with the txCount, and if txCount is more than the previous nonce + 1, then we use the txCount as the nonce, otherwise we take previous nonce + 1. This will almost never happen, but if our database gets out of sync in anyway, our transactions won’t fail with the wrong nonce.

multiple pending transactions from our dapp


Boom. Now you don’t have to live in the stone ages & limit your users to just one transaction. Have as many tx’s as you please :).