websocket.ts
Overview
The [websocket.ts](/projects/291/69087) file defines a specialized WebSocket client class (`WebsocketClient`) tailored for subscribing to Solana blockchain transaction logs and processing them in real time. It extends a base WebSocket client from an external library to facilitate subscription management by addresses, handle incoming blockchain event messages, and delegate transaction data to user-defined asynchronous handlers.
This file's core functionality is to:
Establish and manage a WebSocket connection to a Solana RPC endpoint (optionally with an API key).
Subscribe to transaction logs for specified Solana addresses.
Parse and validate incoming WebSocket messages related to subscription confirmations and transaction log notifications.
Dispatch transaction log data asynchronously to one or more user-provided transaction handlers.
Manage subscription lifecycle internally, including subscribing, unsubscribing, and tracking active subscriptions.
The class is designed with scalability and flexibility in mind, supporting multiple transaction handlers and multiple address subscriptions concurrently.
Class: WebsocketClient
A Solana blockchain-specific WebSocket client extending the generic `BaseWebsocketClient` for subscribing to logs notifications filtered by addresses. It manages subscription lifecycle and handles incoming messages to process transaction logs.
Declaration
class WebsocketClient extends BaseWebsocketClient
Constructor
constructor(_url: string, args: WebsocketArgs, opts?: Options)
Parameters:
_url(string): The base WebSocket URL for the Solana RPC node.args(WebsocketArgs): Arguments for initialization.Extends
Argsbut excludeslogger.Includes a mandatory
transactionHandlerwhich can be a single function or an array of functions to process incoming transaction logs.Optionally includes an
apiKeythat will be appended as a query parameter to the URL.
opts(Options, optional): Additional options passed to the base client.
Behavior:
Constructs the full URL by appending
?api-key=...if an API key is provided.Calls the
BaseWebsocketClientconstructor with the built URL and a scoped logger.Stores the provided transaction handler(s).
Calls
initialize()(inherited from the base class) to set up the connection.
Usage Example:
const wsClient = new WebsocketClient('wss://solana-rpc.example.com', {
apiKey: 'your-api-key',
transactionHandler: async (tx) => {
console.log('Received transaction:', tx.signature);
}
});
Properties
Property | Type | Description |
|---|---|---|
`handleTransaction` | `TransactionHandler | TransactionHandler[]` |
`addresses` | `string[]` | List of addresses currently subscribed to. |
`subscriptionIds` | `number[]` | List of active subscription IDs returned from the server. |
`currentId` | `number` | Incremental ID used for tracking subscription requests. |
Methods
protected onOpen(): void
Called automatically when the WebSocket connection is opened.
If there are subscribed addresses stored, it triggers a resubscription to those addresses.
Overrides the base class's
onOpen()method.Usage: Internal lifecycle method, no direct user invocation.
protected async onMessage(message: WebSocket.MessageEvent): Promise<void>
Handles incoming messages from the WebSocket server.
Parameters:
message: The raw WebSocket message event.
Behavior:
Parses the message JSON.
If the message is a subscription confirmation response (
WebsocketSubscribeResponse):Validates if the subscription ID matches the current ID.
Stores the subscription result ID.
If unmatched, unsubscribes immediately.
If the message is a logs notification (
logsNotificationmethod):Verifies the subscription ID is active.
Calls each transaction handler asynchronously with the transaction log data.
If the subscription ID is unknown, unsubscribes it.
Logs and swallows any errors from message parsing or handling.
Usage: Internal event handler for WebSocket messages.
subscribeAddresses(addresses: string[]): void
Subscribes to logs notifications for the specified Solana addresses.
Parameters:
addresses: Array of Solana address strings to subscribe to.
Behavior:
Updates the internal
addresseslist.Increments
currentIdto differentiate this subscription batch.Unsubscribes from all previous subscription IDs.
Sends new subscription requests for each address using the JSON-RPC
logsSubscribemethod withmentionsfilter.Logs any errors encountered during subscription sending.
Usage Example:
wsClient.subscribeAddresses(['Address1', 'Address2']);
private unsubscribe(subscriptionId: number): void
Unsubscribes from a subscription based on its subscription ID.
Parameters:
subscriptionId: The subscription ID to cancel.
Behavior:
Sends an
logsUnsubscribeJSON-RPC request for the given subscription ID.
Usage: Called internally when unsubscribing from stale or unwanted subscriptions.
Types and Interfaces
TransactionHandler
type TransactionHandler = (data: Logs) => Promise<void>
A function type that takes a Solana
Logsobject and returns a Promise.Used as the callback signature for handling transaction log data.
WebsocketArgs
interface WebsocketArgs extends Omit<Args, 'logger'> {
transactionHandler: TransactionHandler | TransactionHandler[]
}
Arguments for constructing
WebsocketClient.Extends base
Argsbut excludeslogger.Requires a
transactionHandler, which can be a single function or an array.
Important Implementation Details
Subscription IDs &
currentId:currentIdis incremented on each subscription change. Incoming subscription confirmation messages are checked against this ID to maintain consistency and avoid stale subscriptions.Multiple Transaction Handlers:
Supports both single and multiple asynchronous handlers for transaction logs. Each handler is invoked independently in a non-blocking fashion.Reliable Subscription Management:
On reconnect or opening connection, the client automatically resubscribes to all stored addresses.Message Validation:
Uses type-guard functions (isWebsocketResponse,isWebsocketSubscribeResponse) to verify the structure of incoming messages safely.Error Handling:
All exceptions in message parsing or handler execution are caught and logged with context for easier debugging.
Interactions with Other System Components
BaseWebsocketClient (from
@shapeshiftoss/websocket):
Provides foundational WebSocket connection management, including socket lifecycle and message dispatching, whichWebsocketClientextends.Logger (from
@shapeshiftoss/logger):
Scoped logger instance for debug, error, and informational logs within the client.Solana
LogsType (from@solana/web3.js):
Represents the structure of transaction logs emitted by the Solana blockchain, passed to transaction handlers.Types Module (
./types):
Contains type guards and interfaces for validating WebSocket message payloads.External Solana RPC/WebSocket Endpoints:
The client connects to Solana RPC servers supporting WebSocket subscriptions for transaction logs, optionally with API keys for authenticated endpoints.
Usage Example
import { WebsocketClient } from './websocket'
import { Logs } from '@solana/web3.js'
async function processTransaction(tx: Logs): Promise<void> {
console.log('Tx signature:', tx.signature)
// Add custom processing logic here...
}
const ws = new WebsocketClient('wss://api.mainnet-beta.solana.com', {
apiKey: process.env.SOLANA_API_KEY,
transactionHandler: processTransaction,
})
// Subscribe to logs for multiple addresses
ws.subscribeAddresses([
'4Nd1mLkZQ7zbmfK9hQ7aMT1p5H1yM7Wj7f4p7x1LJ4Vq',
'FhtGmnP4CJc7v1L2x2v7vKKKxW5vE5V2Wz4t5hRJcbkV',
])
Mermaid Class Diagram
classDiagram
class WebsocketClient {
-handleTransaction: TransactionHandler | TransactionHandler[]
-addresses: string[]
-subscriptionIds: number[]
-currentId: number
+constructor(_url: string, args: WebsocketArgs, opts?: Options)
+subscribeAddresses(addresses: string[]): void
#onOpen(): void
#onMessage(message: WebSocket.MessageEvent): Promise<void>
-unsubscribe(subscriptionId: number): void
}
WebsocketClient --|> BaseWebsocketClient
Summary
The [websocket.ts](/projects/291/69087) file delivers a specialized WebSocket client implementation for the Solana blockchain, enabling precise, address-based subscription to transaction logs. It efficiently manages subscription lifecycles, validates incoming data, and delegates transaction processing to customizable asynchronous handlers. It integrates seamlessly with the broader system by extending a generic WebSocket client base, using structured logging, and adhering to Solana's RPC specifications, making it a key component for real-time blockchain event-driven applications.