In blockchain systems, pending transactions are those that have been submitted to the network but have not yet been included in a block. By subscribing to these events using eth_subscribe, your application can receive real-time notifications of transaction hashes as they enter the transaction pool (mempool). This push-based approach helps build responsive decentralized applications, monitor network activity, and provide transaction tracking or analytics in near real-time.

In this guide, we focus on subscribing to pending transactions using eth_subscribe. The provided boilerplate uses a WebSocket provider (pointing to wss://peaq.api.onfinality.io/public-ws), creates a subscription for pending transactions, handles incoming data and errors, and includes a graceful shutdown routine to properly clean up the subscription and disconnect the WebSocket provider.

Prerequisites

  • Node.js Environment: You have Node.js installed on your system.
  • Familiarity with JavaScript: You are comfortable with JavaScript and asynchronous programming (using async/await).
  • WebSocket Connection: You will connect to a peaq network node via WebSocket (using wss://peaq.api.onfinality.io/public-ws).
  • Dependencies: The required packages (web3, dotenv, and web3-providers-ws) are installed.
  • Basic Blockchain Knowledge: You understand the concepts of pending transactions, mempool, and real‑time event subscription.

Instructions

1. Setting Up the Environment

  • Install Dependencies: Ensure you install the necessary packages:
npm install web3 dotenv web3-providers-ws
  • Set ESM Module: Add the following to your package.json to alllow for ESM modules.
"type": "module",
  • Configure Environment Variables: Create a .env file with the following content:
PEAQ_WS_URL=wss://peaq.api.onfinality.io/public-ws

2. Understanding eth_subscribe

The eth_subscribe method is a JSON-RPC method available over WebSocket connections. It allows you to subscribe to various types of events on the blockchain in real-time. When subscribing to pending transactions, the node sends updates as soon as new transactions are detected in the mempool. Here’s how it works:

  • Subscription Request:

    When you call web3.eth.subscribe('pendingTransactions'), the node sets up a listener for new pending transactions.

  • Data Event:

    The subscription object returns a push-based stream of events. Each event provides the transaction hash of a pending transaction. The code attaches an event handler on the "data" event to process each incoming transaction hash.

  • Error Handling:

    An "error" event is also attached to handle any issues (e.g., network errors or connection drops).

3. Implementing the Boilerplate

The provided boilerplate performs the following steps:

  • Initialize the Provider and Web3 Instance:

    A WebSocket provider is created using web3-providers-ws, connecting to the peaq network RPC endpoint.

  • Subscribe to Pending Transactions:

    An asynchronous function is used to call web3.eth.subscribe('pendingTransactions'). Once the subscription is created, event handlers for "data" and "error" are attached.

  • Graceful Shutdown:

    A signal handler for SIGINT (e.g., when pressing Ctrl+C) is registered. Upon receiving the shutdown signal, the code unsubscribes from pending transactions and disconnects the WebSocket provider to ensure a clean exit.

// eth_subscribe_pendingTx.js

import dotenv from 'dotenv';
dotenv.config();

import Web3 from 'web3';
import WSProvider from 'web3-providers-ws';

const WS_URL = process.env.PEAQ_WS_URL || 'wss://peaq.api.onfinality.io/public-ws';
const provider = new WSProvider(WS_URL);
const web3 = new Web3(provider);

let pendingSubscription;

(async () => {
  try {
    pendingSubscription = await web3.eth.subscribe('pendingTransactions');
    pendingSubscription.on("data", (txHash) => {
      console.log("Pending Transaction Hash received:");
      console.log(txHash);
    });
    pendingSubscription.on("error", (error) => {
      console.error("Error in pendingTransactions subscription:", error);
    });
  } catch (err) {
    console.error("Error subscribing to pendingTransactions:", err);
  }
})();

// Graceful shutdown
process.on('SIGINT', async () => {
  console.log("\nGracefully shutting down...");
  try {
    if (pendingSubscription) {
      await pendingSubscription.unsubscribe();
      console.log("Unsubscribed from pendingTransactions.");
    }
  } catch (err) {
    console.error("Error unsubscribing from pendingTransactions:", err);
  }
  provider.disconnect();
  process.exit();
});

console.log("Listening for pending transactions on the peaq network (eth_subscribe)...");

The terminal will output the pending transaction hash as follows:

Conclusion

This guide demonstrates how to use the eth_subscribe JSON-RPC method to listen to pending transactions on peaq network.

Using this approach, your application can efficiently monitor the mempool for new pending transactions, enabling you to build responsive, data-driven decentralized applications on the peaq network. Feel free to customize and extend the boilerplate code to suit your specific requirements.