Solana Web3.js 2.0 represents a major update to the JavaScript library used for interacting with the Solana blockchain. Among its many enhancements, it introduces a more powerful WebSocket subscription system for monitoring on-chain events. This guide explains how to use the new subscription system for tracking account balance changes, emphasizing improvements in type safety, modern asynchronous iteration, and error handling mechanisms.
Overview of Solana Web3.js 2.0
The latest version of Solana’s JavaScript library brings significant upgrades for developers. The most notable improvements include:
- Type Safety: The new API uses TypeScript generics and strict types throughout.
- Modern Asynchronous Iteration: Leveraging
for await...ofloops instead of callbacks, aligning with contemporary async iterator protocols. - Abort Controller Integration: Built-in support for subscription cleanup using AbortController.
- Better Error Handling: Enhanced error types and handling mechanisms.
These features make it easier to build reliable and maintainable applications that interact with the Solana blockchain in real time.
Setting Up Your Development Environment
Before diving into the implementation, ensure you have the necessary tools and dependencies installed.
Prerequisites
- Node.js (version 20.0 or higher recommended)
- npm or yarn package manager
- TypeScript and ts-node installed globally or locally
Step-by-Step Setup
Create a new project directory:
Open your terminal and run:mkdir solana-subscriptions-v2 && cd solana-subscriptions-v2Initialize a new npm project:
npm init -yInstall required dependencies:
npm install @solana/web3.js@2For development dependencies, install TypeScript and related packages:
npm install --save-dev typescript ts-node @types/nodeConfigure TypeScript:
Generate atsconfig.jsonfile:tsc --initUpdate the configuration with the following settings:
{ "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", "noEmit": true, "target": "ESNext" } }
Building an Account Monitor
With the environment ready, you can now create a script to monitor Solana account changes.
Import Dependencies
Create a new file named app.ts and add the following imports:
import {
createSolanaRpcSubscriptions,
RpcSubscriptions,
SolanaRpcSubscriptionsApi,
address,
Address
} from '@solana/web3.js';Define Constants
Add constants for the WebSocket provider URL, Lamports per SOL, and the account address to monitor:
const WSS_PROVIDER_URL = 'wss://your-quicknode-endpoint.example';
const LAMPORTS_PER_SOL = 1_000_000_000;
const PUMP_FUN_FEE_ACCOUNT = address("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM");Note: Replace the WebSocket URL with your actual endpoint. For Solana development, a reliable API endpoint is essential.
Helper Function for Formatting
Include a function to convert Lamports to SOL for display:
const lamportsToSolString = (lamports: number, includeUnit = true): string => {
const solAmount = lamports / LAMPORTS_PER_SOL;
return `${solAmount.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
})} ${includeUnit ? 'SOL' : ''}`;
};Interface for Tracking Arguments
Define an interface to structure the arguments for the tracking function:
interface TrackAccountArgs {
rpcSubscriptions: RpcSubscriptions<SolanaRpcSubscriptionsApi>;
accountAddress: Address;
abortSignal: AbortSignal;
}Account Tracking Function
Implement the core function to monitor account changes:
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 account 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 sets up a subscription to account notifications, processes each update, and logs balance changes in a user-friendly format.
Entry Point and Execution
Add the main function to execute the tracker:
async function main() {
console.log(`Tracking 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();Run the script using:
ts-node app.tsThe monitor will start tracking balance changes and display outputs like:
Detected account change at slot 301,428,932. New balance: 265,598.16 SOL (+0.14 SOL)Billing and Optimization Tips
WebSocket methods are billed based on the number of responses received, not the number of subscriptions created. For example, if you receive 100 responses from an accountNotifications subscription, your account will be charged 2,000 credits (20 credits per response × 100 responses).
To optimize usage and avoid unnecessary costs:
- Use AbortController or similar logic to unsubscribe when subscriptions are no longer needed.
- Apply filters where applicable to receive only relevant data.
👉 Explore real-time monitoring tools
Alternative Solutions for Real-Time Data
QuickNode offers multiple tools for accessing real-time Solana data:
- WebSockets: Ideal for simple applications and rapid development, providing direct connectivity to Solana nodes.
- Yellowstone gRPC Geyser Plugin: Offers a robust gRPC interface for streaming Solana data with built-in filtering and historical support.
- Streams: A managed solution for processing and routing Solana data to multiple destinations, featuring advanced filtering and historical capabilities.
Each tool has unique strengths, so choose based on your project’s requirements for scalability, filtering, and integration.
Frequently Asked Questions
What is Solana Web3.js 2.0?
Solana Web3.js 2.0 is the latest version of the JavaScript library for interacting with the Solana blockchain. It introduces improved type safety, modern asynchronous patterns, and better error handling.
How do I set up a WebSocket subscription?
Use the accountNotifications method from the RpcSubscriptions class, providing an account address and commitment level. The method returns an async iterable for processing notifications.
Can I monitor multiple accounts simultaneously?
Yes, you can create multiple subscriptions by calling the accountNotifications method for each account. Ensure proper resource management to avoid excessive billing.
What is AbortController used for?
AbortController allows you to cancel asynchronous operations, such as WebSocket subscriptions, when they are no longer needed, helping manage resources and costs.
How are WebSocket requests billed?
Billing is based on the number of responses received. Each response consumes a fixed number of API credits, so optimizing filters and unsubscribing promptly can reduce costs.
Are there alternatives to WebSockets for real-time data?
Yes, alternatives include gRPC plugins and managed streams, which offer additional features like historical data support and built-in filtering for complex applications.
Conclusion
Solana Web3.js 2.0 provides a robust, type-safe approach to handling WebSocket subscriptions. Its modern API simplifies subscription management, error handling, and resource cleanup, making it easier to build reliable applications for monitoring blockchain events. By leveraging these tools, developers can create efficient and maintainable solutions for real-time data tracking on Solana.
For further learning, explore the official Solana Web3.js documentation and community resources to deepen your understanding of blockchain development.