For the accounts maintained by geth, we don't need to worry about the transaction nonce because geth can add the correct nonce to the transactions and sign them. While using accounts that aren't managed by geth, we need to calculate the nonce ourselves.
To calculate the nonce ourselves, we can use the getTransactionCount method provided by geth. The first argument should be the address whose transaction count we need and the second argument is the block until we need the transaction count. We can provide the "pending" string as the block to include transactions from the block that's currently being mined. As we discussed in an earlier chapter, geth maintains a transaction pool in which it keeps pending and queued transactions. To mine a block, geth takes the pending transactions from the transaction pool and starts mining the new block. Until the block is not mined, the pending transactions remain in the transaction pool and once mined, the mined transactions are removed from the transaction pool. The new incoming transactions received while a block is being mined are put in the transaction pool and are mined in the next block. So when we provide "pending" as the second argument while calling getTransactionCount, it doesn't look inside the transaction pool; instead, it just considers the transactions in the pending block.
So if you are trying to send transactions from accounts not managed by geth, then count the total number of transactions of the account in the blockchain and add it with the transactions pending in the transaction pool. If you try to use pending transactions from the pending block, then you will fail to get the correct nonce if transactions are sent to geth within a few seconds of the interval because it takes 12 seconds on average to include a transaction in the blockchain.
In the previous chapter, we relied on the hooked-web3-provider to add nonce to the transaction. Unfortunately, the hooked-web3-provider doesn't try to get the nonce the correct way. It maintains a counter for every account and increments it every time you send a transaction from that account. And if the transaction is invalid (for example, if the transaction is trying to send more ether than it has), then it doesn't decrement the counter. Therefore, the rest of the transactions from that account will be queued and never be mined until the hooked-web3-provider is reset, that is, the client is restarted. And if you create multiple instances of the hooked-web3-provider, then these instances cannot sync the nonce of an account with each other, so you may end up with the incorrect nonce. But before you add the nonce to the transaction, the hooked-web3-provider always gets the transaction count until the pending block and compares it with its counter and uses whichever is greater. So if the transaction from an account managed by the hooked-web3-provider is sent from another node in the network and is included in the pending block, then the hooked-web3-provider can see it. But the overall hooked-web3-provider cannot be relied on to calculate the nonce. It's great for quick prototyping of client-side apps and is fit to use in apps where the user can see and resend transactions if they aren't broadcasted to the network and the hooked-web3-provider is reset frequently. For example, in our wallet service, the user will frequently load the page, so a new hooked-web3-provider instance is created frequently. And if the transaction is not broadcasted, not valid, or not mined, then the user can refresh the page and resend transactions.