#!/usr/bin/env node /** * WebSocket Test Client * Simple script to test WebSocket connection and subscriptions * * Usage: * node test-websocket.js */ const WebSocket = require('ws'); const WS_URL = 'ws://localhost:3000/ws'; console.log('OrbiQuant WebSocket Test Client'); console.log('================================\n'); const ws = new WebSocket(WS_URL); let messageCount = 0; const startTime = Date.now(); ws.on('open', () => { console.log('āœ… Connected to WebSocket server'); console.log(` URL: ${WS_URL}\n`); // Subscribe to multiple channels console.log('šŸ“” Subscribing to channels...'); ws.send(JSON.stringify({ type: 'subscribe', channels: [ 'price:BTCUSDT', 'ticker:ETHUSDT', 'klines:BTCUSDT:1m' ] })); }); ws.on('message', (data) => { messageCount++; const msg = JSON.parse(data.toString()); const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); switch (msg.type) { case 'connected': console.log(`\nšŸ”Œ Server welcome message:`); console.log(` Client ID: ${msg.data.clientId}`); console.log(` Authenticated: ${msg.data.authenticated}`); console.log(` Timestamp: ${msg.data.timestamp}\n`); break; case 'subscribed': console.log(`āœ… Subscribed to: ${msg.channel}`); break; case 'price': console.log(`[${elapsed}s] šŸ’° PRICE UPDATE - ${msg.data.symbol}`); console.log(` Price: $${msg.data.price.toLocaleString()}`); console.log(` 24h Change: ${msg.data.changePercent24h >= 0 ? '+' : ''}${msg.data.changePercent24h.toFixed(2)}%`); console.log(` Volume: ${msg.data.volume24h.toLocaleString()}\n`); break; case 'ticker': console.log(`[${elapsed}s] šŸ“Š TICKER UPDATE - ${msg.data.symbol}`); console.log(` Price: $${msg.data.price.toLocaleString()}`); console.log(` Bid/Ask: $${msg.data.bid} / $${msg.data.ask}`); console.log(` 24h: ${msg.data.changePercent >= 0 ? '+' : ''}${msg.data.changePercent.toFixed(2)}%`); console.log(` High/Low: $${msg.data.high} / $${msg.data.low}\n`); break; case 'kline': const kline = msg.data; console.log(`[${elapsed}s] šŸ“ˆ KLINE UPDATE - ${kline.symbol} (${kline.interval})`); console.log(` O: $${kline.open} H: $${kline.high} L: $${kline.low} C: $${kline.close}`); console.log(` Volume: ${kline.volume.toFixed(4)}`); console.log(` Status: ${kline.isFinal ? 'āœ“ Closed' : 'ā³ Updating'}\n`); break; case 'trade': console.log(`[${elapsed}s] šŸ’ø TRADE - ${msg.data.symbol}`); console.log(` ${msg.data.side.toUpperCase()}: ${msg.data.quantity} @ $${msg.data.price}\n`); break; case 'pong': console.log(`[${elapsed}s] šŸ“ Pong received (heartbeat OK)\n`); break; case 'error': console.error(`[${elapsed}s] āŒ ERROR:`); console.error(` ${msg.data.message}\n`); break; default: console.log(`[${elapsed}s] šŸ“Ø ${msg.type}:`, JSON.stringify(msg.data || {}, null, 2), '\n'); } }); ws.on('error', (error) => { console.error('\nāŒ WebSocket Error:', error.message); console.error('\nTroubleshooting:'); console.error('1. Make sure backend server is running: npm run dev'); console.error('2. Check if port 3000 is accessible'); console.error('3. Verify WebSocket endpoint: ws://localhost:3000/ws\n'); }); ws.on('close', () => { console.log(`\nšŸ‘‹ Disconnected from server`); console.log(` Total messages received: ${messageCount}`); console.log(` Duration: ${((Date.now() - startTime) / 1000).toFixed(1)}s\n`); process.exit(0); }); // Send ping every 30 seconds const pingInterval = setInterval(() => { if (ws.readyState === WebSocket.OPEN) { console.log('šŸ“ Sending ping...'); ws.send(JSON.stringify({ type: 'ping' })); } }, 30000); // Auto-disconnect after 60 seconds (for testing) setTimeout(() => { console.log('\nā° Test duration reached (60s), disconnecting...'); clearInterval(pingInterval); ws.close(); }, 60000); // Handle Ctrl+C gracefully process.on('SIGINT', () => { console.log('\n\nāš ļø Interrupted by user'); clearInterval(pingInterval); ws.close(); }); console.log('ā³ Connecting to WebSocket server...'); console.log(' (Test will run for 60 seconds, or press Ctrl+C to stop)\n');