This section is a collection of extra documentation on the workings of Hyperliquid L1. It is not exhaustive, rather it complements the Hyperliquid Docs. For each section under Sources where the Parent is
  • Datastreams then entity is the Kafka Topic name
  • Snowflake then the entity is the table name

Assets

In a lot of the data sources, especially datastreams and tables in the raw schema you will find assets listed as a number.This is how Hyperliquid refers to them. They are normally a trading Pair.
Where the asset is simply an index.Perpetuals - index in the universe field returned by the meta response.Spot - 10000 + index in the universe field returned by the spotMeta response.For example, when submitting an order for PURR/USDC, theset that should be used is 10000 because its asset index in the spot metadata is 0.

Spot

Spot Pairs are prefixed by an @
The Spot Pair PURR/USDC is the only one not referred to by an @index and instead you will see it referred by PURR/USDC
You can fetch the Hyperliquid Spot metadata here. Samples
{
  "tokens": [
...
    {
      "name": "HYPE",
      "szDecimals": 2,
      "weiDecimals": 8,
      "index": 150,
      "tokenId": "0x0d01dc56dcaaca66ad901c959b4011ec",
      "isCanonical": false,
      "evmContract": null,
      "fullName": "Hyperliquid",
      "deployerTradingFeeShare": "0.0"
    }
...
  ],
  "universe": [
...
    {
      "tokens": [
        150,
        0
      ],
      "name": "@107",
      "index": 107,
      "isCanonical": false
    }
...
  ]
}
Looking at the universe section we can see a index 107 with name @107 @107 is what you will see in the hyperliquid data, and this refer to the trading pair HYPE/USDC
0 = USDC
150 = Hyper

Perpetuals

You can fetch the Hyperliquid Perpetual metadata here.
Perpetuals are easier than Spot, as the name is the Token which trades against USDC.
For example
  • HYPE will be HYPE/USDC.
  • BTC will be BTC/USDC

Orders

For order types and options see the hyperliquid docs

Market order fills

  • Sources
    • Datastreams
      • hyperliquid.orders
      • hyperliquid.fills
    • Snowflake
      • hyperliquid.raw.orders
  • Filter by:
    • status = 'filled'
    • type = 'market'

Limit order fills

  • Sources
    • Datasteam
      • hyperliquid.orders
      • hyperliquid.fills
    • Snowflake
      • hyperliquid.raw.orders
  • Filter by
    • status = 'filled'
    • type = 'limit'

What are TWAP Orders?

It is an order which is divided into multiple suborders over a period of time set by user. A suborder is sent every 30 seconds during the course of the TWAP.
TWAP stands for Time-Weighted Average Price.
In hyperliquid TWAPs are executed automatically by the validators and as such they do not have a transaction hash, only the order to place a twap has a transaction hash. As such you will very often see trades and fills with 0x0000000000000000000000000000000000000000000000000000000000000000 as the transaction hash.For trades this means one side of the trade is a TWAP.For fill this means it is a TWAP fill.

Twap fills

  • Sources
    • Datastreams
      • hyperliquid.trades
      • hyperliquid.fills
    • Snowflake
      • hyperliquid.raw.transactions
  • Filter by
    • hash = '0x0000000000000000000000000000000000000000000000000000000000000000'

Twap Open

  • Sources
    • Datastreams
      • hyperliquid.transactions
    • Snowflake
      • hyperliquid.raw.transactions
  • Filter by
    • action:type = 'twapOrder'

Twap Cancel

  • Sources
    • Datastreams
      • hyperliquid.transactions
    • Snowflake
      • hyperliquid.raw.transactions
  • Filter by
    • action:type = 'twapCancel'

