Skip to main content

JavaScript / Node.js

Track all pending settlements

const WebSocket = require("ws");

const ws = new WebSocket("wss://ws.polynode.dev/ws?key=pn_live_YOUR_KEY");

ws.on("open", () => {
  ws.send(JSON.stringify({
    action: "subscribe",
    type: "settlements",
    filters: { status: "pending" }
  }));
});

ws.on("message", (data) => {
  const msg = JSON.parse(data);

  switch (msg.type) {
    case "snapshot":
      console.log(`Loaded ${msg.count} recent settlements`);
      break;
    case "settlement":
      const d = msg.data;
      console.log(
        `${d.status.toUpperCase()} | ${d.taker_side} ${d.taker_size} shares @ ${d.taker_price}`,
        `| "${d.market_title}" (${d.outcome})`
      );
      break;
    case "status_update":
      console.log(`Confirmed: ${msg.data.tx_hash} in ${msg.data.latency_ms}ms`);
      break;
    case "heartbeat":
      break; // ignore
  }
});

// Reconnect on close
ws.on("close", () => setTimeout(() => process.exit(1), 1000));

Whale alerts ($5K+)

const ws = new WebSocket("wss://ws.polynode.dev/ws?key=pn_live_YOUR_KEY");

ws.on("open", () => {
  ws.send(JSON.stringify({
    action: "subscribe",
    type: "large_trades",
    filters: { min_size: 5000 }
  }));
});

ws.on("message", (data) => {
  const msg = JSON.parse(data);
  if (msg.type === "settlement") {
    const d = msg.data;
    console.log(`WHALE ALERT: ${d.taker_side} $${d.taker_size.toFixed(0)} @ ${d.taker_price}`);
    console.log(`  Market: ${d.market_title} (${d.outcome})`);
    console.log(`  Wallet: ${d.taker_wallet}`);
    console.log(`  TX: ${d.tx_hash}`);
  }
});

Monitor a specific market by slug

ws.send(JSON.stringify({
  action: "subscribe",
  type: "markets",
  filters: {
    slugs: ["will-pete-hegseth-win-the-2028-us-presidential-election"],
    snapshot_count: 100 // Get last 100 events
  }
}));

Track a wallet

ws.send(JSON.stringify({
  action: "subscribe",
  type: "wallets",
  filters: {
    wallets: ["0xabcdef1234567890abcdef1234567890abcdef12"]
  }
}));
// Receives: settlements, trades, position changes, deposits, status updates
const ws = new WebSocket("wss://ws.polynode.dev/ws?key=pn_live_YOUR_KEY");

ws.on("open", () => {
  ws.send(JSON.stringify({
    action: "subscribe",
    type: "chainlink",
    filters: { feeds: ["BTC/USD"] }
  }));
});

ws.on("message", (data) => {
  const msg = JSON.parse(data);
  if (msg.type === "price_feed") {
    const d = msg.data;
    console.log(`BTC/USD: $${d.price.toFixed(2)} (bid: $${d.bid.toFixed(2)}, ask: $${d.ask.toFixed(2)})`);
  }
});

Settlements + price feeds on same connection

const ws = new WebSocket("wss://ws.polynode.dev/ws?key=pn_live_YOUR_KEY");

ws.on("open", () => {
  // Subscribe to both — they're independent streams
  ws.send(JSON.stringify({ action: "subscribe", type: "settlements" }));
  ws.send(JSON.stringify({ action: "subscribe", type: "chainlink" }));
});

ws.on("message", (data) => {
  const msg = JSON.parse(data);
  switch (msg.type) {
    case "settlement":
      console.log(`TRADE: ${msg.data.taker_side} ${msg.data.taker_size} @ ${msg.data.taker_price}`);
      break;
    case "price_feed":
      console.log(`BTC: $${msg.data.price.toFixed(2)}`);
      break;
  }
});

Python

asyncio client with reconnection

import asyncio
import json
import websockets

API_KEY = "pn_live_YOUR_KEY"
URL = f"wss://ws.polynode.dev/ws?key={API_KEY}"

