WebSockets
The SDK provides typed WebSocket clients for real-time data.
Connection Lifecycle
WebSocket connections follow this lifecycle:
- Connect - Establish connection to the server
- Authenticate - API key is validated on first message
- Subscribe - Register for specific data channels
- Receive - Data is pushed to your callbacks
- Unsubscribe - Remove specific subscriptions
- Disconnect - Close the connection
┌─────────┐ ┌──────────────┐ ┌───────────┐ ┌─────────┐
│ connect │───>│ authenticate │───>│ subscribe │───>│ receive │
└─────────┘ └──────────────┘ └───────────┘ └────┬────┘
│
┌────────────┐ ┌─────────────┐ │
│ disconnect │<───│ unsubscribe │<──┘
└────────────┘ └─────────────┘
DEX WebSocket
Subscribe to real-time market data:
const dexWs = wallet.createDexWebSocket();
// Connect
await dexWs.connect();
// Subscribe to trending pairs
const subId = await dexWs.subscribe(
{ chain: 'solana', minLiquidity: 10000 },
(pairs) => {
console.log('Trending pairs updated:', pairs.length);
for (const pair of pairs) {
console.log(`${pair.baseToken.symbol}: $${pair.priceUsd}`);
}
}
);
// Later: unsubscribe and disconnect
dexWs.unsubscribe(subId);
dexWs.disconnect();Heartbeat / Ping
The server sends periodic ping frames to keep the connection alive. The SDK handles pong responses automatically. If no ping is received for 60 seconds, the connection is considered stale and will be closed.
Max Subscriptions: Each WebSocket connection supports up to 50 active subscriptions. If you need more, open additional connections. Subscriptions are counted per connection, not per API key.
Subscription Filters
await dexWs.subscribe(
{
chain: 'solana',
minLiquidity: 10000, // Minimum USD liquidity
minVolume: 5000, // Minimum 24h volume
channel: 'trending', // trending, gainers, losers, new
},
(pairs) => console.log(pairs)
);Multiple Subscriptions
// Subscribe to multiple channels
const trendingId = await dexWs.subscribe(
{ channel: 'trending', chain: 'solana' },
handleTrending
);
const gainersId = await dexWs.subscribe(
{ channel: 'gainers', chain: 'solana' },
handleGainers
);
// Unsubscribe individually
dexWs.unsubscribe(trendingId);
dexWs.unsubscribe(gainersId);
// Or unsubscribe all
dexWs.unsubscribeAll();Chain WebSocket
Subscribe to on-chain events:
const chainWs = wallet.createChainWebSocket('solana');
await chainWs.connect();
// Subscribe to account changes
const subId = await chainWs.subscribe(
'accountSubscribe',
['wallet_address', { encoding: 'jsonParsed' }],
(data) => {
console.log('Account updated:', data);
}
);
// Unsubscribe
await chainWs.unsubscribe(subId);
chainWs.disconnect();Solana Subscriptions
// Account changes
await chainWs.subscribe('accountSubscribe', [address], callback);
// Program logs
await chainWs.subscribe('logsSubscribe', [{ mentions: [programId] }], callback);
// Slot updates
await chainWs.subscribe('slotSubscribe', [], callback);Reconnection
Both WebSocket clients support automatic reconnection:
const dexWs = wallet.createDexWebSocket({
reconnect: true,
maxReconnectAttempts: 5,
reconnectDelay: 1000, // Base delay in ms (uses exponential backoff)
});Reconnection Best Practices
Important: Subscriptions are NOT automatically restored after reconnection. You must re-subscribe to channels after the connected event fires.
const dexWs = wallet.createDexWebSocket({
reconnect: true,
maxReconnectAttempts: 5,
reconnectDelay: 1000,
});
// Track active subscriptions for re-subscription
const activeSubscriptions: DexSubscriptionParams[] = [];
dexWs.on('connected', async () => {
console.log('Connected - restoring subscriptions');
// Re-subscribe to all channels after reconnection
for (const params of activeSubscriptions) {
await dexWs.subscribe(params, handleData);
}
});
dexWs.on('disconnected', () => {
console.log('Disconnected - will attempt reconnection');
});
dexWs.on('reconnecting', (attempt) => {
console.log(`Reconnection attempt ${attempt} of 5`);
});
// Store subscription params when subscribing
const params = { channel: 'trending', chain: 'solana' };
activeSubscriptions.push(params);
await dexWs.subscribe(params, handleData);Exponential Backoff
Reconnection uses exponential backoff with jitter:
| Attempt | Base Delay | With Jitter (approx) |
|---|---|---|
| 1 | 1s | 1-1.5s |
| 2 | 2s | 2-3s |
| 3 | 4s | 4-6s |
| 4 | 8s | 8-12s |
| 5 | 16s | 16-24s |
After maxReconnectAttempts is reached, the client stops reconnecting and emits an error event.
Connection Events
dexWs.on('connected', () => console.log('Connected'));
dexWs.on('disconnected', () => console.log('Disconnected'));
dexWs.on('reconnecting', (attempt) => console.log(`Reconnecting... attempt ${attempt}`));
dexWs.on('error', (error) => console.error('Error:', error));Type Definitions
interface DexWebSocketOptions {
reconnect?: boolean;
maxReconnectAttempts?: number;
reconnectDelay?: number;
}
interface DexSubscriptionParams {
chain?: string;
channel?: 'trending' | 'gainers' | 'losers' | 'new';
minLiquidity?: number;
minVolume?: number;
}
interface ChainWebSocketOptions {
reconnect?: boolean;
maxReconnectAttempts?: number;
reconnectDelay?: number;
}