Staking Activity

  • Sources
    • Datastream
      • hyperliquid.misc_events
    • Snowflake
      • hyperliquid.raw.misc_events
  • Filter by
    • inner: { CDeposit for deposits
    • inner: { CWithdrawal for withdrawals

Liquidations

There are two types of liquidations in hyperliquid.
Market LiquidationsThis is when Hyperliquid places an order to sell (for longs) and buy (for shorts) a user’s position on the market.
HLP Vault LiquidationsThis is a last effort, when the above Market Liquidations fails, ie due to lack of liquidity. In this case the HLP Vault acquires the position, and takes the loss (if any).

Market Liquidations

  • Datastreams
    • hyperliquid.fills
  • Snowflake
    • hyperliquid.raw.fills

Market Liquidation Example

{
...
  "liquidation": {
    "liquidatedUser": "0x444591887598c8ce607e8315daa61ead3dc0e912",
    "markPx": "2.3725",
    "method": "market"
  },
...
}
This will be wrapped in a payload key
{
  "payload": [
    "0x4e8ffa69c78d7a067e1795fbe16a5c80c90b6c05",
    {
      "closedPnl": "-9.94483",
      "coin": "ETH",
      "crossed": false,
      "dir": "Liquidated Isolated Long",
      "fee": "0.0",
      "feeToken": "USDC",
      "hash": "0x13286c0383f6dbbf94db0425f954ba0205a300395397739c419f7da34f95f99d",
      "liquidation": {
        "liquidatedUser": "0x4e8ffa69c78d7a067e1795fbe16a5c80c90b6c05",
        "markPx": "2323.3",
        "method": "backstop"
      },
      "oid": 104754754832,
      "px": "2316.0",
      "side": "A",
      "startPosition": "0.1037",
      "sz": "0.1037",
      "tid": 361622066638684,
      "time": 1750541100096
    }
  ],
  "source": "source"
}

HLP Vault Liquidations

  • Sources
    • Datastreams
      • hyperliquid.misc_events
      • hyperliquid.fills
    • Snowflake
      • hyperliquid.raw.misc_events
      • hyperliquid.raw.fills
The HLP Vault Liquidation shows up in both the misc events and the fills. In the fills it will show up with both sides, and one side being the HLP Vault.

Fills

Liquidated User Fill
{
  "payload": [
    "0x4e8ffa69c78d7a067e1795fbe16a5c80c90b6c05",
    {
      "closedPnl": "-9.94483",
      "coin": "ETH",
      "crossed": false,
      "dir": "Liquidated Isolated Long",
      "fee": "0.0",
      "feeToken": "USDC",
      "hash": "0x13286c0383f6dbbf94db0425f954ba0205a300395397739c419f7da34f95f99d",
      "liquidation": {
        "liquidatedUser": "0x4e8ffa69c78d7a067e1795fbe16a5c80c90b6c05",
        "markPx": "2323.3",
        "method": "backstop"
      },
      "oid": 104754754832,
      "px": "2316.0",
      "side": "A",
      "startPosition": "0.1037",
      "sz": "0.1037",
      "tid": 361622066638684,
      "time": 1750541100096
    }
  ],
  "source": "source"
}
HLP Vault Fill
{
  "payload": [
    "0xb0a55f13d22f66e6d495ac98113841b2326e9540",
    {
      "closedPnl": "0.0",
      "coin": "ETH",
      "crossed": true,
      "dir": "Liquidated Isolated Long",
      "fee": "0.0",
      "feeToken": "USDC",
      "hash": "0x13286c0383f6dbbf94db0425f954ba0205a300395397739c419f7da34f95f99d",
      "liquidation": {
        "liquidatedUser": "0x4e8ffa69c78d7a067e1795fbe16a5c80c90b6c05",
        "markPx": "2323.3",
        "method": "backstop"
      },
      "oid": 104754754832,
      "px": "2316.0",
      "side": "B",
      "startPosition": "7177.3205",
      "sz": "0.1037",
      "tid": 361622066638684,
      "time": 1750541100096
    }
  ],
  "source": "source"
}

Misc Events

{
  "payload": {
    "hash": "0x13286c0383f6dbbf94db0425f954ba0205a300395397739c419f7da34f95f99d",
    "inner": {
      "LedgerUpdate": {
        "delta": {
          "accountValue": "0.756264",
          "leverageType": "Isolated",
          "liquidatedNtlPos": "240.92621",
          "liquidatedPositions": [
            {
              "coin": "ETH",
              "szi": "0.1037"
            }
          ],
          "type": "liquidation"
        },
        "users": [
          "0x4e8ffa69c78d7a067e1795fbe16a5c80c90b6c05"
        ]
      }
    },
    "time": "2025-06-21T21:25:00.096291909"
  },
  "source": "source"
}

Order Book

The easiest way to keep an updated order book is to read from the Datastream orders and applying it to a snapshot of the L2 Orderbook. L2 Orderbook snapshot Once you have the snapshot, you can use the orders datastream to update the snapshot. All the possible order statuses can be found in the Hyperliquid Docs
We are working on providing an L4 Orderbook snapshot.

Trade Ids

Trade ids are not guaranteed to be unique.
Trade ids are a 50bit hash of the buyer and seller order ids.

Orders explained

The trading engine does not emit the orders in the same way that it does for fills, nor are they bound to trading engine timestamps. They are not 1-1. For every order with the status filled you may not find a counter order with the status filled. We’ll pick the only order with this timestamp that has the status filled. At a first glace we’d expect to see another order with the status filled as well. (buyer and seller) But this is not the case let’s see why.
select *
from hyperliquid.raw.orders 
where date_trunc('millisecond', status_change_timestamp) = '2025-09-03 05:46:43.881'::timestamp_ntz and status = 'filled';
It’s a filled order. If you across the timestamp, you will find it is the only filled order. So let’s take the order id and find the corresponding fill.
select * from hyperliquid.raw.fills where order_id = '151749521496';
From there we get the trade id (See trade ids section for caveats info on trade ids)
select * from hyperliquid.raw.fills where trade_id = '879183392645577';
Now we should see two fills, so get the order id from the other fill, the counter order
select * from hyperliquid.raw.orders where order_id = '151749449008';
We found the counter order. But we don’t have a filled status; you can see it was opened then cancelled. This is because the time in force is Alo
  • It went into the order book
  • Got a partial fill (you can see the size is less on the cancelled than the open)
  • It was cancelled, so as to not remove liquidity from the order book.

Time in Force Explained

Alo

The ALO (Add Liquidity Only) time-in-force option works similarly to “Post Only” on other exchanges. How ALO Works
  • When you place an order with ALO, the system ensures that your order will only add liquidity to the order book.
  • If your order would immediately match with an existing order (thus taking liquidity), Hyperliquid will automatically cancel it instead of executing.
  • This prevents you from accidentally paying taker fees, guaranteeing that you only act as a maker.

GTC

GTC (Good ’Til Canceled)
  • A GTC order will remain active on the order book until it is either filled or manually canceled by you.
  • It does not expire automatically, regardless of how much time passes.
  • This is the default time-in-force on most exchanges, including Hyperliquid.
  • Useful if you want your order to stay in the market and wait for execution, even if it takes hours or days.

IOC

IOC (Immediate or Cancel)
  • An IOC order must be filled immediately (fully or partially) when it reaches the order book.
  • Any portion of the order that cannot be instantly matched will be canceled right away.
  • This makes IOC useful when you want to execute as much as possible instantly, but don’t want leftover orders sitting on the book.
  • Traders often use IOC for quick entries/exits or to avoid resting exposure on the book.