websockets / ws

Simple to use, blazing fast and thoroughly tested WebSocket client and server for Node.js
MIT License
21.74k stars 2.42k forks source link

How to connect to multiple servers and listen their messages? #2259

Closed TheGP closed 2 weeks ago

TheGP commented 2 weeks ago

Is there an existing issue for this?

Description

I want to connect to multiple different servers and listens messages from them

ws version

8.18.0

Node.js Version

22.6.0

System

No response

Expected result

No response

Actual result

It only receives messages from one of the servers (ws.on('message',)

Attachments

No response

TheGP commented 2 weeks ago

Example of the code, for it to work add more wss servers by registering on https://www.helius.dev/ or https://shyft.to/ and find wss endpoints

import WebSocket from 'ws';
import fetch from 'node-fetch';

const walletAddress = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"; // raydium liquidity pool
const seenSignatures = new Set();

const endpoints = [
    {
        ws: "wss://api.mainnet-beta.solana.com"
    },
    {
        was: "add more"
    },
];

// Initialize results object with domains
const results = {
    signatures: {},
    tokens: {},
    disconnects: {}
};

function getDomain(url) {
    try {
        if (!url || typeof url !== 'string') return null;
        const urlObject = new URL(url);
        const hostnameParts = urlObject.hostname.split('.');

        if (hostnameParts.length > 2 && 
                hostnameParts[hostnameParts.length - 2].length <= 3 && 
                hostnameParts[hostnameParts.length - 1].length <= 3) {
            return hostnameParts.slice(-3).join('.');
        }
        return hostnameParts.slice(-2).join('.');
    } catch (error) {
        console.error('Error parsing domain:', error);
        return null;
    }
}

function createWebSocketConnection(endpoint) {
    const domain = getDomain(endpoint.ws);
    let ws = null;
    let reconnectAttempts = 0;
    const maxReconnectAttempts = 5;

    const connect = () => {
        try {
            ws = new WebSocket(endpoint.ws);

            ws.on('open', () => {
                console.log(`Connected to ${domain}`);
                reconnectAttempts = 0;

                ws.send(JSON.stringify({
                    "jsonrpc": "2.0",
                    "id": 1,
                    "method": "logsSubscribe",
                    "params": [
                        { "mentions": [walletAddress] },
                        { "commitment": "finalized" }
                    ]
                }));
            });

            ws.on('message', async (data) => {
                try {
                    const response = JSON.parse(data);
                    if (response.params?.result?.value?.err === null) {
                        const signature = response.params.result.value.signature;
                        if (!seenSignatures.has(signature)) {
                            seenSignatures.add(signature);
                            const logMessages = new Set(response.params.result.value.logs);
                            if (Array.from(logMessages).some(msg => msg.includes("initialize2"))) {
                                console.log(`${domain}: New pool signature detected:`, signature);
                                results.signatures[domain].push(signature);
                            }
                        }
                    }
                } catch (e) {
                    console.error(`${domain}: Error processing message:`, e);
                }
            });

            ws.on('error', (error) => {
                console.error(`${domain}: WebSocket error:`, error);
            });

            ws.on('close', () => {
                results.disconnects[domain].push(new Date());
                console.log(`${domain}: Disconnected. Attempt ${reconnectAttempts + 1} of ${maxReconnectAttempts}`);

                if (reconnectAttempts < maxReconnectAttempts) {
                    reconnectAttempts++;
                    const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);
                    setTimeout(connect, delay);
                } else {
                    console.error(`${domain}: Max reconnection attempts reached. Giving up.`);
                }
            });
        } catch (error) {
            console.error(`${domain}: Error creating WebSocket connection:`, error);
        }
    };

    return connect;
}

function showResults() {
    console.log('\n=== RESULTS ===');
    for (const [category, domainData] of Object.entries(results)) {
        console.log(`\n${category.toUpperCase()}:`);
        for (const [domain, items] of Object.entries(domainData)) {
            console.log(`${domain}: ${items.length}`);
        }
    }
    console.log('\n');
}

function initialize() {
    // Initialize results structure
    endpoints.forEach(endpoint => {
        const domain = getDomain(endpoint.ws);
        if (domain) {
            results.signatures[domain] = [];
            results.tokens[domain] = [];
            results.disconnects[domain] = [];
        }
    });

    // Create connections
    endpoints.forEach(endpoint => {
        const connect = createWebSocketConnection(endpoint);
        connect();
    });

    // Set up results display interval
    setInterval(showResults, 60000);

    // Handle graceful shutdown
    process.on('SIGINT', () => {
        console.log('\nShutting down...');
        showResults();
        process.exit();
    });
}

initialize();
lpinca commented 2 weeks ago

Use a different WebSocket for each server.

const ws1 = new WebSocket(server1Url);

ws1.on('message', function () {
  console.log('message from server1');
});

const ws2 = new WebSocket(server2Url);

ws2.on('message', function () {
  console.log('message from server2');
});