Skip to main content

Documentation Index

Fetch the complete documentation index at: https://hypernode-docs.polynode.dev/llms.txt

Use this file to discover all available pages before exploring further.

Two consensus layers

hypernode merges two data sources into one stream. Every event is tagged with its consensus state:
LayerconsensusWhat you seeLatency
Pre-consensus"pre"Cancel and modify actions before block commit~1s ahead of public API
Confirmed"confirmed"Every order, fill, cancellation, rejection after block commit~0.5s behind live
Pre-consensus events are raw user-submitted actions intercepted from the gossip protocol before validators commit them. Confirmed events are the validator output after matching, filling, or rejecting.

Event structure

{
  "block": 70852325,
  "timestamp": 1776147484247,
  "type": "cancel",
  "consensus": "pre",
  "user": "0x31ca8395cf837de08b24da3f660e77761dfb974b",
  "asset": "ALGO",
  "asset_id": 158,
  "data": {
    "cancels": [
      {"asset": 158, "oid": 380721371885}
    ]
  },
  "network": "mainnet"
}

Fields

FieldTypeDescription
typestringEvent type (see table below)
consensusstring"pre" (gossip) or "confirmed" (node)
timestampnumberUnix milliseconds
blocknumberL1 block number. Populated for pre-consensus events; 0 for confirmed events
userstringWallet address
assetstringHuman-readable asset name. Absent on scheduleCancel and setReferrer
asset_idnumberNumeric asset identifier. Present on pre-consensus events; may be absent on some confirmed events
dataanyEvent-specific payload. Usually an object, but a number for scheduleCancel and a string for setReferrer
networkstring"mainnet" or "testnet"

Event types

Confirmed events

These appear after the validator processes the action. Every order placed on HyperLiquid produces one of these:
TypeDescriptionKey data fields
orderNew resting limit order (data.status is "open")coin, side, px, sz, oid, tif
order_filledOrder filled immediatelycoin, side, px, sz, oid
order_canceledOrder was canceledcoin, side, px, sz, oid
order_rejectedOrder rejected (see rejection reasons below)coin, side, px, sz, status
fillTrade executioncoin, side (A/B), px, sz, dir, closedPnl, fee, liquidation
triggeredTrigger/stop order activated (rare)coin, side, px, sz
siblingFilledCanceledSibling order canceled due to fill (rare)coin, side, px, sz, oid
perpMaxPositionRejectedRejected due to max position limit (rare)coin, side, px, sz
The "order" type name covers new resting orders where data.status is "open". There is no separate order_open type on the wire. To identify new resting orders, filter for "order" and check data.status === "open".
Rejection reasons in data.status: badAloPxRejected, perpMarginRejected, insufficientSpotBalanceRejected, iocCancelRejected, reduceOnlyCanceled, reduceOnlyRejected, minTradeNtlRejected, selfTradeCanceled.

Pre-consensus events (from gossip protocol)

These arrive before the validator commits them to a block:
TypeDescriptionKey data fields
cancelCancel by order IDcancels[].asset, cancels[].oid
cancelByCloidCancel by client order IDcancels[].asset, cancels[].cloid
batchModifyModify existing ordersmodifies[].oid, modifies[].order.price/size
scheduleCancelDead man’s switchdata is a number (cancel timestamp)
setReferrerSet referral codedata is a string (referral code)
evmRawTxPre-block HyperEVM transactiondata (raw RLP-encoded signed tx hex string)

Confirmed order example

{
  "block": 0,
  "timestamp": 1776147483883,
  "type": "order",
  "consensus": "confirmed",
  "user": "0xfc667adba8d4e79a22cac8e8f6d2a5b5c17cfa94",
  "asset": "BTC",
  "data": {
    "status": "open",
    "coin": "BTC",
    "side": "B",
    "px": "74400.0",
    "sz": "0.04158",
    "oid": 380721383669,
    "orderType": "Limit",
    "tif": "Alo",
    "reduceOnly": false,
    "cloid": "0x000000334e47524d534c363834483736",
    "hash": "0x9d660b786cd389ac9edf04391b7dd901...",
    "builder": null,
    "origSz": "0.04158"
  },
  "network": "mainnet"
}

Fill example

{
  "block": 0,
  "timestamp": 1776147483883,
  "type": "fill",
  "consensus": "confirmed",
  "user": "0x9690bcfc16394e2bd25b00e83d6b06c9ab3f5de5",
  "asset": "HYPE",
  "data": {
    "coin": "HYPE",
    "side": "B",
    "px": "22.608",
    "sz": "442.0",
    "dir": "Close Short",
    "closedPnl": "0.920686",
    "fee": "0.035973",
    "feeToken": "USDC",
    "oid": 380721384070,
    "tid": 910601406,
    "hash": "0xa9a32c7c2b7fb452ab1c...",
    "crossed": true,
    "builder": null,
    "builderFee": null,
    "liquidation": null
  },
  "network": "mainnet"
}

Fill dir field values

ValueMeaning
Open LongNew long position opened
Open ShortNew short position opened
Close LongExisting long position closed
Close ShortExisting short position closed
Long > ShortPosition flipped from long to short
Short > LongPosition flipped from short to long
Buy / SellSpot market fills
The side field is separate: B = bid (buy order), A = ask (sell order).

Liquidation fill example

