Looking for a way to understand success (or failure) for ethereum transaction.

When we execute a contract method (send transaction) we receive it hash. Transaction is added to the block, block is added into chain and waiting for to be mind. It should be mined on one node and on others, success of failure would be clear after consensus stage.

The question is what is the proper way to wait for status of the transaction.

Here is a research on this topic

Polling How can a DApp detect a fork or chain reorganization using web3.js or additional libraries?

External lib https://github.com/barkthins/ether-pudding/blob/master/index.js#L375

Consensus What number of confirmations is considered secure in Ethereum? (why they define 12 as a result of secure transaction? It should 51% of all nodes, isn't it?)

Usage of filter and why it is not right way to go What's the proper way to wait for a transaction to be mined and get the results? Waiting for a transaction to be confirmed

  • When your tx is mined there has been one confirmation of your tx. When the next block is mined there are 2 confirmations. The one after that -> 3 confirmations. By waiting for 12 confs you're ensuring that your tx stays mined because the probability of a chain reorganization occurring is low at that point. Of course, many people are satisfied with just 3-6 confs and don't wait for 12 confs. This is not relevant to the % of nodes. – rohithpr Dec 17 '17 at 11:48
  • Aha! Thank you! Can you please share more info for chain reorganization? It is something new which I totally missed from consideration – Gleichmut Dec 18 '17 at 2:13
  • One more question: how do we measure amount of confirmations? Does it amount of transactions into logs property? – Gleichmut Dec 18 '17 at 8:04

Made a npm module called await-transaction-mined for this specific problem.

const awaitTransactionMined = require ('await-transaction-mined');
(async function() {
   var txHash = '0x6ee5d58c314d183f3ca70e2292b39dca5ae46141fe4e6b1da5b106dd506e589a';
   const minedTxReceipt = await awaitTransactionMined.await(web3, txHash);

It polls the blockchain every 500ms to check if the transaction has been mined. Once mined it returns the transaction receipt.

  • 1
    What version of Web3 did you use for this? getTransaction seems to be broken in 1.2.1. I would also avoid using npm without noting the version since all web3 version are breaking. – ThickMiddleManager Jan 5 '20 at 18:27

I ended up with recursively polling transaction state. Here is a code from one of the answers implemented by Paul S.

awaitBlockConsensus: function(txWeb3, txhash, blockCount, timeout, callback) {
  var startBlock = Number.MAX_SAFE_INTEGER;
  var interval;
  var stateEnum = { start: 1, mined: 2, awaited: 3, confirmed: 4, unconfirmed: 5 };
  var savedTxInfo;
  var attempts = 0;

  var pollState = stateEnum.start;

  var poll = function() {
    if (pollState === stateEnum.start) {
      txWeb3.eth.getTransaction(txhash, function(e, txInfo) {
        if (e || txInfo == null) {
          return; // XXX silently drop errors
        if (txInfo.blockHash != null) {
          startBlock = txInfo.blockNumber;
          savedTxInfo = txInfo;
          pollState = stateEnum.mined;
    else if (pollState == stateEnum.mined) {
        txWeb3.eth.getBlockNumber(function (e, blockNum) {
          if (e) {
            return; // XXX silently drop errors
          console.log("blockNum: ", blockNum);
          if (blockNum >= (blockCount + startBlock)) {
            pollState = stateEnum.awaited;
    else if (pollState == stateEnum.awaited) {
        txWeb3.eth.getTransactionReceipt(txhash, function(e, receipt) {
          if (e || receipt == null) {
            return; // XXX silently drop errors.  TBD callback error?
          // confirm we didn't run out of gas
          // XXX this is where we should be checking a plurality of nodes.  TBD
          if (receipt.gasUsed >= savedTxInfo.gas) {
            pollState = stateEnum.unconfirmed;
            callback(new Error("we ran out of gas, not confirmed!"), null);
          } else {
            pollState = stateEnum.confirmed;
            callback(null, receipt);
    } else {
      throw(new Error("We should never get here, illegal state: " + pollState));

    // note assuming poll interval is 1 second
    if (attempts > timeout) {
      pollState = stateEnum.unconfirmed;
      callback(new Error("Timed out, not confirmed"), null);

  interval = setInterval(poll, 1000);

I don't know what do you mean by "proper" way, but if you mean "that is the best way to check for transaction completion in a programmatic manner" , I would say:

use the EtherScan API: https://etherscan.io/apis

It is easy, and it is reliable, and a lot of people use it

  • Thanks! I will check it out and accept reply if it is what I am looking for – Gleichmut Dec 18 '17 at 2:19
  • 1
    Hm, the issue with it would not work on private network. My current system deployed locally, I can not use etherscan in this case – Gleichmut Dec 18 '17 at 3:08
  • Etherscan is a centralized solution. It's definitely not a proper design pattern for a dapp. – ThickMiddleManager Jan 5 '20 at 18:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.