Monitor Solana Accounts Using WebSockets and Solana Web3.js 2.0

·

Monitoring real-time changes on the blockchain is essential for developers building responsive decentralized applications. With the release of Solana Web3.js 2.0, a major upgrade to the JavaScript SDK, interacting with Solana has become more efficient, type-safe, and developer-friendly—especially when it comes to WebSocket-based subscriptions.

This guide walks you through setting up a robust account monitoring system using the new Web3.js 2.0 API and WebSocket connections. You'll learn how to track balance changes on any Solana account—such as the Pump.fun fee account—with clean, modern TypeScript code.

Key Features of Web3.js 2.0

The latest version of Solana’s Web3.js library introduces several architectural improvements that enhance reliability and maintainability:

These enhancements make it easier than ever to build resilient, production-grade dApps that react instantly to on-chain events.

👉 Discover how real-time blockchain monitoring can power your next project.

Setting Up Your Development Environment

Before diving into the implementation, ensure your environment is properly configured.

Prerequisites

Step-by-Step Setup

  1. Create a new project directory:

    mkdir solana-subscriptions-v2 && cd solana-subscriptions-v2
  2. Initialize the project:

    npm init -y
  3. Install required packages:

    npm install @solana/web3.js@2
    npm install --save-dev typescript ts-node @types/node
  4. Generate and configure tsconfig.json:
    Run:

    tsc --init

    Then update the file with:

    {
      "compilerOptions": {
        "module": "NodeNext",
        "moduleResolution": "NodeNext",
        "noEmit": true,
        "target": "ESNext"
      }
    }

This configuration ensures compatibility with modern ECMAScript features and Node.js module resolution.

Implementing Account Monitoring

Create a file named app.ts and begin implementing the monitoring logic step by step.

1. Import Required Modules

import {
  createSolanaRpcSubscriptions,
  RpcSubscriptions,
  SolanaRpcSubscriptionsApi,
  address,
  Address
} from '@solana/web3.js';

These imports give you access to the new subscription APIs and type-safe utilities.

2. Define Constants

const WSS_PROVIDER_URL = 'wss://your-quicknode-endpoint.example';
const LAMPORTS_PER_SOL = 1_000_000_000;
const PUMP_FUN_FEE_ACCOUNT = address("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM");

Replace WSS_PROVIDER_URL with your actual WebSocket endpoint from a provider like QuickNode or OKX. The address() function converts a string into a type-safe Address object required by Web3.js 2.0.

We're monitoring the Pump.fun fee account as an example, but you can substitute any valid Solana address.

3. Format Lamports to SOL

Add this helper function to convert lamports (the smallest unit of SOL) into human-readable values:

const lamportsToSolString = (lamports: number, includeUnit = true): string => {
  const solAmount = lamports / LAMPORTS_PER_SOL;
  return `${solAmount.toLocaleString('en-US', {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  })} ${includeUnit ? 'SOL' : ''}`;
};

This ensures clean output with two decimal places and optional unit labeling.

4. Define Interface for Tracking Parameters

interface TrackAccountArgs {
  rpcSubscriptions: RpcSubscriptions<SolanaRpcSubscriptionsApi>;
  accountAddress: Address;
  abortSignal: AbortSignal;
}

This interface improves code clarity and enables better type checking during development.

5. Create the Account Tracking Function

async function trackAccount({ rpcSubscriptions, accountAddress, abortSignal }: TrackAccountArgs) {
  let lastLamports: number | null = null;

  try {
    const accountNotifications = await rpcSubscriptions
      .accountNotifications(accountAddress, { commitment: 'confirmed' })
      .subscribe({ abortSignal });

    try {
      for await (const notification of accountNotifications) {
        const { slot } = notification.context;
        const currentLamports = Number(notification.value.lamports);
        const delta = lastLamports !== null ? currentLamports - lastLamports : 0;
        const sign = delta > 0 ? '+' : delta < 0 ? '-' : ' ';

        console.log(`Account change detected at slot ${slot.toLocaleString()}. New balance: ${lamportsToSolString(currentLamports)} (${sign}${lamportsToSolString(Math.abs(delta))})`);
        lastLamports = currentLamports;
      }
    } catch (error) {
      console.error('Error processing notification:', error);
    }
  } catch (error) {
    console.error('Error creating subscription:', error);
  }
}

This function:

6. Set Up the Entry Point

async function main() {
  console.log(`💊 Monitoring Pump.fun fee account: ${PUMP_FUN_FEE_ACCOUNT} 💊`);
  
  const rpcSubscriptions = createSolanaRpcSubscriptions(WSS_PROVIDER_URL);
  const abortController = new AbortController();

  try {
    await trackAccount({
      rpcSubscriptions,
      accountAddress: PUMP_FUN_FEE_ACCOUNT,
      abortSignal: abortController.signal
    });
  } catch (e) {
    console.log('Subscription error', e);
  } finally {
    abortController.abort();
  }
}

main();

The main() function initializes the connection, starts tracking, and ensures proper cleanup using AbortController.

Running the Monitor

Once everything is set up, run the script:

ts-node app.ts

You’ll see output like:

Account change detected at slot 301,428,932. New balance: 265,598.16 SOL (+0.14 SOL)

Each line shows real-time balance updates including slot number and change magnitude.

👉 Start building real-time blockchain applications today with powerful tools.

Frequently Asked Questions (FAQ)

Q: What are the core benefits of Web3.js 2.0 over version 1.x?
A: Web3.js 2.0 offers better type safety with TypeScript generics, modern async iteration (for await...of), native support for AbortController, and improved error handling—making code more reliable and maintainable.

Q: How do I stop a WebSocket subscription gracefully?
A: Use AbortController. Pass its signal to the .subscribe() method and call .abort() when done. This prevents memory leaks and unnecessary resource usage.

Q: Can I monitor multiple accounts simultaneously?
A: Yes! You can create multiple subscriptions using separate AbortController instances or manage them collectively using a single controller if needed.

Q: Are there costs associated with WebSocket subscriptions?
A: Yes—most providers charge based on message volume. For example, each response may cost API credits. Always unsubscribe when not in use to avoid unnecessary fees.

Q: Is it possible to filter specific types of account changes?
A: While basic filtering isn’t available in accountNotifications, advanced tools like Yellowstone gRPC or Streams allow fine-grained filtering by data layout or program ID.

Q: Which RPC provider should I use for production monitoring?
A: Choose a reliable provider with low latency and high uptime—such as OKX or QuickNode—especially for mission-critical monitoring applications.

Optimizing Performance and Cost

WebSocket billing is typically based on the number of messages received—not just active subscriptions. To optimize:

👉 Explore high-performance blockchain infrastructure built for scale.

Conclusion

Solana Web3.js 2.0 marks a significant leap forward in developer experience. Its modernized subscription model—powered by async iterators, strong typing, and clean abort semantics—makes monitoring Solana accounts easier, safer, and more efficient than ever before.

By following this guide, you now have a working foundation for real-time blockchain monitoring that’s ready for integration into wallets, analytics dashboards, trading bots, or DeFi platforms.

Whether you're tracking token inflows, detecting smart contract events, or auditing transaction flows, leveraging Web3.js 2.0 ensures your applications stay responsive and robust in fast-moving blockchain environments.

Core Keywords: Solana Web3.js 2.0, WebSocket subscription, monitor Solana account, TypeScript blockchain development, real-time blockchain monitoring, Solana RPC, account change detection