The data.liquidation field is always present on fill events. It is null when the fill is not part of a liquidation, and an object when it is. Do NOT check "liquidation" in data — that will be true for every fill. Check data.liquidation !== null instead.
Liquidation fills carry a populated data.liquidation object in addition to the standard fill fields. Use the liquidations_only filter to subscribe to only these events.
{
  "block": 0,
  "timestamp": 1776147612530,
  "type": "fill",
  "consensus": "confirmed",
  "user": "0xf27f22d0988f958837c4393284297377a00387ed",
  "asset": "SUI",
  "data": {
    "coin": "SUI",
    "side": "A",
    "px": "88.588",
    "sz": "142.0",
    "dir": "Close Long",
    "closedPnl": "-123.45",
    "fee": "0.0012",
    "feeToken": "USDC",
    "oid": 381234567890,
    "tid": 912345678,
    "hash": "0x3a4b5c...",
    "crossed": true,
    "liquidation": {
      "liquidatedUser": "0xf27f22d0988f958837c4393284297377a00387ed",
      "markPx": "88.588",
      "method": "market"
    }
  },
  "network": "mainnet"
}
Both sides of a liquidation (the liquidated user and the liquidator) appear as separate fill events with the same tid and hash. Correlate them using these shared fields to see the full liquidation flow. Liquidation object fields:
FieldDescription
liquidatedUserAddress of the account being liquidated
markPxMark price at the moment of liquidation
methodLiquidation method (currently "market" for all observed liquidations)

evmRawTx example (pre-block HyperEVM)

Every HyperEVM smart contract transaction appears as an evmRawTx event before it is included in a block. The data field is a hex string containing the full EIP-2718 envelope: a 1-byte tx type prefix followed by RLP-encoded transaction fields. There are no top-level decoded fields — you decode the hex to extract to, calldata, chainId, gas, etc.
{
  "block": 70861403,
  "timestamp": 1776225421823,
  "type": "evmRawTx",
  "consensus": "pre",
  "user": "0x000000362b9ddd0000000000333ce9b04c000000",
  "data": "02f8d48203e782071084b2d05e0085746a52...",
  "network": "mainnet"
}
The user field on evmRawTx events is a gossip internal identifier, not the transaction sender. To get the real sender, you must recover it from the signature during decoding.

Decoding data (Python)

The hex starts with the EIP-2718 tx type byte (0x02 for EIP-1559). Everything after that is RLP:
import rlp
from eth_hash.auto import keccak

def decode_evm_raw_tx(hex_data: str) -> dict:
    raw = bytes.fromhex(hex_data)
    tx_type = raw[0]

    if tx_type == 0x02:
        # EIP-1559: [chainId, nonce, maxPrioFee, maxFee, gas, to, value, data, accessList, v, r, s]
        decoded = rlp.decode(raw[1:])
        return {
            "tx_hash": "0x" + keccak(raw).hex(),
            "tx_type": tx_type,
            "chain_id": int.from_bytes(decoded[0], "big"),
            "nonce": int.from_bytes(decoded[1], "big"),
            "max_fee_per_gas": int.from_bytes(decoded[3], "big"),
            "gas_limit": int.from_bytes(decoded[4], "big"),
            "to": "0x" + decoded[5].hex() if decoded[5] else None,
            "value": int.from_bytes(decoded[6], "big"),
            "calldata": decoded[7].hex(),
            "function_selector": "0x" + decoded[7][:4].hex() if len(decoded[7]) >= 4 else None,
        }
    else:
        raise ValueError(f"Unsupported tx type: {tx_type}")

# Usage
event = {"type": "evmRawTx", "data": "02f8d4820..."}
decoded = decode_evm_raw_tx(event["data"])
print(decoded["to"], decoded["function_selector"], decoded["chain_id"])
# 0xa4ea0e42eaab32e638703db88da1192fb42517f4 0xf3dc4762 999
All observed evmRawTx events have been EIP-1559 (tx type 0x02). chainId is always 999 (HyperEVM mainnet). Measured lead time vs HyperLiquid’s public RPC: 250ms to 3 seconds, averaging ~1 second. See EVM RPC for pointer-back info on why the HL RPC cannot serve this data.

Pre-consensus cancel example

{
  "block": 70852325,
  "timestamp": 1776147484247,
  "type": "cancel",
  "consensus": "pre",
  "user": "0x31ca8395cf837de08b24da3f660e77761dfb974b",
  "asset": "ALGO",
  "asset_id": 158,
  "data": {
    "cancels": [
      {"asset": 158, "oid": 380721371885},
      {"asset": 158, "oid": 380721371886}
    ]
  },
  "network": "mainnet"
}

Prediction market events

Events for HIP-4 outcome tokens include a prediction object in the data:
{
  "type": "order",
  "consensus": "confirmed",
  "asset": "#39890",
  "data": {
    "coin": "#39890",
    "side": "B",
    "px": "0.95",
    "sz": "200",
    "prediction": {
      "outcome_id": 3989,
      "side_index": 0,
      "asset_id": 100039890
    }
  }
}
Outcome token naming: #{10 * outcome_id + side_index}. See Prediction Markets for details.

Timestamp

Unix milliseconds. To convert:
const date = new Date(event.timestamp);
from datetime import datetime
dt = datetime.fromtimestamp(event["timestamp"] / 1000)