# 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

JavaScript
- **Node.js** (version 16 or higher) - Download from [nodejs.org](https://nodejs.org/)
- **npm** or **yarn** (comes with Node.js)
- A code editor like **VS Code**


Python
- **Python** (version 3.7 or higher) - Download from [python.org](https://python.org/)
- **pip** (comes with Python)
- A code editor like **VS Code** or **PyCharm**


## 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

JavaScript
1. **Create a new project folder:**



```bash
mkdir trading-bot-client
cd trading-bot-client
```

1. **Initialize a new Node.js project:**



```bash
npm init -y
```

1. **Install required packages:**



```bash
npm install socket.io-client
```

1. **Create your main file:**



```bash
touch index.js
```

Python
1. **Create a new project folder:**



```bash
mkdir trading-bot-client
cd trading-bot-client
```

1. **Install required packages:**



```bash
pip install python-socketio aiohttp
```

1. **Create your main file:**



```bash
touch main.py
```

### 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

JavaScript
Create a file called `index.js`:


```javascript
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:**


```bash
node index.js
```

Python
Create a file called `main.py`:


```python
import socketio
import asyncio
import signal
import sys

API_KEY = 'YOUR_API_KEY'  # Replace with your actual API key
SERVER_URL = 'wss://api.sniperoo.app'

positions_sio = socketio.AsyncClient()

def subscribe_callback(data):
    """Callback for subscription confirmation which returns all open positions"""
    print('📬 Subscription confirmed!')
    print(f'  Received {len(data["openPositions"])} open positions.')
    # Uncomment the next line to print all open positions
    # print(data['openPositions'])
    for position in data['openPositions']:
        token_info = position['tokenExtraInfo']
        print(f'  Position #{position["id"]}: {token_info["tokenSymbol"]}')

async def subscribe_to_positions():
    print('🔄 Subscribing to positions...')
    await positions_sio.emit('subscribe_positions_api', {
        'apiKey': API_KEY
    }, namespace='/positions', callback=subscribe_callback)


# Positions event handlers
@positions_sio.event(namespace='/positions')
async def connect():
    print('✅ Connected to positions!')
    await subscribe_to_positions()


@positions_sio.event(namespace='/positions')
async def disconnect():
    print('❌ Disconnected from positions')


@positions_sio.on('position_created', namespace='/positions')
async def on_position_created(data):
    position = data['positionWithTransactions']
    token_info = position['tokenExtraInfo']
    print('🆕 New position created!')
    print(f'  Position #{position["id"]}: {token_info["tokenSymbol"]}')


@positions_sio.on('position_updated', namespace='/positions')
async def on_position_updated(data):
    print('📈 Position updated!')
    print(f'  Position #{data["position"]["id"]} - Type: {data["type"]}')


@positions_sio.on('position_transaction_added', namespace='/positions')
async def on_position_transaction_added(data):
    print('💰 New transaction in position!')
    transaction = data['positionTransaction']
    print(f'  Position #{transaction["positionId"]} - added new transaction with ID: {transaction["transactionId"]}')


async def main():
    """Main function to run the client"""
    try:
        print('🚀 Starting trading bot client...')

        await positions_sio.connect(SERVER_URL)
        await positions_sio.wait()

    except Exception as e:
        print(f'❌ Error: {e}')
    finally:
        await cleanup()


async def cleanup():
    """Clean shutdown"""
    print('\n👋 Shutting down...')
    await positions_sio.disconnect()


def signal_handler(sig, frame):
    """Handle Ctrl+C gracefully"""
    print('\n👋 Received shutdown signal...')
    asyncio.create_task(cleanup())
    sys.exit(0)


if __name__ == '__main__':
    # Register signal handler for graceful shutdown
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    # Run the main function
    asyncio.run(main())
```

**To run this:**


```bash
python main.py
```

## API Reference

### Namespaces

The WebSocket API is organized into two main namespaces:

| Namespace | Description | Methods & Events |
|  --- | --- | --- |
| `/orders` | For order-related updates | [Link](/websockets/order-subscribtion) |
| `/positions` | For position-related updates | [Link](/websockets/order-subscribtion) |


### 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.