All files / services WebSocketService.js

0% Statements 0/58
0% Branches 0/6
0% Functions 0/20
0% Lines 0/58

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140                                                                                                                                                                                                                                                                                       
const logger = require('../utils/logger');
const jwt = require('jsonwebtoken');
 
class WebSocketService {
  constructor(io) {
    this.io = io;
    this.connectedUsers = new Map();
    this.rooms = new Map();
  }
 
  initialize() {
    this.io.on('connection', (socket) => {
      logger.info(`Client connected: ${socket.id}`);
 
      // Authenticate socket connection
      socket.on('authenticate', async (data) => {
        try {
          const { token } = data;
          const decoded = jwt.verify(token, process.env.JWT_SECRET);
          
          socket.userId = decoded.userId;
          socket.join(`user:${decoded.userId}`);
          
          this.connectedUsers.set(decoded.userId, socket.id);
          
          socket.emit('authenticated', { success: true });
          logger.info(`User ${decoded.userId} authenticated`);
        } catch (error) {
          logger.error('Socket authentication error:', error);
          socket.emit('authentication_error', { error: 'Invalid token' });
        }
      });
 
      // Subscribe to portfolio updates
      socket.on('subscribe:portfolio', () => {
        if (socket.userId) {
          socket.join(`portfolio:${socket.userId}`);
          logger.info(`User ${socket.userId} subscribed to portfolio updates`);
        }
      });
 
      // Subscribe to trade updates
      socket.on('subscribe:trades', () => {
        if (socket.userId) {
          socket.join(`trades:${socket.userId}`);
          logger.info(`User ${socket.userId} subscribed to trade updates`);
        }
      });
 
      // Subscribe to market data
      socket.on('subscribe:market', (data) => {
        const { pair } = data;
        socket.join(`market:${pair}`);
        logger.info(`Socket ${socket.id} subscribed to market:${pair}`);
      });
 
      // Unsubscribe from topics
      socket.on('unsubscribe', (data) => {
        const { topic } = data;
        socket.leave(topic);
        logger.info(`Socket ${socket.id} unsubscribed from ${topic}`);
      });
 
      // Handle disconnection
      socket.on('disconnect', () => {
        logger.info(`Client disconnected: ${socket.id}`);
        if (socket.userId) {
          this.connectedUsers.delete(socket.userId);
        }
      });
 
      // Handle errors
      socket.on('error', (error) => {
        logger.error('Socket error:', error);
      });
    });
 
    logger.info('WebSocket service initialized');
  }
 
  // Emit portfolio update to specific user
  emitPortfolioUpdate(userId, data) {
    this.io.to(`portfolio:${userId}`).emit('portfolio:update', data);
    logger.debug(`Portfolio update sent to user ${userId}`);
  }
 
  // Emit trade update to specific user
  emitTradeUpdate(userId, trade) {
    this.io.to(`trades:${userId}`).emit('trade:update', trade);
    logger.debug(`Trade update sent to user ${userId}`);
  }
 
  // Emit new trade to specific user
  emitNewTrade(userId, trade) {
    this.io.to(`user:${userId}`).emit('trade:new', trade);
    logger.debug(`New trade notification sent to user ${userId}`);
  }
 
  // Emit trade execution status
  emitTradeExecution(userId, status) {
    this.io.to(`user:${userId}`).emit('trade:execution', status);
    logger.debug(`Trade execution status sent to user ${userId}`);
  }
 
  // Emit market data update
  emitMarketUpdate(pair, data) {
    this.io.to(`market:${pair}`).emit('market:update', data);
  }
 
  // Emit notification to specific user
  emitNotification(userId, notification) {
    this.io.to(`user:${userId}`).emit('notification', notification);
    logger.debug(`Notification sent to user ${userId}:`, notification.message);
  }
 
  // Broadcast system message to all users
  broadcast(event, data) {
    this.io.emit(event, data);
    logger.info(`Broadcast sent: ${event}`);
  }
 
  // Check if user is connected
  isUserConnected(userId) {
    return this.connectedUsers.has(userId);
  }
 
  // Get connected users count
  getConnectedUsersCount() {
    return this.connectedUsers.size;
  }
 
  // Get all connected users
  getConnectedUsers() {
    return Array.from(this.connectedUsers.keys());
  }
}
 
module.exports = WebSocketService;