Skip to content

WebSocket Streaming

Examples for real-time data streams using WebSocket subscriptions.

WebSocket subscriptions work without any credentials — only brokerId is needed.

Subscribe to Orderbook

Stream live orderbook updates for a market:

typescript
import { HundredX } from '100x-sdk';

// WebSocket works with read-only config
const sdk = new HundredX({ brokerId: 1 });

const subId = await sdk.ws.subscribeOrderbook(1, (data) => {
  if (data.bids) {
    console.log('Bids:');
    for (const level of data.bids.slice(0, 5)) {
      console.log(`  ${level.price} x ${level.quantity}`);
    }
  }
  if (data.asks) {
    console.log('Asks:');
    for (const level of data.asks.slice(0, 5)) {
      console.log(`  ${level.price} x ${level.quantity}`);
    }
  }
});

Subscribe to Trades

Stream real-time trade data:

typescript
const tradeSubId = await sdk.ws.subscribeTrades(1, (trades) => {
  for (const trade of trades) {
    console.log(`[${trade.timestamp}] ${trade.side} ${trade.size} @ ${trade.price}`);
  }
});

Subscribe to Market Prices

Get orderbook data across all markets:

typescript
const priceSubId = await sdk.ws.subscribeMarketPrices((data) => {
  if (data.marketId) {
    const bestBid = data.bids?.[0]?.price || 'N/A';
    const bestAsk = data.asks?.[0]?.price || 'N/A';
    console.log(`Market ${data.marketId}: ${bestBid} / ${bestAsk}`);
  }
});

Unsubscribe

Each subscribe* call returns a subscription ID. Use it to unsubscribe:

typescript
// Unsubscribe from a specific stream
sdk.ws.unsubscribe(subId);

// Unsubscribe from everything
sdk.ws.unsubscribeAll();

Build a Live Spread Monitor

typescript
async function spreadMonitor(marketId: number) {
  let bestBid = '0';
  let bestAsk = '0';

  await sdk.ws.subscribeOrderbook(marketId, (data) => {
    if (data.bids && data.bids.length > 0) bestBid = data.bids[0].price;
    if (data.asks && data.asks.length > 0) bestAsk = data.asks[0].price;

    const spread = parseFloat(bestAsk) - parseFloat(bestBid);
    const mid = (parseFloat(bestBid) + parseFloat(bestAsk)) / 2;
    const spreadBps = mid > 0 ? (spread / mid) * 10000 : 0;

    console.log(`Spread: ${bestBid} / ${bestAsk} (${spreadBps.toFixed(1)} bps)`);
  });
}

await spreadMonitor(1);

Trade Volume Tracker

Track trade volume over a rolling window:

typescript
async function volumeTracker(marketId: number, windowMs: number = 60000) {
  const recentTrades: { size: number; timestamp: number }[] = [];

  await sdk.ws.subscribeTrades(marketId, (trades) => {
    const now = Date.now();

    for (const trade of trades) {
      recentTrades.push({
        size: parseFloat(trade.size),
        timestamp: now,
      });
    }

    // Remove expired trades
    while (recentTrades.length > 0 && now - recentTrades[0].timestamp > windowMs) {
      recentTrades.shift();
    }

    const volume = recentTrades.reduce((sum, t) => sum + t.size, 0);
    console.log(`Volume (${windowMs / 1000}s window): ${volume.toFixed(4)}`);
  });
}

await volumeTracker(1);

Price Feed for Market Making

Use WebSocket prices to drive a market maker:

typescript
async function wsMarketMaker(marketId: number) {
  // Need full credentials for trading
  const sdk = await HundredX.create({
    privateKey: process.env.PRIVATE_KEY!,
    brokerId: Number(process.env.BROKER_ID!),
  });

  let currentMid = 0;
  const SIZE = '0.5';
  const SPREAD_BPS = 8;

  // Stream prices
  await sdk.ws.subscribeOrderbook(marketId, (data) => {
    if (data.bids?.length && data.asks?.length) {
      const bid = parseFloat(data.bids[0].price);
      const ask = parseFloat(data.asks[0].price);
      currentMid = (bid + ask) / 2;
    }
  });

  // Refresh quotes every 2 seconds
  setInterval(async () => {
    if (currentMid === 0) return;

    try {
      await sdk.exchange.cancelAllOrders(marketId);

      const halfSpread = currentMid * (SPREAD_BPS / 10000);
      const bid = (currentMid - halfSpread).toFixed(2);
      const ask = (currentMid + halfSpread).toFixed(2);

      await sdk.exchange.placeOrder({
        marketId,
        isBuy: true,
        amount: SIZE,
        price: bid,
        orderType: 'LIMIT',
      });

      await sdk.exchange.placeOrder({
        marketId,
        isBuy: false,
        amount: SIZE,
        price: ask,
        orderType: 'LIMIT',
      });

      console.log(`Quoted: ${bid} / ${ask} (mid: ${currentMid.toFixed(2)})`);
    } catch (error) {
      console.error('Quote refresh error:', error);
    }
  }, 2000);
}

await wsMarketMaker(1);

Multiple Market Subscriptions

typescript
const marketIds = [1, 2, 3];
const subscriptions: string[] = [];

for (const id of marketIds) {
  const sub = await sdk.ws.subscribeOrderbook(id, (data) => {
    const bid = data.bids?.[0]?.price || 'N/A';
    const ask = data.asks?.[0]?.price || 'N/A';
    console.log(`Market ${id}: ${bid} / ${ask}`);
  });
  subscriptions.push(sub);
}

// Cleanup
function cleanup() {
  for (const sub of subscriptions) {
    sdk.ws.unsubscribe(sub);
  }
  sdk.disconnect();
}

process.on('SIGINT', cleanup);

Clean Shutdown

Always disconnect WebSocket connections when you're done:

typescript
// Option 1: Unsubscribe individually
sdk.ws.unsubscribe(subId);

// Option 2: Unsubscribe all and disconnect
sdk.ws.unsubscribeAll();
sdk.disconnect();

100x Exchange Market Maker SDK