2

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

3
  • 1
    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, 2017 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, 2017 at 2:13
  • One more question: how do we measure amount of confirmations? Does it amount of transactions into logs property?
    – Gleichmut
    Dec 18, 2017 at 8:04

3 Answers 3

2

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
  • 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. Jan 5, 2020 at 18:27
1

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;
          console.log("mined");
          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
          clearInterval(interval);
          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
    attempts++;
    if (attempts > timeout) {
      clearInterval(interval);
      pollState = stateEnum.unconfirmed;
      callback(new Error("Timed out, not confirmed"), null);
    }
  };

  interval = setInterval(poll, 1000);
  poll();
}
0

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

3
  • Thanks! I will check it out and accept reply if it is what I am looking for
    – Gleichmut
    Dec 18, 2017 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, 2017 at 3:08
  • Etherscan is a centralized solution. It's definitely not a proper design pattern for a dapp. Jan 5, 2020 at 18:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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