Monitor Solana Accounts Using WebSocket and Solana Web3.js 2.0

·

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

This guide walks you through setting up a robust account monitoring system using the new Web3.js 2.0 API, leveraging modern async iteration, improved error handling, and built-in support for clean resource management via AbortController.


Key Features of Solana Web3.js 2.0

The latest version introduces significant improvements over its predecessor, particularly in how developers manage real-time data streams:

These enhancements make Web3.js 2.0 ideal for monitoring accounts, tracking token transfers, or reacting to smart contract events in real time.

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


Setting Up Your Development Environment

Before diving into code, ensure your environment meets the following requirements:

Step 1: Initialize Project

Create a new directory and initialize an npm project:

mkdir solana-subscriptions-v2 && cd solana-subscriptions-v2
npm init -y

Step 2: Install Dependencies

Install the required packages:

npm install @solana/web3.js@2
npm install --save-dev typescript ts-node @types/node

Step 3: Configure TypeScript

Generate a tsconfig.json file:

tsc --init

Update it with modern module settings:

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

This configuration ensures compatibility with the latest ES features and proper module resolution.


Building the Account Monitor

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

Import Required Modules

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

These imports provide access to the new subscription system and typed address handling.

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. The address() function ensures type-safe account references.

Note: You can monitor any Solana account. Here, we track the Pump.fun fee collection wallet for demonstration.

Helper Function: Format Lamports to SOL

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 utility converts raw lamport values into human-readable SOL amounts.


Implementing the Subscription Logic

Define Interface for Tracking Parameters

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

This interface improves code clarity and enables better IDE support.

Create the trackAccount 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(`Detected change at slot ${slot.toLocaleString()}. New balance: ${lamportsToSolString(currentLamports)} (${sign}${lamportsToSolString(Math.abs(delta))})`);
        lastLamports = currentLamports;
      }
    } catch (error) {
      throw error;
    }
  } catch (error) {
    throw error;
  }
}

This function uses async iteration to listen for balance updates, calculates deltas, and logs changes with context.


Entry Point: Initialize and Run

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.error('Subscription error:', e);
  } finally {
    abortController.abort();
  }
}

main();

The main() function initializes the connection, starts monitoring, and ensures cleanup via abortController.abort().

👉 See how you can integrate live blockchain feeds into your app


Running the Monitor

Execute the script using:

ts-node app.ts

You’ll see output like:

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

Each line reflects a confirmed state change in the monitored account.


Frequently Asked Questions

Q: What are the benefits of Web3.js 2.0 over version 1.x?
A: Version 2.0 offers better type safety, modern async/await patterns, native AbortController integration, and more consistent error handling—making it easier to build reliable dApps.

Q: How do I stop a WebSocket subscription properly?
A: Use AbortController as shown in the example. Calling abortController.abort() triggers cleanup and closes the WebSocket connection gracefully.

Q: Can I monitor multiple accounts simultaneously?
A: Yes. Create separate subscriptions for each account using individual AbortSignal instances or manage them within a loop with proper scoping.

Q: Are there costs associated with WebSocket subscriptions?
A: Yes. Providers often charge based on message volume. For instance, each notification received may consume API credits. Always unsubscribe when done to avoid unnecessary costs.

Q: Is this method suitable for production use?
A: Absolutely. With proper error handling, reconnection logic (not shown here), and monitoring, this pattern is production-ready for real-time Solana applications.

Q: Can I filter specific types of account changes?
A: While basic filtering isn't available in accountNotifications, you can apply logic in your loop to ignore irrelevant updates based on size, timing, or other criteria.


Optimization & Cost Management

WebSocket usage is typically billed per response received. For example:

To optimize:

👉 Explore high-performance blockchain data APIs for scalable apps


Alternative Real-Time Data Solutions

While WebSockets are great for simple use cases, consider these alternatives for advanced needs:

Choose based on your scalability, latency, and processing requirements.


Conclusion

Solana Web3.js 2.0 revolutionizes how developers interact with real-time blockchain data. By embracing modern JavaScript patterns and enhancing developer ergonomics, it simplifies building responsive, maintainable applications that react instantly to on-chain activity.

Whether you're tracking wallet balances, detecting token swaps, or building analytics dashboards, this new API empowers you with greater control and reliability.

Start experimenting today—and unlock the full potential of live Solana data.

Core Keywords: Solana Web3.js 2.0, WebSocket subscription, monitor Solana account, real-time blockchain data, TypeScript blockchain development, async iteration JavaScript, Solana RPC API