DEV Community

Cover image for How to monitor ETH Transactions using Web3.js
Mihai-Adrian Andrei
Mihai-Adrian Andrei

Posted on

How to monitor ETH Transactions using Web3.js

In order to monitor ETH transactions, we need an Ethereum node. We can use one provided by Infura for free. You just need to sign up on Infura and create a new project.

Infura create project

From the project settings, we get a http provider:

  • ex: https://ropsten.infura.io/v3/775214aeabb642a5b93e138293d83a1e

You will need to change 775214aeabb642a5b93e138293d83a1e with your project id.

Project Settings

Don't worry, I deleted the project so the keys from the picture will not work 😀. Get your own keys.

Now, let's install web3 and node-cron with the following command:

npm install web3
npm install node-cron
Enter fullscreen mode Exit fullscreen mode

Monitor Ethereum class

After that, create a file monitor.js and paste the following code:

const Web3 = require("web3");

class MonitorEth {
  constructor(httpProvider) {
    this.web3 = new Web3(new Web3.providers.HttpProvider(httpProvider));
    this.lastSyncedBlock = null;
  }

  async initializeLastSyncedBlock() {
    this.lastSyncedBlock = await this.getLastBlockNumber();
  }

  async getBlock(blockNumber) {
    return this.web3.eth.getBlock(blockNumber, true);
  }

  async getLastBlockNumber() {
    return this.web3.eth.getBlockNumber();
  }

  async searchTransaction(to) {
    const lastBlock = await this.getLastBlockNumber();
    console.log(`Searching blocks: ${this.lastSyncedBlock + 1} - ${lastBlock}`);

    for (
      let blockNumber = this.lastSyncedBlock + 1;
      blockNumber < lastBlock;
      blockNumber++
    ) {
      const block = await this.getBlock(blockNumber);

      if (!block?.transactions) {
        continue;
      }
      for (const tx of block.transactions) {
        if (!tx?.to) {
          continue;
        }
        if (tx.to.toLowerCase() === to.toLowerCase()) {
          console.log(tx);
        }
      }
    }
    this.lastSyncedBlock = lastBlock;
    console.log(
      `Finished searching blocks: ${this.lastSyncedBlock + 1} - ${lastBlock}`
    );
  }
}

module.exports = MonitorEth;

Enter fullscreen mode Exit fullscreen mode

In the constructor, we create our Web3 instance in order to interact with the Ethereum chain. Also, we created a method that will initialize our app and will save the last block number that we scanned. ( Probably, you will save this in your database in order to not lose it if your app goes down ).

After that, we created 2 methods that we need in order to get more information from the chain:

  • getLastBlockNumber -> Will fetch the number of the last block mined.
  • getBlock -> Will fetch the block information from the node and it will contain all the transactions present in that block.

And at the end, the method searchTransaction. This gets the block data from the chain between our last synced block, and the current last block from the chain, and checks if there is any transaction that matches our to address -> with the following condition: tx.to.toLowerCase() === to.toLowerCase()

Main script

Now, let's create our main script app.js.

First, we need to import node-cron and our monitor class.

const cron = require("node-cron");
const MonitorEth = require("./monitor");
Enter fullscreen mode Exit fullscreen mode

After that, we need our endpoint from Infura and the address that we want to monitor.

const httpProvider =
  "https://ropsten.infura.io/v3/775214aeabb642a5b93e138293d83a1e";
const to = "0xd8588cc99979a961De7f2Ca3532477A4221BFb79";
Enter fullscreen mode Exit fullscreen mode

The last thing we need to do is create an instance of our monitor class, initialize the last block, and create a cron.

const cron = require("node-cron");
const MonitorEth = require("./monitor");

const httpProvider =
  "https://ropsten.infura.io/v3/775214aeabb642a5b93e138293d83a1e";
const to = "0xd8588cc99979a961De7f2Ca3532477A4221BFb79";

async function main() {
  try {
    const monitor = new MonitorEth(httpProvider);
    await monitor.initializeLastSyncedBlock();
    console.log('Looking for transactions...')

    cron.schedule("*/2 * * * *", async () => {
      console.log('Cron started.')
      await monitor.searchTransaction(to);
      console.log('Cron finished.')

    });
  } catch (error) {
    console.log(error);
  }
}

main();
Enter fullscreen mode Exit fullscreen mode

Here, our cron will be fired every 2 minutes. If you want to learn more about cron times, you can check https://crontab.guru/.

After that, you can just start it with node app.js and make a transaction to your to address.

Here it is an example of what it will look like:

$ node app.js 
Looking for transactions...
Cron started.
Searching blocks: 12451460 - 12451563
{
  accessList: [],
  blockHash: '0xb0df4a27e1c77df495a32324650e06e9fa8138c8f9a3910fb3562b4156d5f37c',
  blockNumber: 12451460,
  chainId: '0x3',
  from: '0xeE1D1D01A7a5fCa456006b0458693723E61427f6',
  gas: 21000,
  gasPrice: '227691906143',
  hash: '0xaf96ccf776e47adf8f8724f3222bb9068d5287c9bc50bd69d2bf3fa90e3889c1',
  input: '0x',
  maxFeePerGas: '257616117457',
  maxPriorityFeePerGas: '38800000000',
  nonce: 24,
  r: '0x59946a27e3d0c452843b9780c8072ca17f81bce410430a722013a6a08084d7f9',
  s: '0x4be019582ba83865bbc28790ff26ec767ae2bbcb6e610947ea00ba17d5d01de9',
  to: '0xd8588cc99979a961De7f2Ca3532477A4221BFb79',
  transactionIndex: 2,
  type: 2,
  v: '0x1',
  value: '10000000000000000'
}
Finished searching blocks: 12451564 - 12451563
Cron finished.
Cron started.
Searching blocks: 12451564 - 12451567
Finished searching blocks: 12451568 - 12451567
Cron finished.
Cron started.
Searching blocks: 12451568 - 12451572
Finished searching blocks: 12451573 - 12451572
Cron finished.
Cron started.
Searching blocks: 12451573 - 12451577
Finished searching blocks: 12451578 - 12451577
Cron finished.
Enter fullscreen mode Exit fullscreen mode

In the above example, I made a transaction of 0.01 ETH that you can check here.
As you can see, the value is actually 10000000000000000 because that is in WEI, not ETH. You can find the ETH value by using: https://eth-converter.com/.

And, that's it. Now you can monitor incoming transactions to one of your addresses. 🎉🎉🎉

Top comments (2)

Collapse
 
gonzaloaraujoc profile image
Gonzalo Araújo C

Hello!, I need to know if there's a better way to monitor incoming transactions to a number of Ethereum wallets in my system other than constantly checking all transactions as you propose. Doing this for a few hours uses all credits on my node account. Is there a better way?

There are hundreds of transactions per minute, thousands per hour, hundreds of thousands per day, millions every week, all of this just to check if there's a transaction coming to a monitored address. This is disproportionate in terms of processing, API tokens, and network usage for the purpose. there need to be a better way,-

Collapse
 
legaciespanda profile image
Ernest Obot

Thanks so much for this.