Skip to main content

Introduction

The Opinix Trade WebSocket API provides real-time market data updates including order book depth, trades, and ticker information. WebSocket connections enable low-latency, bi-directional communication for live trading data.

Connection

WebSocket URL

Connect to the WebSocket server at:
ws://wss.opinix.trade
Use wss:// (secure WebSocket) in production environments.

Establishing Connection

const ws = new WebSocket('ws://wss.opinix.trade');

ws.onopen = () => {
  console.log('Connected to Opinix Trade WebSocket');
};

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  console.log('Received:', message);
};

ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};

ws.onclose = () => {
  console.log('Disconnected from WebSocket');
};

Subscription Model

The WebSocket API uses a subscription-based model where clients subscribe to specific channels to receive updates.

User Management

When a client connects:
  1. A unique user ID is automatically generated (source: services/wss/src/classes/UserManager.ts:38-40)
  2. The client is registered in the UserManager singleton
  3. Upon disconnect, all subscriptions are automatically cleaned up

Subscription Manager

The WebSocket server uses Redis pub/sub to efficiently manage subscriptions:
  • Each subscription channel corresponds to an event ID
  • Multiple users can subscribe to the same channel
  • When the first user subscribes to a channel, the server subscribes to the Redis channel
  • When the last user unsubscribes, the server unsubscribes from Redis

Message Types

The WebSocket API supports two types of messages:

Incoming Messages (Client → Server)

Subscribe

Subscribe to orderbook updates for specific events

Unsubscribe

Unsubscribe from orderbook updates

Outgoing Messages (Server → Client)

Subscribe to Orderbook

To receive orderbook updates for specific events, send a subscribe message:

Message Format

{
  "method": "subscribe_orderbook",
  "events": ["3169798", "3169799"]
}
method
string
required
Must be "subscribe_orderbook"
events
string[]
required
Array of event IDs to subscribe to

Example

const ws = new WebSocket('ws://wss.opinix.trade');

ws.onopen = () => {
  // Subscribe to multiple events
  ws.send(JSON.stringify({
    method: 'subscribe_orderbook',
    events: ['3169798', '3169799']
  }));
};

Unsubscribe from Orderbook

To stop receiving updates for specific events:

Message Format

{
  "method": "unsubscribe_orderbook",
  "events": ["3169798"]
}
method
string
required
Must be "unsubscribe_orderbook"
events
string[]
required
Array of event IDs to unsubscribe from

Example

// Unsubscribe from specific events
ws.send(JSON.stringify({
  method: 'unsubscribe_orderbook',
  events: ['3169798']
}));

Connection Lifecycle

1

Connect

Establish WebSocket connection to ws://wss.opinix.trade
2

Register

Server automatically generates a unique user ID and registers the connection
3

Subscribe

Send subscribe messages for events you want to monitor
4

Receive Updates

Receive real-time depth, ticker, and trade updates
5

Unsubscribe (Optional)

Unsubscribe from specific events when no longer needed
6

Disconnect

Close connection. Server automatically cleans up all subscriptions

Best Practices

WebSocket connections can drop due to network issues. Always implement automatic reconnection with exponential backoff:
function connectWithRetry(url, maxRetries = 5) {
  let retries = 0;
  
  function connect() {
    const ws = new WebSocket(url);
    
    ws.onclose = () => {
      if (retries < maxRetries) {
        const delay = Math.min(1000 * Math.pow(2, retries), 30000);
        console.log(`Reconnecting in ${delay}ms...`);
        setTimeout(connect, delay);
        retries++;
      }
    };
    
    ws.onopen = () => {
      retries = 0; // Reset on successful connection
    };
    
    return ws;
  }
  
  return connect();
}
Always wrap JSON parsing in try-catch to handle malformed messages:
ws.onmessage = (event) => {
  try {
    const message = JSON.parse(event.data);
    handleMessage(message);
  } catch (error) {
    console.error('Failed to parse message:', error);
  }
};
Don’t subscribe to all events. Only subscribe to the events you’re actively displaying to reduce bandwidth and processing overhead.
When navigating away from an event page or closing a view, unsubscribe from events you no longer need.
Implement ping/pong or heartbeat mechanism to detect stale connections:
let heartbeatInterval;

ws.onopen = () => {
  heartbeatInterval = setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: 'ping' }));
    }
  }, 30000); // Every 30 seconds
};

ws.onclose = () => {
  clearInterval(heartbeatInterval);
};

Type Definitions

Based on services/wss/src/types/index.ts, here are the TypeScript type definitions:
export const subscribeOrderbook = "subscribe_orderbook";
export const unSubscribeOrderbook = "unsubscribe_orderbook";

export type SubscribeMessage = {
  method: typeof subscribeOrderbook;
  events: string[];
}

export type UnsubscribeMessage = {
  method: typeof unSubscribeOrderbook;
  events: string[];
}

export type IncomingMessage = SubscribeMessage | UnsubscribeMessage;

export type DepthUpdateMessage = {
  type: "depth";
  data: {
    b?: [string, string][]; // bids
    a?: [string, string][]; // asks
    id: number;             // event ID
    e: "depth";             // event type
  }
}

export type OutgoingMessage = DepthUpdateMessage;

Implementation Notes

Source Code Reference:
  • WebSocket server: services/wss/src/index.ts
  • User management: services/wss/src/classes/UserManager.ts
  • Subscription management: services/wss/src/classes/SubscriptionManager.ts
  • Type definitions: services/wss/src/types/index.ts
  • Message types: packages/types/src/index.ts:170-209

Next Steps