Skip to content
Last updated

Listening to real-time position and order updates using Websockets

Overview

This WebSocket API allows you to get real-time updates about your trading orders and positions. Think of it like a live notification system - whenever something happens with your trades (like an order getting filled or a position being created), you'll get instant updates.

Prerequisites

    • Node.js (version 16 or higher) - Download from nodejs.org
    • npm or yarn (comes with Node.js)
    • A code editor like VS Code

    How WebSockets Work

    WebSockets create a persistent connection between your application and our server. Unlike regular HTTP requests that you send and forget, WebSockets keep the connection open so the server can send you updates instantly when something happens.

    Phone Call vs Letters
    • HTTP requests = Sending letters (you send, wait for response, send again)
    • WebSockets = Phone call (continuous two-way communication)

    Quick Start

    Installation

      1. Create a new project folder:
      mkdir trading-bot-client
      cd trading-bot-client
      1. Initialize a new Node.js project:
      npm init -y
      1. Install required packages:
      npm install socket.io-client
      1. Create your main file:
      touch index.js

      Configuration

      Base URL

      wss://api.sniperoo.app
      API Key Required

      You'll need an API Key to connect. This is like a password that identifies your account. You should have received this when you signed up.

      Complete Working Examples

        Create a file called index.js:

        const { io } = require('socket.io-client');
        
        // Your configuration
        const API_KEY = 'YOUR_API_KEY'; // Replace with your actual API key
        
        const SERVER_URL = 'wss://api.sniperoo.app';
        
        // Create connections to both orders and positions
        const ordersSocket = io(`${SERVER_URL}/orders`, {
            transports: ['websocket']
        });
        
        const positionsSocket = io(`${SERVER_URL}/positions`, {
            transports: ['websocket']
        });
        
        // Function to start listening for orders
        async function subscribeToOrders() {
            console.log('🔄 Subscribing to orders...');
        
            const activeOrders =  await ordersSocket.emitWithAck('subscribe_orders_api', {
                apiKey: API_KEY
            });
        
            console.log(`Received ${activeOrders['orders'].length} active orders`);
            // Uncomment the line below to log the active orders
            // console.log(JSON.stringify(activeOrders));
        
        }
        
        // Function to start listening for positions
        async function subscribeToPositions() {
            console.log('🔄 Subscribing to positions...');
        
            const res = await positionsSocket.emitWithAck('subscribe_positions_api', {
                apiKey: API_KEY
            });
            
            console.log(`Received ${res['openPositions'].length} open positions`);
            // Uncomment the line below to log the open positions
            // console.log(JSON.stringify(res['openPositions']));
        }
        
        // Handle successful connections
        ordersSocket.on('connect', () => {
            console.log('✅ Connected to orders!');
            subscribeToOrders();
        });
        
        positionsSocket.on('connect', () => {
            console.log('✅ Connected to positions!');
            subscribeToPositions();
        });
        
        // Listen for real-time order events
        ordersSocket.on('order_created', (data) => {
            const order = data.order.order;
            console.log('🆕 New order created!');
            console.log(`  Order #${order.id}: ${order.orderType} ${data.order.tokenExtraInfo.tokenSymbol}`);
        });
        
        ordersSocket.on('order_executed', (data) => {
            console.log('✅ Order executed!');
            console.log(`  Order #${data.order.id} has been filled`);
        });
        
        ordersSocket.on('order_cancelled', (data) => {
            console.log('❌ Order cancelled');
            console.log(`  Order #${data.order.id} was cancelled`);
        });
        
        ordersSocket.on('order_failed', (data) => {
            console.log('💥 Order failed');
            console.log(`  Order #${data.order.id} failed to execute`);
        });
        
        ordersSocket.on('order_expire', (data) => {
            console.log('⏰ Order expired');
            console.log(`  Order #${data.order.id} has expired`);
        });
        
        // Listen for real-time position events
        positionsSocket.on('position_created', (data) => {
            const position = data.positionWithTransactions;
            console.log('🆕 New position created!');
            console.log(`  Position #${position.id}: ${position.tokenExtraInfo.tokenSymbol}`);
            if (position.toastFrontendId) {
                console.log(`  Frontend Toast ID: ${position.toastFrontendId}`);
            }
        });
        
        positionsSocket.on('position_updated', (data) => {
            console.log('📈 Position updated!');
            console.log(`  Position #${data.position.id} - Type: ${data.type}`);
            if (data.position.toastFrontendId) {
                console.log(`  Frontend Toast ID: ${data.position.toastFrontendId}`);
            }
        });
        
        positionsSocket.on('position_transaction_added', (data) => {
            console.log('💰 New transaction in position!');
            console.log(`  Position #${data.positionTransaction.positionId} - added new transaction with ID: ${data.positionTransaction.transactionId}`);
            if (data.toastFrontendId) {
                console.log(`  Frontend Toast ID: ${data.toastFrontendId}`);
            }
        });
        
        // Handle disconnections
        ordersSocket.on('disconnect', () => {
            console.log('❌ Disconnected from orders');
        });
        
        positionsSocket.on('disconnect', () => {
            console.log('❌ Disconnected from positions');
        });
        
        // Graceful shutdown
        process.on('SIGINT', () => {
            console.log('\n👋 Shutting down...');
            ordersSocket.disconnect();
            positionsSocket.disconnect();
            process.exit();
        });
        
        console.log('🚀 Starting trading bot client...');
        

        To run this:

        node index.js

        API Reference

        Namespaces

        The WebSocket API is organized into two main namespaces:

        NamespaceDescriptionMethods & Events
        /ordersFor order-related updatesLink
        /positionsFor position-related updatesLink

        Authentication

        All API subscriptions require a valid API key included in the subscription payload.

        Troubleshooting

        Connection Issues

        "Connection refused"

        • Check your server URL is correct
        • Make sure the server is running
        • Verify you're using the right protocol (ws:// or wss://)

        Authentication Issues

        "please_refresh" message

        • Your client is outdated, restart your application
        • Make sure you're sending the correct payload format with apiKey

        No events received

        • Check your API key is valid
        • Verify you're subscribed to the right namespace
        • Make sure your account has orders/positions

        Environment Issues

        Python: "Module not found"

        • Run pip install python-socketio aiohttp if you haven't installed the packages yet

        JavaScript: "Cannot find module"

        • Run npm install socket.io-client in your project folder

        Next Steps

        1. Start Simple: Run the basic examples first to see if you get connected
        2. Add Your Logic: Once connected, add your own code to handle the events
        3. Error Handling: Add proper error handling for production use
        4. Logging: Consider adding file logging to track what happens
        5. Database: Store the events in a database for analysis
        Remember

        Replace the placeholder values (API_KEY) with your actual value before running the examples.