[Ethereum] How to get transactions by account using web3 js

nodejstransactionsweb3js

I'm sure this question was asked before, but I did not find any result that helped my problem.

How can I get the transactions (in and out) for a given account? I use nodejs and web3?

With this line I get the number of sent transactions:

web3.eth.getTransactionCount(accounts[i])

So at least web3 should know something about the account activity.

Is there an easy way to get the transactions of my accounts? Or did I miss something about it? Do I have to crawl the entire blockchain, block by block, to get my transactions?

Best Answer

Simple transactions are not indexed. So you either need to iterate over all the blocks, use some kind of an off-chain index (e.g. etherscan.io), or build one up yourself and use it.

For example, you can use this heuristic approach without having to process the entire chain

var myAddr = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413';
var currentBlock = eth.blockNumber;
var n = eth.getTransactionCount(myAddr, currentBlock);
var bal = eth.getBalance(myAddr, currentBlock);
for (var i=currentBlock; i >= 0 && (n > 0 || bal > 0); --i) {
    try {
        var block = eth.getBlock(i, true);
        if (block && block.transactions) {
            block.transactions.forEach(function(e) {
                if (myAddr == e.from) {
                    if (e.from != e.to)
                        bal = bal.plus(e.value);
                    console.log(i, e.from, e.to, e.value.toString(10));
                    --n;
                }
                if (myAddr == e.to) {
                    if (e.from != e.to)
                        bal = bal.minus(e.value);
                    console.log(i, e.from, e.to, e.value.toString(10));
                }
            });
        }
    } catch (e) { console.error("Error in block " + i, e); }
}

How does it work?

Using the available information about the current state (number of "from" transactions and the current balance), it goes back in time until at least so many "from" transactions have been found, and then continues going back until the balance reaches 0.

The inherent limitation is that 0-value transactions before the account was funded will not be found.


Contract events on the other hand, are indexed. So if you're developing a smart contract, you can make use of that.
Using web3 1.0.0 API:

web3.eth.getPastLogs({fromBlock:'0x0',address:'0x9e3319636e2126e3c0bc9e3134AEC5e1508A46c7'})
.then(res => {
  res.forEach(rec => {
    console.log(rec.blockNumber, rec.transactionHash, rec.topics);
  });
}).catch(err => console.log("getPastLogs failed", err));

Or via JSON RPC eth_getLogs.

Related Topic