Game WebSocket API
The game WebSocket is the primary integration point between Velo's RGS and your frontend. It delivers real-time game state — round lifecycle, live odds, bet confirmations, and settlement results — over a single persistent connection.
No Price Feed Integration Needed
Velo handles all price sourcing internally (Binance for live prices, Pyth Network for settlement). Your frontend only needs to connect to this WebSocket and render the game state it receives. You do not need to integrate any price feeds yourself.
Connection
wss://your-rgs-host/ws/game/btc?gsid=YOUR_GAME_SESSION_IDThe gsid (game session ID) is obtained from the Game Launch API. It authenticates the player and links the WebSocket to their wallet session.
Message Format
All messages are JSON with a top-level type field:
json
{
"type": "round_start",
"round": { "id": 43, "entryPrice": 71310.25, ... }
}Server → Client Messages
snapshot
Sent once on connection — contains the current game state so your UI can render immediately:
json
{
"type": "snapshot",
"history": [
{ "price": 71280.00, "timestamp": 1710437280000 },
{ "price": 71282.25, "timestamp": 1710437280200 }
],
"round": {
"id": 42,
"entryPrice": 71284.50,
"startTime": 1710437400000,
"endTime": 1710437700000,
"duration": 300000,
"status": "active"
},
"odds": { "up": 1.82, "down": 2.05 }
}player_info
Sent after snapshot — contains the player's balance and any active bets to restore:
json
{
"type": "player_info",
"player_id": "550e8400-...",
"username": "JohnDoe",
"balance": 1500.00,
"currency": "USD",
"active_bets": [
{ "id": "bet-uuid", "side": "up", "stake": 100, "odds": 1.82, "result": "pending" }
]
}price_update
Live price tick, sent 5× per second. Use this to drive the chart:
json
{
"type": "price_update",
"price": 71290.75,
"remaining": 142000,
"timestamp": 1710437558000
}odds_update
Updated payout multipliers, sent approximately every second:
json
{
"type": "odds_update",
"up": 1.82,
"down": 2.05,
"sigma": 0.42,
"players_online": 34,
"pool_up": 2400.00,
"pool_down": 1800.00
}| Field | Description |
|---|---|
up / down | Payout multiplier for each side |
sigma | Current annualized volatility |
players_online | Connected WebSocket clients |
pool_up / pool_down | Total stakes on each side |
round_start
New 5-minute round begins:
json
{
"type": "round_start",
"round": {
"id": 43,
"entryPrice": 71310.25,
"startTime": 1710437700000,
"endTime": 1710438000000,
"duration": 300000,
"status": "active"
}
}round_lock
10-second lock buffer activates — no more bets accepted:
json
{
"type": "round_lock",
"round": {
"id": 43,
"entryPrice": 71310.25,
"startTime": 1710437700000,
"endTime": 1710438000000,
"duration": 300000,
"status": "locked"
}
}round_settle
Round settled via Pyth Network oracle — includes the verifiable proof URL:
json
{
"type": "round_settle",
"round": {
"id": 43,
"entryPrice": 71310.25,
"settlementPrice": 71342.80,
"startTime": 1710437700000,
"endTime": 1710438000000,
"duration": 300000,
"status": "settled",
"result": "up",
"pythVerificationUrl": "https://hermes.pyth.network/..."
}
}bet_confirmed
Sent to the player who placed the bet:
json
{
"type": "bet_confirmed",
"bet_id": "550e8400-...",
"round_id": 184721,
"side": "up",
"stake": 100.00,
"odds": 1.82,
"balance": 1400.00
}bet_settle
Sent per-player when their bet settles:
json
{
"type": "bet_settle",
"bet_id": "550e8400-...",
"player_id": "player-uuid",
"result": "win",
"payout": 182.00,
"balance": 1582.00
}cashout_result
Sent after a successful early cashout:
json
{
"type": "cashout_result",
"bet_id": "550e8400-...",
"cashout_value": 145.00,
"pyth_price": 71325.50,
"pyth_verification_url": "https://hermes.pyth.network/...",
"balance": 1545.00
}Client → Server Messages
place_bet
Place a bet on the current round:
json
{
"type": "place_bet",
"side": "up",
"stake": 100.00,
"odds": 1.82
}INFO
The player_id is resolved from the gsid session — you don't need to send it.
cashout_request
Request an early cashout on an active bet:
json
{
"type": "cashout_request",
"bet_id": "550e8400-...",
"side": "up",
"stake": 100.00,
"odds": 1.82
}pause
Operator pauses gameplay (AML/fraud/responsible gaming). All bet attempts are rejected until resumed.
json
{ "type": "pause" }Response: { "type": "paused" }
resume
Operator resumes gameplay after a pause.
json
{ "type": "resume" }Response: { "type": "resumed" }
balance_update
Operator notifies the game of an external deposit or withdrawal. The game forwards this to the player's UI.
json
{
"type": "balance_update",
"stake": 2500.00
}Response: { "type": "balance_update", "balance": 2500.00 }
TIP
The stake field is reused to carry the new balance value. The game forwards it as balance to the client.
Client Example
javascript
const ws = new WebSocket('wss://your-rgs-host/ws/game/btc?gsid=YOUR_GSID');
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case 'snapshot':
initChart(msg.history);
if (msg.round) setRound(msg.round);
break;
case 'player_info':
setBalance(msg.balance);
restoreBets(msg.active_bets);
break;
case 'price_update':
updateChart(msg.price);
break;
case 'odds_update':
updateOdds(msg.up, msg.down);
break;
case 'round_start':
resetRound(msg.round);
break;
case 'round_settle':
showResult(msg.round);
break;
case 'bet_confirmed':
confirmBet(msg);
break;
case 'bet_settle':
settleBet(msg);
break;
}
};
// Place a bet
ws.send(JSON.stringify({
type: 'place_bet',
side: 'up',
stake: 100,
odds: 1.82
}));