Positions Channel

Real-time position updates with initial snapshot.

Channel: positions
Authentication: Required


Subscribe

{
  "method": "subscribe",
  "params": {
    "channel": "positions",
    "market_ids": [1, 2],
    "makers": ["0x1234567890123456789012345678901234567890"]
  }
}
ParameterTypeRequiredDescription
market_idsnumber[]NoFilter by market IDs. Empty = all markets
makersstring[]NoFilter by account addresses. Empty = authenticated account only

Message Format

Snapshot

Sent immediately after subscribing. Contains all positions matching your filters.

{
  "method": "snapshot",
  "channel": "positions",
  "type": "snapshot",
  "data": [
    {
      "@type": "type.googleapis.com/boom.v1.api.BuilderPosition",
      "account": "0x1234567890123456789012345678901234567890",
      "market_id": "1",
      "size": "1000000000000000000",
      "quote_amount": "50000000000000000000000",
      "margin_mode": "CROSS",
      "side": "BUY",
      "isolated_usdc_balance": "0",
      "last_funding_payment": "0",
      "leverage": "5000000000000000000",
      "avg_entry_price": "50000000000000000000000",
      "block_number": "12345678",
      "log_index": "0",
      "block_timestamp": "1703123456000000000"
    }
  ],
  "position_count": 1,
  "timestamp": "1703123456123456789"
}

Update

Sent when a position changes (opened, modified, or closed).

{
  "channel": "positions",
  "type": "update",
  "market_id": "1",
  "data": [
    {
      "@type": "type.googleapis.com/boom.v1.api.BuilderPosition",
      "account": "0x1234567890123456789012345678901234567890",
      "market_id": "1",
      "size": "1500000000000000000",
      "quote_amount": "75000000000000000000000",
      "margin_mode": "CROSS",
      "side": "BUY",
      "isolated_usdc_balance": "0",
      "last_funding_payment": "-50000000000000000",
      "leverage": "5000000000000000000",
      "avg_entry_price": "50000000000000000000000",
      "block_number": "12345679",
      "log_index": "1",
      "block_timestamp": "1703123457000000000"
    }
  ],
  "block_number": 12345679,
  "log_index": 1,
  "tx_hash": "0xabc123...",
  "block_timestamp": "1703123457000000000",
  "timestamp": "1703123457123456789"
}

Snapshot Message Fields

FieldTypeDescription
methodstringAlways "snapshot"
channelstringAlways "positions"
typestringAlways "snapshot"
dataarrayArray of Position objects
position_countnumberTotal number of positions
timestampstringServer timestamp (nanoseconds)

Update Message Fields

FieldTypeDescription
channelstringAlways "positions"
typestringAlways "update"
market_idstringMarket ID
dataarrayArray of Position objects
block_numbernumberBlockchain block number
log_indexnumberLog index within the block
tx_hashstringTransaction hash (optional)
block_timestampstringBlockchain timestamp (nanoseconds)
timestampstringServer timestamp (nanoseconds)

Position Object Fields

FieldTypeDescription
@typestringProtobuf message type
accountstringPosition owner address
market_idstringMarket ID
sizestringPosition size (wei, 18 decimals). "0" = closed
quote_amountstringQuote amount (wei, 18 decimals). Represents cost basis
margin_modestringCROSS or ISOLATED
sidestringBUY (long) or SELL (short)
isolated_usdc_balancestringUSDC balance for isolated margin (wei, 18 decimals)
last_funding_paymentstringLast funding payment amount (wei, 18 decimals). Can be negative
leveragestringPosition leverage (wei, 18 decimals). e.g., "5000000000000000000" = 5x
avg_entry_pricestringWeighted average entry price (wei, 18 decimals)
block_numberstringBlock number of last update
log_indexstringLog index within the block
block_timestampstringBlock timestamp (nanoseconds)

Margin Modes

ModeDescription
CROSSCross margin - shares margin across all positions
ISOLATEDIsolated margin - separate margin per position

Position Closed

When a position is closed, size becomes "0":

{
  "channel": "positions",
  "type": "update",
  "market_id": "1",
  "data": [
    {
      "@type": "type.googleapis.com/boom.v1.api.BuilderPosition",
      "account": "0x1234567890123456789012345678901234567890",
      "market_id": "1",
      "size": "0",
      "quote_amount": "0",
      "margin_mode": "CROSS",
      "side": "BUY",
      "isolated_usdc_balance": "0",
      "last_funding_payment": "0",
      "leverage": "0",
      "avg_entry_price": "0",
      "block_number": "12345680",
      "log_index": "2",
      "block_timestamp": "1703123458000000000"
    }
  ],
  "block_number": 12345680,
  "log_index": 2,
  "tx_hash": "0xdef456...",
  "block_timestamp": "1703123458000000000",
  "timestamp": "1703123458123456789"
}

Calculating PnL

For long positions (side = BUY):

unrealizedPnL = (size * markPrice / 10^18) - quoteAmount

For short positions (side = SELL):

unrealizedPnL = quoteAmount - (size * markPrice / 10^18)

Examples

Subscribe to all your positions

{
  "method": "subscribe",
  "params": {
    "channel": "positions"
  }
}

Subscribe to specific markets

{
  "method": "subscribe",
  "params": {
    "channel": "positions",
    "market_ids": [1, 2]
  }
}

Subscribe to specific accounts

{
  "method": "subscribe",
  "params": {
    "channel": "positions",
    "market_ids": [1],
    "makers": ["0x1234567890123456789012345678901234567890"]
  }
}

Unsubscribe

{
  "method": "unsubscribe",
  "params": {
    "channel": "positions"
  }
}