Skip to main content

WebSocket

General Information

  • All data is returned in JSON format
  • All timestamps are in milliseconds (Unix epoch time)
  • A single connection can subscribe to multiple streams
  • The WebSocket server sends a ping frame every 30 seconds
  • If a pong frame is not received within 60 seconds, the connection will be closed
  • Maximum connection lifetime is 24 hours

Message Format

Request Format

All requests to the WebSocket server follow this format:

{
"method": "subscribe",
"params": {
"channels": ["trade@1_2", "depth@1_2"]
},
"id": 1
}

Request Fields:

FieldTypeDescription
methodSTRINGAction to perform: "subscribe" or "unsubscribe"
paramsOBJECTParameters for the method
channelsARRAYArray of channel names to subscribe/unsubscribe
idINTRequest ID for correlation with responses

Response Format

Server responses for subscription requests:

{
"result": "ok",
"id": 1
}

Stream Data Format

Stream updates are sent in this format:

{
"method": "subscription",
"params": {
"channel": "trade@1_2",
"result": {
// Stream-specific data
}
}
}

Available Streams

Trade Streams

Real-time trade executions for a specific market.

Channel Name: trade@{marketId}

Example: trade@1_2

Subscribe:

{
"method": "subscribe",
"params": {
"channels": ["trade@1_2"]
},
"id": 1
}

Stream Data:

{
"method": "subscription",
"params": {
"channel": "trade@1_2",
"result": {
"tradeId": "405100010000",
"marketId": "1_2",
"price": "2.3",
"quantity": "0.7",
"buyOrderId": "0xdb9d5d086b4755fb5e49819fef783f80fb98f893",
"sellOrderId": "0x766be3ed6e3296708885405c7766c6cc880cfafa",
"createdAt": 1758005316000,
"isBuyerMaker": false
}
}
}

Order Book Depth Streams

Real-time order book updates for a specific market.

Channel Name: depth@{marketId}

Example: depth@1_2

Subscribe:

{
"method": "subscribe",
"params": {
"channels": ["depth@1_2"]
},
"id": 1
}

Stream Data:

{
"method": "subscription",
"params": {
"channel": "depth@1_2",
"result": {
"marketId": "1_2",
"bids": [
["2.3", "10.5"],
["2.29", "25.0"]
],
"asks": [
["2.31", "15.0"],
["2.32", "30.0"]
],
"firstId": 42920,
"finalId": 42921,
"time": 1758096768006
}
}
}

Ticker Streams

24hr rolling window ticker statistics for all markets.

Channel Name: ticker (all markets only)

Subscribe:

{
"method": "subscribe",
"params": {
"channels": ["ticker"]
},
"id": 1
}

Stream Data:

{
"method": "subscription",
"params": {
"channel": "ticker",
"result": [
{
"marketId": "1_2",
"baseTokenId": "1",
"quoteTokenId": "2",
"price": "2.3",
"open24h": "2.1",
"high24h": "2.5",
"low24h": "2.0",
"volume24h": "150000.5",
"quoteVolume24h": "345001.15"
},
{
"marketId": "3_2",
"baseTokenId": "3",
"quoteTokenId": "2",
"price": "3500.0",
"open24h": "3400.0",
"high24h": "3600.0",
"low24h": "3350.0",
"volume24h": "1200.5",
"quoteVolume24h": "4200000.0"
}
]
}
}

Ticker Stream Response Fields:

FieldTypeDescription
resultARRAYArray of ticker data for all markets
marketIdSTRINGMarket identifier
baseTokenIdSTRINGBase token identifier
quoteTokenIdSTRINGQuote token identifier
priceSTRINGCurrent/last traded price
open24hSTRINGOpening price 24 hours ago
high24hSTRINGHighest price in last 24 hours
low24hSTRINGLowest price in last 24 hours
volume24hSTRINGBase token volume in last 24 hours
quoteVolume24hSTRINGQuote token volume in last 24 hours

User Event Streams

Real-time updates for user's orders and trades.

Channel Name: userEvent@{address}

