WebSocket Connection Guide

Complete guide to establishing and maintaining WebSocket connections for real-time data streaming from Vibe Trading.

Overview

WebSocket connections provide real-time, bidirectional communication with the Vibe Trading platform. This allows you to receive live market data, order updates, and AI signals without polling the REST API.

Connection Details

WebSocket URL

wss://ws.vibetrading.tech/ws

Connection Parameters

  • Protocol: WebSocket (WSS for secure connections)
  • Authentication: API key and signature required
  • Heartbeat: 30-second ping/pong to maintain connection
  • Reconnection: Automatic reconnection with exponential backoff

Authentication

Connection Authentication

WebSocket connections require authentication using your API credentials.

Authentication Message:

{
  "type": "auth",
  "apiKey": "your_api_key",
  "timestamp": 1640995200,
  "signature": "calculated_signature"
}

Signature Generation

Same HMAC-SHA256 signature generation as REST API:

function generateWebSocketSignature(secretKey, apiKey, timestamp) {
  const message = apiKey + timestamp;
  return crypto.createHmac("sha256", secretKey).update(message).digest("hex");
}

Authentication Response

{
  "type": "auth_success",
  "message": "Authentication successful",
  "timestamp": 1640995200
}

Connection Management

Establishing Connection

JavaScript/Node.js

const WebSocket = require("ws");
const crypto = require("crypto");

class VibeTradingWebSocket {
  constructor(apiKey, secretKey) {
    this.apiKey = apiKey;
    this.secretKey = secretKey;
    this.ws = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
    this.reconnectInterval = 1000;
  }

  connect() {
    this.ws = new WebSocket("wss://ws.vibetrading.tech/ws");

    this.ws.on("open", () => {
      console.log("WebSocket connected");
      this.authenticate();
      this.reconnectAttempts = 0;
    });

    this.ws.on("message", (data) => {
      this.handleMessage(JSON.parse(data));
    });

    this.ws.on("close", (code, reason) => {
      console.log(`WebSocket closed: ${code} ${reason}`);
      this.handleReconnect();
    });

    this.ws.on("error", (error) => {
      console.error("WebSocket error:", error);
    });
  }

  authenticate() {
    const timestamp = Math.floor(Date.now() / 1000);
    const signature = this.generateSignature(timestamp);

    const authMessage = {
      type: "auth",
      apiKey: this.apiKey,
      timestamp: timestamp,
      signature: signature,
    };

    this.ws.send(JSON.stringify(authMessage));
  }

  generateSignature(timestamp) {
    const message = this.apiKey + timestamp;
    return crypto
      .createHmac("sha256", this.secretKey)
      .update(message)
      .digest("hex");
  }

  handleMessage(message) {
    switch (message.type) {
      case "auth_success":
        console.log("Authentication successful");
        this.subscribeToChannels();
        break;
      case "auth_error":
        console.error("Authentication failed:", message.error);
        break;
      case "pong":
        // Heartbeat response
        break;
      default:
        this.processDataMessage(message);
    }
  }

  subscribeToChannels() {
    // Subscribe to desired channels
    const subscriptions = [
      { type: "subscribe", channel: "ticker", symbol: "BTC/USD" },
      { type: "subscribe", channel: "orderbook", symbol: "BTC/USD" },
      { type: "subscribe", channel: "trades", symbol: "BTC/USD" },
    ];

    subscriptions.forEach((sub) => {
      this.ws.send(JSON.stringify(sub));
    });
  }

  handleReconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      const delay =
        this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1);

      console.log(
        `Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`
      );

      setTimeout(() => {
        this.connect();
      }, delay);
    } else {
      console.error("Max reconnection attempts reached");
    }
  }

  processDataMessage(message) {
    // Process incoming data messages
    console.log("Received data:", message);
  }

  sendPing() {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({ type: "ping" }));
    }
  }

  close() {
    if (this.ws) {
      this.ws.close();
    }
  }
}

// Usage
const ws = new VibeTradingWebSocket("your_api_key", "your_secret_key");
ws.connect();

// Set up heartbeat
setInterval(() => {
  ws.sendPing();
}, 30000);

Python

import asyncio
import websockets
import json
import hmac
import hashlib
import time