async def connect():
    while True:
        try:
            async with websockets.connect(URL) as ws:
                # Subscribe to pending settlements
                await ws.send(json.dumps({
                    "action": "subscribe",
                    "type": "settlements",
                    "filters": {"status": "pending", "min_size": 100}
                }))

                async for message in ws:
                    msg = json.loads(message)

                    if msg["type"] == "snapshot":
                        print(f"Loaded {msg['count']} recent events")

                    elif msg["type"] == "settlement":
                        d = msg["data"]
                        print(f"{d['taker_side']} {d['taker_size']:.0f} @ {d['taker_price']:.2f}"
                              f" | {d.get('market_title', 'unknown')}")

                    elif msg["type"] == "status_update":
                        print(f"Confirmed: {msg['data']['tx_hash'][:16]}..."
                              f" ({msg['data']['latency_ms']}ms)")

        except (websockets.ConnectionClosed, ConnectionError) as e:
            print(f"Disconnected: {e}. Reconnecting in 3s...")
            await asyncio.sleep(3)

asyncio.run(connect())

Multiple wallet subscriptions

const ws = new WebSocket("wss://ws.polynode.dev/ws?key=pn_live_YOUR_KEY");
const subscriptionIds = [];

ws.on("open", () => {
  // Subscribe to multiple wallet groups — each creates an independent subscription
  ws.send(JSON.stringify({
    action: "subscribe",
    type: "wallets",
    filters: { wallets: ["0xWallet1...", "0xWallet2..."] }
  }));

  ws.send(JSON.stringify({
    action: "subscribe",
    type: "wallets",
    filters: { wallets: ["0xWallet3...", "0xWallet4..."] }
  }));
});

ws.on("message", (data) => {
  const msg = JSON.parse(data);

  if (msg.type === "subscribed") {
    // Save subscription_id for targeted unsubscribe later
    subscriptionIds.push(msg.subscription_id);
    console.log(`Subscribed: ${msg.subscription_id}`);
  }

  if (msg.type === "settlement") {
    console.log(`${msg.data.taker_side} ${msg.data.taker_size} @ ${msg.data.taker_price}`);
  }
});

// Later: remove just one subscription
// ws.send(JSON.stringify({ action: "unsubscribe", subscription_id: subscriptionIds[0] }));

// Or remove all
// ws.send(JSON.stringify({ action: "unsubscribe" }));

wscat (CLI)

Quick testing from the command line:
# Install
npm install -g wscat

# Connect
wscat -c "wss://ws.polynode.dev/ws?key=pn_live_YOUR_KEY"

# Once connected, paste:
{"action": "subscribe", "type": "settlements", "filters": {"status": "pending"}}
# Subscribe to Chainlink BTC/USD prices
{"action": "subscribe", "type": "chainlink"}

# Subscribe to whale trades (stacks with previous subscriptions)
{"action": "subscribe", "type": "large_trades", "filters": {"min_size": 10000}}

# Subscribe by market slug
{"action": "subscribe", "type": "markets", "filters": {"slugs": ["bitcoin-100k-2026"]}}

# Ping
{"action": "ping"}

# Unsubscribe a specific subscription (use the subscription_id from the ack)
{"action": "unsubscribe", "subscription_id": "abc123:1"}

# Unsubscribe all
{"action": "unsubscribe"}

curl (WebSocket upgrade)

# Using websocat (Rust CLI tool)
websocat "wss://ws.polynode.dev/ws?key=pn_live_YOUR_KEY"

# Then type:
{"action":"subscribe","type":"settlements"}

Common patterns

Reconnection with exponential backoff

function createConnection() {
  let delay = 1000;

  function connect() {
    const ws = new WebSocket("wss://ws.polynode.dev/ws?key=pn_live_YOUR_KEY");

    ws.onopen = () => {
      delay = 1000; // Reset backoff
      ws.send(JSON.stringify({
        action: "subscribe",
        type: "settlements"
      }));
    };

    ws.onclose = () => {
      console.log(`Reconnecting in ${delay}ms...`);
      setTimeout(connect, delay);
      delay = Math.min(delay * 2, 30000); // Max 30s
    };

    ws.onmessage = (event) => {
      const msg = JSON.parse(event.data);
      if (msg.type !== "heartbeat") {
        handleEvent(msg);
      }
    };
  }

  connect();
}

Pending-to-confirmed tracking

const pending = new Map();

function handleEvent(msg) {
  if (msg.type === "settlement" && msg.data.status === "pending") {
    pending.set(msg.data.tx_hash, {
      ...msg.data,
      received_at: Date.now()
    });
    console.log(`PENDING: ${msg.data.taker_side} ${msg.data.taker_size} @ ${msg.data.taker_price}`);
  }

  if (msg.type === "status_update") {
    const original = pending.get(msg.data.tx_hash);
    if (original) {
      console.log(`CONFIRMED: ${msg.data.latency_ms}ms latency, block ${msg.data.block_number}`);
      pending.delete(msg.data.tx_hash);
    }
  }
}