Important: The address in the channel name is automatically converted to EIP-55 checksum format. For example, if you subscribe with a lowercase address, the stream will return with the checksummed version.

Example:

  • Input (lowercase): userEvent@0x000000000000000000000000000000000000abcd
  • Stream returns (checksummed): userEvent@0x000000000000000000000000000000000000ABcD

Subscribe:

{
"method": "subscribe",
"params": {
"channels": ["userEvent@0x000000000000000000000000000000000000ABcD"]
},
"id": 1
}

User Event Response Fields:

Common Fields (All Events):

FieldTypeDescription
topicSTRINGEvent topic: "ORDER" or "ACCOUNT"
eventTypeSTRINGEvent type (see Event Types table below)
eventTimeLONGEvent timestamp in milliseconds
blockNumberLONGBlockchain block number
accountAddressSTRINGAccount address
txHashSTRINGTransaction hash

ORDER Topic Fields (topic="ORDER"):

FieldTypeEvent TypesDescription
orderIdSTRINGALLOrder identifier (transaction hash)
marketIdSTRINGALLMarket identifier
sideSTRINGALL"BUY" or "SELL"
orderTypeSTRINGALLOrder type (LIMIT, MARKET, etc.)
orderModeINTEGERALLOrder mode: 0 = base token quantity, 1 = quote token quantity
origPriceSTRINGALLOriginal order price
origQtySTRINGALLOriginal order quantity
origQuoteOrderQtySTRINGALLOriginal quote order quantity
statusSTRINGALLOrder status: "NEW", "PARTIALLY_FILLED", "FILLED", "CANCELED", "REJECTED"
createdAtLONGALLOrder creation timestamp in milliseconds
executedQtySTRINGALLTotal cumulative executed quantity including this event
executedQuoteQtySTRINGALLTotal cumulative executed quote amount including this event
lastPriceSTRINGALLPrice from this event (0 for non-execution events)
lastQtySTRINGALLQuantity from this event (0 for non-execution events)
feeSTRINGALLFee from this event
feeTokenIdSTRINGALLFee token ID
tradeIdSTRINGALLTrade ID (empty for non-trade events)
isMakerBOOLEANALLTrue if maker order

ACCOUNT Topic Fields (topic="ACCOUNT"):

FieldTypeEvent TypesDescription
tokenIdSTRINGALLToken identifier
amountSTRINGALLAsset amount
fromAddressSTRINGTRANSFERSource address (sender)
toAddressSTRINGTRANSFERDestination address (receiver)

User Event Types:

ORDER Topic Events:

Event TypeDescription
NEWNew order placed
TRADEOrder execution/trade
CANCELOrder canceled
TRIGGERTrigger order activated
REJECTEDOrder was rejected by the system

ACCOUNT Topic Events:

Event TypeDescription
DEPOSITAsset deposit to the DEX
WITHDRAWAsset withdrawal from the DEX
TRANSFERAsset transfer between accounts

ORDER Topic Events