class VibeTradingWebSocket:
    def __init__(self, api_key, secret_key):
        self.api_key = api_key
        self.secret_key = secret_key
        self.websocket = None
        self.reconnect_attempts = 0
        self.max_reconnect_attempts = 5
        self.reconnect_interval = 1

    async def connect(self):
        uri = "wss://ws.vibetrading.tech/ws"

        try:
            self.websocket = await websockets.connect(uri)
            print("WebSocket connected")
            await self.authenticate()
            self.reconnect_attempts = 0

            # Start listening for messages
            await self.listen()

        except websockets.exceptions.ConnectionClosed:
            print("WebSocket connection closed")
            await self.handle_reconnect()
        except Exception as e:
            print(f"WebSocket error: {e}")
            await self.handle_reconnect()

    async def authenticate(self):
        timestamp = int(time.time())
        signature = self.generate_signature(timestamp)

        auth_message = {
            "type": "auth",
            "apiKey": self.api_key,
            "timestamp": timestamp,
            "signature": signature
        }

        await self.websocket.send(json.dumps(auth_message))

    def generate_signature(self, timestamp):
        message = self.api_key + str(timestamp)
        return hmac.new(
            self.secret_key.encode(),
            message.encode(),
            hashlib.sha256
        ).hexdigest()

    async def listen(self):
        async for message in self.websocket:
            data = json.loads(message)
            await self.handle_message(data)

    async def handle_message(self, message):
        message_type = message.get("type")

        if message_type == "auth_success":
            print("Authentication successful")
            await self.subscribe_to_channels()
        elif message_type == "auth_error":
            print(f"Authentication failed: {message.get('error')}")
        elif message_type == "pong":
            # Heartbeat response
            pass
        else:
            await self.process_data_message(message)

    async def subscribe_to_channels(self):
        subscriptions = [
            {"type": "subscribe", "channel": "ticker", "symbol": "BTC/USD"},
            {"type": "subscribe", "channel": "orderbook", "symbol": "BTC/USD"},
            {"type": "subscribe", "channel": "trades", "symbol": "BTC/USD"}
        ]

        for sub in subscriptions:
            await self.websocket.send(json.dumps(sub))

    async def handle_reconnect(self):
        if self.reconnect_attempts < self.max_reconnect_attempts:
            self.reconnect_attempts += 1
            delay = self.reconnect_interval * (2 ** (self.reconnect_attempts - 1))

            print(f"Reconnecting in {delay}s (attempt {self.reconnect_attempts})")
            await asyncio.sleep(delay)
            await self.connect()
        else:
            print("Max reconnection attempts reached")

    async def process_data_message(self, message):
        # Process incoming data messages
        print(f"Received data: {message}")

    async def send_ping(self):
        if self.websocket:
            await self.websocket.send(json.dumps({"type": "ping"}))

    async def close(self):
        if self.websocket:
            await self.websocket.close()

# Usage
async def main():
    ws = VibeTradingWebSocket("your_api_key", "your_secret_key")

    # Start connection
    await ws.connect()

    # Set up heartbeat
    while True:
        await ws.send_ping()
        await asyncio.sleep(30)

if __name__ == "__main__":
    asyncio.run(main())

Channel Subscriptions

Available Channels

Ticker Channel

Real-time price updates for trading pairs.

Subscribe:

{
  "type": "subscribe",
  "channel": "ticker",
  "symbol": "BTC/USD"
}

Data:

{
  "type": "ticker",
  "symbol": "BTC/USD",
  "price": 49850.25,
  "bid": 49840.0,
  "ask": 49860.5,
  "volume24h": 1250.75,
  "change24h": 2.5,
  "timestamp": "2024-01-15T12:00:00Z"
}

Order Book Channel

Real-time order book updates.

Subscribe:

{
  "type": "subscribe",
  "channel": "orderbook",
  "symbol": "BTC/USD",
  "depth": 20
}

Data:

{
  "type": "orderbook",
  "symbol": "BTC/USD",
  "bids": [
    { "price": 49840.0, "quantity": 0.5 },
    { "price": 49835.0, "quantity": 0.3 }
  ],
  "asks": [
    { "price": 49860.5, "quantity": 0.3 },
    { "price": 49865.0, "quantity": 0.4 }
  ],
  "timestamp": "2024-01-15T12:00:00Z"
}

Trades Channel

Real-time trade executions.

Subscribe:

{
  "type": "subscribe",
  "channel": "trades",
  "symbol": "BTC/USD"
}

Data:

{
  "type": "trades",
  "symbol": "BTC/USD",
  "trades": [
    {
      "tradeId": "trade_123456",
      "price": 49850.25,
      "quantity": 0.1,
      "side": "buy",
      "timestamp": "2024-01-15T12:00:00Z"
    }
  ]
}

Orders Channel

Real-time order updates for your account.

Subscribe:

{
  "type": "subscribe",
  "channel": "orders"
}

Data:

{
  "type": "order_update",
  "orderId": "12345678-1234-1234-1234-123456789012",
  "status": "filled",
  "filledQuantity": 0.1,
  "averagePrice": 49850.25,
  "timestamp": "2024-01-15T12:00:00Z"
}

Positions Channel

Real-time position updates for your account.

Subscribe:

{
  "type": "subscribe",
  "channel": "positions"
}

Data:

{
  "type": "position_update",
  "symbol": "BTC/USD",
  "quantity": 0.1,
  "unrealizedPnl": 150.75,
  "markPrice": 50000.0,
  "timestamp": "2024-01-15T12:00:00Z"
}

