Introduction
Solana Web3.js 2.0 represents a significant upgrade to the JavaScript library for interacting with the Solana blockchain. This update introduces a more robust WebSocket subscription system for monitoring on-chain events, offering enhanced type safety and error handling. This guide provides a step-by-step approach to implementing account monitoring using the new subscription system, enabling developers to track real-time changes on the Solana network efficiently.
Key Improvements in Web3.js 2.0
The updated subscription system in Solana Web3.js 2.0 brings several notable enhancements:
- Type Safety: The new API incorporates TypeScript generics and strict typing throughout.
- Modern Asynchronous Iteration: Utilizes
for await...ofloops instead of callbacks, aligning with contemporary asynchronous iteration protocols. - AbortController Integration: Built-in support for subscription cleanup using AbortController.
- Improved Error Handling: Enhanced error types and handling mechanisms.
Setting Up the Development Environment
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:
mkdir solana-subscriptions-v2 && cd solana-subscriptions-v2Initialize a new npm project:
npm init -yInstall required dependencies:
npm install @solana/web3.js@2 npm install --save-dev typescript ts-node @types/nodeConfigure TypeScript:
Create atsconfig.jsonfile with the following settings:{ "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", "noEmit": true, "target": "ESNext" } }
Implementing Account Monitoring
Create the Main Application File
Create a new file named app.ts and open it in your code editor.
Import Dependencies
Add the following imports to app.ts:
import {
createSolanaRpcSubscriptions,
RpcSubscriptions,
SolanaRpcSubscriptionsApi,
address,
Address
} from '@solana/web3.js';Define Constants
Add these constants below your imports:
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 the placeholder WebSocket URL with your actual QuickNode endpoint. The example uses the Pump.fun fee account, but you can substitute any Solana account address.
Helper Function for Formatting
Add this utility function to convert 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' : ''}`;
};Define Interface for Tracking Arguments
Create an interface to define the parameters for the tracking function:
interface TrackAccountArgs {
rpcSubscriptions: RpcSubscriptions<SolanaRpcSubscriptionsApi>;
accountAddress: Address;
abortSignal: AbortSignal;
}Implement Account Tracking Function
Add the following function to handle account monitoring:
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) {
throw error;
}
} catch (error) {
throw error;
}
}Create Main Function
Add the entry point function to execute your tracking:
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();Running the Monitoring Script
Execute the script using ts-node:
ts-node app.tsThe monitor will begin tracking changes to the specified account and display balance changes in the following format:
Account change detected at slot 301,428,932. New balance: 265,598.16 SOL (+0.14 SOL)Billing Considerations and Optimization
WebSocket methods are billed based on the number of responses received rather than the number of subscriptions created. Each response from an accountNotifications subscription costs 20 API credits. To optimize your usage and avoid unnecessary costs:
- Use AbortController or other subscription logic to cancel subscriptions when not needed
- Implement filters where applicable to receive only relevant data
- Monitor your usage through your provider's dashboard
👉 View real-time monitoring tools
Alternative Real-Time Data Solutions
QuickNode offers several solutions for obtaining real-time Solana data:
- WebSockets: Ideal for simple applications and rapid development, providing direct connections to Solana nodes
- Yellowstone gRPC Geyser Plugin: Offers a powerful gRPC interface for streaming Solana data with built-in filtering and historical data support
- Streams: A managed solution that processes and routes Solana data to multiple destinations with built-in filtering and historical support
Each option has distinct advantages depending on your specific use case and technical requirements.
Frequently Asked Questions
What is Solana Web3.js 2.0?
Solana Web3.js 2.0 is a major update to the JavaScript library for interacting with the Solana blockchain. It introduces improved type safety, modern asynchronous iteration patterns, and better error handling for WebSocket subscriptions and other blockchain interactions.
How does account monitoring work with WebSockets?
Account monitoring through WebSockets establishes a persistent connection to a Solana node. When changes occur to the specified account (such as balance changes), the node pushes notifications to the client in real-time, allowing immediate response to on-chain activity.
What commitment level should I use for monitoring?
The 'confirmed' commitment level provides a balance between speed and reliability, ensuring that changes are recorded by the cluster before notifications are sent. For applications requiring maximum certainty, 'finalized' may be more appropriate, though it may introduce slight delays.
Can I monitor multiple accounts simultaneously?
Yes, you can create multiple subscriptions to monitor different accounts. However, be mindful of API credit usage as each response from each subscription incurs separate costs.
How do I handle disconnections and reconnections?
The new Web3.js 2.0 API provides improved error handling that can help detect disconnections. Implementing reconnection logic with exponential backoff is recommended for production applications to maintain reliable monitoring.
What are the rate limits for WebSocket subscriptions?
Rate limits vary by provider and subscription plan. Check with your RPC provider for specific limitations on the number of subscriptions and messages per connection.
Conclusion
Solana Web3.js 2.0 provides a more robust, type-safe approach to handling WebSocket subscriptions for Solana blockchain monitoring. The new API simplifies subscription management, error handling, and resource cleanup, enabling developers to create more reliable and maintainable applications for tracking on-chain events.
👉 Explore more monitoring strategies
The enhanced subscription system represents a significant step forward in developer experience for Solana ecosystem projects. By following the implementation outlined in this guide, developers can efficiently monitor account changes and respond to real-time blockchain events with confidence.