WebSockets

The SDK provides typed WebSocket clients for real-time data.

Connection Lifecycle

WebSocket connections follow this lifecycle:

  1. Connect - Establish connection to the server
  2. Authenticate - API key is validated on first message
  3. Subscribe - Register for specific data channels
  4. Receive - Data is pushed to your callbacks
  5. Unsubscribe - Remove specific subscriptions
  6. 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:

AttemptBase DelayWith Jitter (approx)
11s1-1.5s
22s2-3s
34s4-6s
48s8-12s
516s16-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;
}