WebSocket API
Prediction Market — WebSocket Push API (Integration Guide)
1. Field Format Specification
1.1 amount (Money)
CodeRule: truncate to 2 decimal places (DOWN mode, towards zero) Examples: 2.5678 → "2.56" 0.009 → "<0.01" ← Unified display for amounts < 0.01 null → "<0.01" 100 → "100.00"
Integration tips:
- Render the
amountfield directly to the user - For precise numerical computation, fetch via REST API — do NOT reverse-parse this field
1.2 topic (Market Title)
CodeRule: if longer than 12 chars, truncate and append ".." (max 14 chars total) Examples: "BTC will hit 100K" → "BTC will hi.." "Short title" → "Short title" null → ""
1.3 outcome (Outcome Name)
CodeRule: passed through as-is, not truncated Possible values: "Yes" / "No" (binary markets) "Trump" / "Biden" / … (multi-outcome markets) "" (when data is missing)
1.4 pushId (Idempotency Key)
Format: see Wallet Events WebSocket API Section 3.3. Present in every topic, strongly recommended for client-side deduplication.
2. End-to-End Integration Example
2.1 Full Flow
Code1. Acquire API Key + Secret Key under user's logged-in session via REST API 2. Prepare timestamp + random 3. Sort all URL parameters alphabetically and concatenate 4. Compute signature with HMAC SHA256 5. Build the full WSS URL 6. Open WebSocket connection with header X-MBX-APIKEY 7. on('open') → connection established; send SUBSCRIBE if not in URL 8. on('message') → parse the message (outer JSON, then inner JSON) 9. on('close') → trigger reconnect logic (regenerate timestamp + signature) 10. setInterval 30s → send empty PING frame
2.2 Node.js Sample
Codeconst WebSocket = require("ws"); const crypto = require("crypto"); const API_KEY = process.env.BINANCE_API_KEY; const SECRET_KEY = process.env.BINANCE_SECRET_KEY; const BASE_URL = "wss://api.binance.com/sapi/wss"; // All prediction topics to subscribe const TOPICS = ["web3_prediction_pm_market_buy_success", "web3_prediction_pm_market_buy_fail", "web3_prediction_pm_market_sell_success", "web3_prediction_pm_market_sell_fail", "web3_prediction_pm_limit_submit_success", "web3_prediction_pm_limit_submit_fail", "web3_prediction_pm_limit_order_filled", "web3_prediction_pm_limit_order_partial_fill", "web3_prediction_pm_claim_success", "web3_prediction_pm_claim_fail", "web3_prediction_pm_claim_partial_success", "web3_prediction_pm_transfer_success", "web3_prediction_pm_transfer_fail", "web3_prediction_pm_market_close"]; function buildConnectionUrl() { const params = { random: crypto.randomBytes(16).toString("hex"), topic: TOPICS.join("|"), recvWindow: "30000", timestamp: Date.now().toString(), }; const sortedKeys = Object.keys(params).sort(); const payload = sortedKeys.map((k) => `${k}=${params[k]}`).join("&"); const signature = crypto.createHmac("sha256", SECRET_KEY).update(payload).digest("hex"); return `${BASE_URL}?${payload}&signature=${signature}`; } const seenPushIds = new Set(); // For production, replace with a proper LRU cache function connect() { const url = buildConnectionUrl(); const ws = new WebSocket(url, [], { headers: { "X-MBX-APIKEY": API_KEY }, }); ws.on("open", () => { console.log("[ws] connected"); // Heartbeat setInterval(() => { if (ws.readyState === WebSocket.OPEN) ws.ping(); }, 30_000); }); ws.on("message", (raw) => { const envelope = JSON.parse(raw.toString()); // Command response if (envelope.type === "COMMAND") { console.log("[ws] command response:", envelope); return; } // Business push if (envelope.type === "TOPIC") { const payload = JSON.parse(envelope.data); // ⚠️ data is a stringified JSON handlePredictionPush(envelope.topic, payload); } }); ws.on("close", (code, reason) => { console.warn("[ws] closed", code, reason.toString()); setTimeout(connect, 3_000); // Simple reconnect; use exponential backoff in production }); ws.on("error", (err) => { console.error("[ws] error", err); }); return ws; } function handlePredictionPush(topic, payload) { // 1. Idempotency if (seenPushIds.has(payload.pushId)) return; seenPushIds.add(payload.pushId); // 2. Extract scenarioCode (strip topic prefix) const scenarioCode = topic.replace("web3_prediction_", ""); // 3. Field fallbacks const amount = payload.amount ?? "<0.01"; const marketTopic = payload.topic ?? "the market"; const outcome = payload.outcome ?? ""; // 4. Dispatch by scenario switch (scenarioCode) { case "pm_market_buy_success": console.log(`Bought ${amount} USDT in ${marketTopic}`); break; case "pm_claim_success": console.log(`Successfully claimed ${amount} USDT.`); break; case "pm_claim_fail": console.log(`Failed to claim ${amount} from ${outcome}.`); break; case "pm_market_close": console.log(`Market ${marketTopic} resolved.`); break; // ... other 11 scenarios default: console.log(`[unknown scenario] ${scenarioCode}`, payload); } } connect();
2.3 End-to-End Business Example: Limit BUY Flow
CodeT+0s User submits a limit order ← Topic: pm_limit_submit_success ← data: {"pushId":"pm_O1_pm_limit_submit_success_xx","amount":"100.00","topic":"BTC will hi.."} T+30s Partial liquidity matched ← Topic: pm_limit_order_partial_fill ← data: {"pushId":"pm_O1_pm_limit_order_partial_fill_yy","amount":"30.00","topic":"BTC will hi.."} T+5min Fully filled ← Topic: pm_limit_order_filled ← data: {"pushId":"pm_O1_pm_limit_order_filled_zz","amount":"100.00","topic":"BTC will hi.."}
Was this page helpful?
Last modified on