{
"method": "subscription",
"params": {
"channel": "userEvent@0x000000000000000000000000000000000000ABcD",
"result": {
"topic": "ORDER",
"eventType": "TRADE", // Event types: "NEW", "TRADE", "CANCEL", "TRIGGER", "REJECTED"
"eventTime": 1758182405000,
"blockNumber": 12345678,
"accountAddress": "0x000000000000000000000000000000000000ABcD",
"orderId": "0x99eaddbe1a31751b4aca11269d6e45bd9c18894190140fbd80c08053933a7949",
"txHash": "0x99eaddbe1a31751b4aca11269d6e45bd9c18894190140fbd80c08053933a7949",
"marketId": "5_2",
"side": "SELL", // "BUY" or "SELL"
"orderType": "LIMIT", // "LIMIT", "MARKET", "STOP_LOSS_LIMIT", "TAKE_PROFIT_LIMIT"
"orderMode": 0,
"origPrice": "0.2",
"origQty": "10",
"origQuoteOrderQty": "0",
"status": "FILLED", // NEW: "NEW" | TRADE: "PARTIALLY_FILLED" or "FILLED" | CANCEL: "CANCELED" | TRIGGER: "NEW" | REJECTED: "REJECTED"
"createdAt": 1758182405000,
"executedQty": "10", // Cumulative filled amount. NEW/TRIGGER/REJECTED: "0" | TRADE: cumulative | CANCEL: amount filled before cancellation
"executedQuoteQty": "2", // Cumulative filled quote value. Same rules as executedQty
"lastPrice": "0.2", // Price from this specific trade. NEW/CANCEL/TRIGGER/REJECTED: "0" | TRADE: actual trade price
"lastQty": "10", // Quantity from this specific trade. NEW/CANCEL/TRIGGER/REJECTED: "0" | TRADE: actual trade quantity
"fee": "0.0006", // Fee amount for this event. NEW/CANCEL/TRIGGER/REJECTED: "0" | TRADE: actual fee
"feeTokenId": "2", // Fee token ID. null if no fee
"tradeId": "4340900010000", // Trade ID. Empty string for non-TRADE events
"isMaker": false // Whether this was a maker order. Only relevant for TRADE events
}
}
}

Field Notes by Event Type:

  • NEW: Order placed. status="NEW", all execution fields (executedQty, executedQuoteQty, lastPrice, lastQty, fee) are "0", tradeId is empty.
  • TRADE: Order executed. status is "PARTIALLY_FILLED" or "FILLED". executedQty/executedQuoteQty show cumulative totals. lastPrice/lastQty show this specific trade's execution.
  • CANCEL: Order canceled. status="CANCELED". executedQty/executedQuoteQty show amounts filled before cancellation. lastPrice/lastQty are "0".
  • TRIGGER: Stop-loss/take-profit order activated. status="NEW" (order now active in orderbook). All execution fields are "0" as triggering is not an execution.
  • REJECTED: Order rejected by system. status="REJECTED", all execution fields are "0".

ACCOUNT Topic Events

{
"method": "subscription",
"params": {
"channel": "userEvent@0x000000000000000000000000000000000000ABcD",
"result": {
"topic": "ACCOUNT",
"eventType": "TRANSFER", // Event types: "DEPOSIT", "WITHDRAW", "TRANSFER"
"eventTime": 1758182700000,
"blockNumber": 12345710,
"accountAddress": "0x000000000000000000000000000000000000ABcD", // DEPOSIT: recipient | WITHDRAW: sender | TRANSFER: sender or receiver
"txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"tokenId": "2",
"amount": "25.5",
"fromAddress": "0x000000000000000000000000000000000000ABcD", // Only for TRANSFER events. The sender address
"toAddress": "0x1111111111111111111111111111111111111111" // Only for TRANSFER events. The receiver address
}
}
}

Field Notes by Event Type:

  • DEPOSIT: Asset deposited into the DEX. accountAddress is the recipient (matches ToAddress). fromAddress and toAddress are not included.
  • WITHDRAW: Asset withdrawn from the DEX. accountAddress is the initiator (matches FromAddress). fromAddress and toAddress are not included.
  • TRANSFER: Asset transferred between accounts. Two separate events are generated (one for sender, one for receiver). accountAddress matches the party receiving the event. fromAddress and toAddress fields indicate the transfer direction.

Subscription Management

Subscribe to Multiple Streams

You can subscribe to multiple streams in a single request:

{
"method": "subscribe",
"params": {
"channels": [
"trade@1_2",
"depth@1_2",
"ticker",
"userEvent@0x000000000000000000000000000000000000ABcD"
]
},
"id": 1
}

Unsubscribe from Streams

To unsubscribe from specific streams:

{
"method": "unsubscribe",
"params": {
"channels": ["trade@1_2", "depth@1_2"]
},
"id": 2
}

Connection Maintenance

Ping/Pong

The server sends ping frames every 30 seconds to maintain the connection. Your WebSocket client should automatically respond with pong frames. If you're implementing a custom client:

ws.on('ping', function() {
ws.pong(); // Respond to ping with pong
});