How to listen to events on a smart contract using ethers.js and contract.on() in node.js

So there was a question in the community that was asked about listening to events on smart contracts.

There are a few things you need.

  • An Alchemy or Infura websocket url
  • The ABI for the contract to listen to
  • The Address of the contract

Once we have those we’re able to get started.

I’m more recently leaning towards Hardhat so we’ll use npx hardhat

Say yes to everything, just like in real life.

In this example I’m going to use Tether (USDT). So we head over to Etherscan to find the contract Address, which is here.

We’ll also need to copy the ABI which can be found here.

Once you have an Alchemy account or Infura, you’ll need to create a new project and grab the websocket URL that they provide you for Ethereum Mainnet.

Then we’ll head back to the code editor, create a JSON file for our ABI code. Paste it in then we’ll go to the scripts file.

We’ll need to import Ethers and the ABI that we just saved.

Inside the async function that should be there already because of Hardhat.

We assign the Tether contract address to a variable, create a provider using ethers and our websocket url and then we’ll create a pointer to our contract.

We’ll then use the contract.on method.

We can choose which event we wish to listen to, for this example we’ll use Transfer.

There aren’t many to choose from on the Tether contract aside from Approval. We can see that the Transfer event takes some params, we’ll need these in our node.js file.

Something to note here is that most ERC20 contracts have 18 decimal places, but Tether uses 6, so when we convert the value that’s being transferred, we can use ethers util method to formatUnits and pass in 6 as the decimal place.

Run this function and wait for a few moments for the data to populate.

You’ll get the details of the event as well as the transaction hash to prove that you’re seeing the right data.

const ethers = require("ethers");
const usdtABI = require("../abis/usdt.json");
async function main() {
  const usdtAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
  const provider = new ethers.providers.WebSocketProvider(
  const contract = new ethers.Contract(usdtAddress, usdtABI, provider);
  contract.on("Transfer", (from, to, value, event) => {
    let info = {
      from: from,
      to: to,
      value: ethers.utils.formatUnits(value, 6),
      data: event,
    console.log(JSON.stringify(info, null, 4));