Skip to main content

Listening To Web3 Contract Events Using Nestjs Framework

Β· 4 min read
Sivabharathy

Smart contracts are not just static codeβ€”they emit events that can be listened to in real-time, enabling dApps to react immediately to on-chain activity. In a modern backend built with NestJS, listening to Ethereum events using Web3.js is a powerful way to automate workflows, trigger actions, or update state based on blockchain transactions.

In this guide, we’ll walk you through how to:

  • Connect to the Ethereum blockchain with Web3.js
  • Subscribe to smart contract events
  • Cleanly handle connections and disconnections
  • Integrate the event listener into a NestJS service lifecycle

Let’s get started!


πŸ“¦ Prerequisites​

Before diving into the code, make sure you have:

  • A NestJS project set up (@nestjs/cli)
  • An Ethereum WebSocket endpoint (e.g., Infura)
  • Contract ABI and deployed contract address

Install the required package:

npm install web3

πŸš€ Step-by-Step Implementation​

1. Create the Web3Service​

Here's a complete service example that connects to Ethereum via WebSocket and listens to a specific contract event:

// web3.service.ts
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import Web3 from 'web3';
import { Subscription } from 'web3-core-subscriptions';

@Injectable()
export class Web3Service implements OnModuleInit, OnModuleDestroy {
private web3: Web3;
private contract: any;
private eventSubscription: Subscription<any>;

async onModuleInit() {
// Connect to Ethereum node using WebSocket
this.web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_PROJECT_ID');

const abi = [ /* Contract ABI */ ];
const contractAddress = '0xYourContractAddress';

this.contract = new this.web3.eth.Contract(abi, contractAddress);

this.subscribeToEvents();
}

private subscribeToEvents() {
this.eventSubscription = this.contract.events.YourEventName({
fromBlock: 'latest',
})
.on('connected', (subscriptionId) => {
console.log(`Event listener connected: ${subscriptionId}`);
})
.on('data', (event) => {
console.log('Event received:', event.returnValues);
// TODO: Process event (e.g., save to DB, trigger business logic)
})
.on('error', (error) => {
console.error('Event listener error:', error);
// Optionally implement retry or fallback logic here
});
}

async onModuleDestroy() {
if (this.eventSubscription) {
this.eventSubscription.unsubscribe((error, success) => {
if (success) {
console.log('Event subscription successfully unsubscribed.');
} else {
console.error('Error unsubscribing:', error);
}
});
}

// Optional: close WebSocket connection
if (this.web3?.currentProvider && typeof this.web3.currentProvider.disconnect === 'function') {
(this.web3.currentProvider as any).disconnect(1000, 'App shutdown');
console.log('WebSocket disconnected.');
}
}
}

🧠 Key Concepts Explained​

1. OnModuleInit / OnModuleDestroy​

These lifecycle hooks ensure your event listener is started when the service is initialized and properly cleaned up when the app is shut down.

2. WebSocket Connection​

We're using wss://mainnet.infura.io/ws/v3/YOUR_INFURA_PROJECT_ID to connect to Ethereum. WebSockets allow real-time event streaming.

⚠️ Always use WebSocket endpoints for subscriptions. HTTP JSON-RPC does not support event subscriptions.

3. Smart Contract & ABI​

To listen to a smart contract event, you need:

  • The ABI of the contract
  • The deployed contract address
  • The correct event name (case-sensitive)

4. Event Subscription Handling​

  • .on('data') fires every time a new event is emitted.
  • .on('error') is crucial to handle dropped connections or failures.
  • .unsubscribe() ensures memory leaks and dangling connections are avoided.

βœ… Use Cases for Event Listeners​

Here are practical ways you can use Web3 event listeners in a NestJS app:

  • Real-time dashboards: Update frontend UI based on blockchain activity
  • Notifications: Send SMS/Email when specific events happen on-chain
  • Analytics: Aggregate metrics like total mints, transfers, volume, etc.
  • Automation: Trigger off-chain logic like payouts or access control

πŸ§ͺ Testing Tips​

  • Deploy the same contract to a testnet like Goerli or Sepolia
  • Use Web3 console or Truffle/Hardhat to trigger events manually
  • Confirm events using Etherscan or Web3 dev tools

πŸ›‘ Best Practices​

  • Always check the connection status
  • Use retry logic or exponential backoff in case of dropped connections
  • Filter events by topics if listening to high-traffic contracts
  • Secure your WebSocket URL (do not expose it in frontend code)

🧩 Bonus: Extending the Service​

Want to go further?

  • Add a database service to persist event data (MongoDB, PostgreSQL, etc.)
  • Add event queues (like BullMQ) to offload heavy post-processing
  • Emit custom NestJS events to communicate across modules

πŸš€ Conclusion​

Listening to smart contract events in real-time is a foundational building block for any dApp backend or blockchain-aware server. With NestJS and Web3.js, you can build scalable, event-driven apps that respond instantly to on-chain activity.

By leveraging service lifecycle hooks, clean code practices, and proper Web3 subscriptions, you can stay ahead in the Web3 world with reliable, maintainable infrastructure.

Now go build the future of decentralized applications with confidence!