AI Signals Channel

Real-time AI trading signals.

Subscribe:

{
  "type": "subscribe",
  "channel": "signals",
  "symbols": ["BTC/USD", "ETH/USD"]
}

Data:

{
  "type": "signal",
  "symbol": "BTC/USD",
  "recommendation": "buy",
  "confidence": 87,
  "timeHorizon": "short_term",
  "reasoning": ["Strong bullish momentum detected", "High volume confirmation"],
  "timestamp": "2024-01-15T12:00:00Z"
}

Subscription Management

Subscribe to Multiple Channels

{
  "type": "subscribe",
  "channels": [
    { "channel": "ticker", "symbol": "BTC/USD" },
    { "channel": "orderbook", "symbol": "BTC/USD" },
    { "channel": "trades", "symbol": "BTC/USD" }
  ]
}

Unsubscribe from Channel

{
  "type": "unsubscribe",
  "channel": "ticker",
  "symbol": "BTC/USD"
}

Unsubscribe from All Channels

{
  "type": "unsubscribe_all"
}

Heartbeat and Connection Health

Ping/Pong Mechanism

Maintain connection health with regular ping messages.

Ping Message:

{
  "type": "ping"
}

Pong Response:

{
  "type": "pong",
  "timestamp": "2024-01-15T12:00:00Z"
}

Connection Monitoring

class ConnectionMonitor {
  constructor(websocket) {
    this.ws = websocket;
    this.lastPong = Date.now();
    this.pingInterval = 30000; // 30 seconds
    this.timeoutThreshold = 60000; // 60 seconds

    this.startPing();
    this.startMonitoring();
  }

  startPing() {
    setInterval(() => {
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(JSON.stringify({ type: "ping" }));
      }
    }, this.pingInterval);
  }

  startMonitoring() {
    setInterval(() => {
      const timeSinceLastPong = Date.now() - this.lastPong;

      if (timeSinceLastPong > this.timeoutThreshold) {
        console.warn("Connection timeout detected");
        this.handleConnectionTimeout();
      }
    }, 10000); // Check every 10 seconds
  }

  handlePong() {
    this.lastPong = Date.now();
  }

  handleConnectionTimeout() {
    // Implement reconnection logic
    console.log("Attempting to reconnect...");
    this.ws.close();
    // Trigger reconnection
  }
}

Error Handling

Connection Errors

ws.on("error", (error) => {
  console.error("WebSocket error:", error);

  switch (error.code) {
    case "ECONNREFUSED":
      console.log("Connection refused - server may be down");
      break;
    case "ENOTFOUND":
      console.log("DNS resolution failed");
      break;
    case "ETIMEDOUT":
      console.log("Connection timeout");
      break;
    default:
      console.log("Unknown connection error");
  }
});

Message Processing Errors

function handleMessage(rawMessage) {
  try {
    const message = JSON.parse(rawMessage);
    processMessage(message);
  } catch (error) {
    console.error("Failed to parse message:", error);
    console.log("Raw message:", rawMessage);
  }
}

Best Practices

Connection Management

  • Reconnection Logic: Implement automatic reconnection with exponential backoff
  • Heartbeat Monitoring: Monitor connection health with ping/pong
  • Error Handling: Handle all possible connection errors gracefully
  • Resource Cleanup: Properly close connections when done

Message Handling

  • Message Validation: Validate all incoming messages
  • Error Recovery: Handle malformed or unexpected messages
  • Rate Limiting: Respect message rate limits
  • Memory Management: Avoid memory leaks with large message volumes

Performance Optimization

  • Selective Subscriptions: Only subscribe to needed channels
  • Message Filtering: Filter messages on the client side
  • Connection Pooling: Use connection pooling for multiple streams
  • Compression: Enable WebSocket compression when available

Troubleshooting

Common Issues

Connection Refused

  • Check URL: Verify WebSocket URL is correct
  • Check Network: Ensure network connectivity
  • Check Firewall: Verify firewall allows WebSocket connections
  • Check SSL: Ensure WSS (secure) connections are supported

Authentication Failures

  • Check Credentials: Verify API key and secret are correct
  • Check Signature: Ensure signature generation is correct
  • Check Timestamp: Verify timestamp is within acceptable range
  • Check Permissions: Ensure API key has WebSocket permissions

Message Loss

  • Check Buffer: Monitor WebSocket buffer size
  • Check Processing: Ensure messages are processed quickly
  • Check Reconnection: Verify reconnection logic works correctly
  • Check Subscriptions: Ensure subscriptions are maintained after reconnection

Debugging Tools

  • Browser DevTools: Use WebSocket tab in browser dev tools
  • Wireshark: Monitor WebSocket traffic
  • Logging: Implement comprehensive logging
  • Health Checks: Monitor connection health metrics

Ready to start streaming data? Check out our WebSocket Events guide or explore Message Formats.