Skip to content

Hyperliquid SDK

Complete reference for ctx.hyperliquid — programmatic access to the Hyperliquid on-chain perpetuals DEX from worker code.

Read-only adapter — by design

Hyperliquid is an on-chain DEX. Every order is signed in the user's browser via EIP-712 with their MetaMask / WalletConnect wallet. The private key never touches our server.

This means workers cannot place / cancel / modify orders directly. The ctx.hyperliquid adapter is read-only — it exposes every public

  • per-user state endpoint, but trading must go through the canvas block (which has wallet access).

For trading flows, the recommended pattern is: worker computes signal → emits a BlockEvent → Hyperliquid block on the canvas catches it and signs the order in the browser. See Recipes.

Setup

  1. Add a Hyperliquid trading block to your workspace canvas.
  2. Click "Connect Wallet" inside the block — MetaMask / WalletConnect / Phantom.
  3. The wallet address is persisted to the block config.
  4. Connect the block to your Worker block via an edge.
  5. ctx.hyperliquid is now available.
python
def tick(ctx):
    state = ctx.hyperliquid.get_account_state()
    equity = state["marginSummary"]["accountValue"]
    ctx.log.info(f"HL equity: ${equity}")

If no Hyperliquid block is connected, public methods still work, but per-user methods raise:

RuntimeError: No trading block connected. Connect a Hyperliquid block to this worker.

Modes

ModeEndpointNotes
liveapi.hyperliquid.xyzReal positions on mainnet
testnetapi.hyperliquid-testnet.xyzFree testnet — airdrop testnet USDC at the testnet UI

Set on the API key — no per-call override. (You can pass api_mode="testnet" to public methods to override.)

Public Market Data

These methods don't need a connected block.

get_meta

Universe metadata: list of perp assets, max leverage, decimals.

python
ctx.hyperliquid.get_meta(api_mode: str = "live") -> dict
python
meta = ctx.hyperliquid.get_meta()
# meta["universe"] = [{"name": "BTC", "szDecimals": 5, "maxLeverage": 50, ...}, ...]

get_meta_and_contexts

Meta + per-asset live context (mark, oracle, OI, funding) in one call. Most efficient way to scan the whole universe.

python
ctx.hyperliquid.get_meta_and_contexts(api_mode: str = "live") -> list
# Returns [meta_dict, [asset_ctx_dict, ...]]  (parallel arrays by asset index)

get_spot_meta / get_spot_meta_and_contexts

Same shape but for the spot universe.

python
ctx.hyperliquid.get_spot_meta(api_mode: str = "live") -> dict
ctx.hyperliquid.get_spot_meta_and_contexts(api_mode: str = "live") -> list

get_all_mids

All-asset mid prices in one call. Fastest snapshot of the whole market.

python
ctx.hyperliquid.get_all_mids(api_mode: str = "live") -> dict
# {"BTC": "67234.5", "ETH": "3520.1", "SOL": "152.4", ...}

Use this for scanners

Single REST call for every asset's mid — way faster than per-asset l2Book.

get_l2_book

L2 order book for a specific coin.

python
ctx.hyperliquid.get_l2_book(coin: str, api_mode: str = "live") -> dict

Returns: {"coin", "time", "levels": [[bid_levels], [ask_levels]]} where each level is {"px", "sz", "n"}.

get_candles

OHLCV candles.

python
ctx.hyperliquid.get_candles(
    coin: str,
    interval: str = "1h",
    start_time: int = None,    # ms timestamp
    end_time: int = None,
    api_mode: str = "live",
) -> list
intervalValues
Sub-hour"1m", "3m", "5m", "15m", "30m"
Hours"1h", "2h", "4h", "8h", "12h"
Days+"1d", "3d", "1w", "1M"

get_funding_history

Historical funding rate for a perpetual.

python
ctx.hyperliquid.get_funding_history(
    coin: str,
    start_time: int = None,
    end_time: int = None,
    api_mode: str = "live",
) -> list

get_vault_details

Public vault info: APY, depositors, position composition.

python
ctx.hyperliquid.get_vault_details(vault_address: str, api_mode: str = "live") -> dict

Per-User State

These need a Hyperliquid block connected so the SDK can read the wallet address from its cfg.

get_account_state

Full account state: positions, cross-margin summary, withdrawable balance.

python
ctx.hyperliquid.get_account_state() -> dict

Returns: {"marginSummary": {"accountValue", "totalNtlPos", "totalRawUsd", "totalMarginUsed"}, "crossMarginSummary": {...}, "crossMaintenanceMarginUsed", "withdrawable", "assetPositions": [{...}], "time"}

python
s = ctx.hyperliquid.get_account_state()
equity = float(s["marginSummary"]["accountValue"])
free = float(s["withdrawable"])
ctx.log.info(f"Equity: ${equity:.2f}, free: ${free:.2f}")

for p in s["assetPositions"]:
    pos = p["position"]
    if float(pos["szi"]) != 0:
        ctx.log.info(f"{pos['coin']}: size={pos['szi']}, "
                     f"entry={pos['entryPx']}, "
                     f"PnL={pos['unrealizedPnl']}")

get_spot_balances

Spot wallet balances per token.

python
ctx.hyperliquid.get_spot_balances() -> dict

get_open_orders / get_frontend_open_orders

Active (unfilled) orders. The frontend_* variant adds extra trigger-info fields used by the Hyperliquid UI for stop / TP-SL orders.

python
ctx.hyperliquid.get_open_orders() -> list
ctx.hyperliquid.get_frontend_open_orders() -> list

get_user_fills

Recent fills (executed trades) with fees.

python
ctx.hyperliquid.get_user_fills() -> list

get_user_fills_by_time

Fills within a time range.

python
ctx.hyperliquid.get_user_fills_by_time(start_time: int, end_time: int = None) -> list
# timestamps in ms

get_user_funding

Funding payments history.

python
ctx.hyperliquid.get_user_funding(
    start_time: int = None,
    end_time: int = None,
) -> list

get_historical_orders

All orders ever placed (filled, cancelled, rejected).

python
ctx.hyperliquid.get_historical_orders() -> list

get_ledger_updates

Non-funding ledger: deposits, withdrawals, transfers, internal moves.

python
ctx.hyperliquid.get_ledger_updates(start_time: int = None, end_time: int = None) -> list

get_sub_accounts

User's Hyperliquid sub-accounts (their isolation primitive).

python
ctx.hyperliquid.get_sub_accounts() -> list

get_referral

Referral code, rewards earned, downstream users.

python
ctx.hyperliquid.get_referral() -> dict

get_user_vault_equities

Positions in vaults the user has deposited into.

python
ctx.hyperliquid.get_user_vault_equities() -> list

Common Patterns

How to "trade" from a worker

You can't sign orders from a worker (by design). The pattern is:

  1. Worker computes a signal and emits a BlockEvent:
    python
    ctx.emit("hl_signal", {
        "coin": "BTC",
        "side": "buy",
        "size": 0.001,
        "limit_price": 65000,
    })
  2. Hyperliquid block on the canvas listens for hl_signal events and signs+sends the order via the user's wallet.

This keeps the security boundary intact: the worker has read access to state for decision-making, the wallet does the signing.

Error handling

python
def tick(ctx):
    try:
        state = ctx.hyperliquid.get_account_state()
    except Exception as e:
        ctx.log.error(f"Hyperliquid unreachable: {e}")
        return

HyperliquidAPIError is raised for HTTP errors with status and body attributes.

Cloud-Run proxy

PRO+ workers route Hyperliquid traffic through a Cloud Run proxy with rotating exit IPs. Transparent — no code changes.

Recipes

Position-aware risk monitor

Watch positions and alert on margin pressure.

python
def tick(ctx):
    s = ctx.hyperliquid.get_account_state()
    summary = s["marginSummary"]
    used = float(summary["totalMarginUsed"])
    equity = float(summary["accountValue"])
    util = used / equity if equity else 0

    if util > 0.7:
        ctx.log.warn(f"Margin utilization {util:.1%} — getting hot")
        ctx.monitor.alert("HL margin > 70%", level="warn")
    elif util > 0.9:
        ctx.log.error(f"Margin utilization {util:.1%} — danger")
        ctx.monitor.alert("HL margin > 90%", level="critical")

Funding-rate income tracker

python
def tick(ctx):
    import time
    now_ms = int(time.time() * 1000)
    day_ago = now_ms - 86400 * 1000

    funding = ctx.hyperliquid.get_user_funding(
        start_time=day_ago, end_time=now_ms,
    )
    total = sum(float(f["delta"]["usdc"]) for f in funding)
    ctx.log.info(f"24h net funding: ${total:+.4f}")
    ctx.monitor.metric("hl_funding_24h", total)

Cross-asset signal generator (worker → on-canvas trade)

python
def tick(ctx):
    mids = ctx.hyperliquid.get_all_mids()
    candles = ctx.hyperliquid.get_candles("BTC", interval="1h", start_time=...)

    closes = [float(c["c"]) for c in candles]
    sma_24 = sum(closes[-24:]) / 24
    last = float(mids["BTC"])

    # No direct trading from worker — emit signal for the canvas block
    if last > sma_24 * 1.005:
        ctx.emit("hl_signal", {"coin": "BTC", "side": "buy", "size": 0.001})
        ctx.log.info(f"Long signal: {last} > SMA24 {sma_24:.2f}")
    elif last < sma_24 * 0.995:
        ctx.emit("hl_signal", {"coin": "BTC", "side": "sell", "size": 0.001})
        ctx.log.info(f"Short signal: {last} < SMA24 {sma_24:.2f}")

Vault performance scanner

python
def tick(ctx):
    # The user's address would be in their Hyperliquid block cfg;
    # for vault-finding we hardcode well-known vault addresses or
    # discover via meta endpoints elsewhere.
    famous = ["0x...vault1...", "0x...vault2..."]
    for v in famous:
        d = ctx.hyperliquid.get_vault_details(v)
        apr = d.get("apr", 0)
        tvl = d.get("tvl", 0)
        ctx.log.info(f"{d.get('name', v[:10])} APR={apr:.1%} TVL=${tvl:,.0f}")

Reference

Hyperliquid endpointSDK methodAuth needed
POST /info {type:"meta"}get_metano
POST /info {type:"metaAndAssetCtxs"}get_meta_and_contextsno
POST /info {type:"spotMeta"}get_spot_metano
POST /info {type:"spotMetaAndAssetCtxs"}get_spot_meta_and_contextsno
POST /info {type:"allMids"}get_all_midsno
POST /info {type:"l2Book"}get_l2_bookno
POST /info {type:"candleSnapshot"}get_candlesno
POST /info {type:"fundingHistory"}get_funding_historyno
POST /info {type:"vaultDetails"}get_vault_detailsno
POST /info {type:"clearinghouseState"}get_account_statewallet addr
POST /info {type:"spotClearinghouseState"}get_spot_balanceswallet addr
POST /info {type:"openOrders"}get_open_orderswallet addr
POST /info {type:"frontendOpenOrders"}get_frontend_open_orderswallet addr
POST /info {type:"userFills"}get_user_fillswallet addr
POST /info {type:"userFillsByTime"}get_user_fills_by_timewallet addr
POST /info {type:"userFunding"}get_user_fundingwallet addr
POST /info {type:"historicalOrders"}get_historical_orderswallet addr
POST /info {type:"userNonFundingLedgerUpdates"}get_ledger_updateswallet addr
POST /info {type:"subAccounts"}get_sub_accountswallet addr
POST /info {type:"referral"}get_referralwallet addr
POST /info {type:"userVaultEquities"}get_user_vault_equitieswallet addr
POST /exchange (signed)not exposed — use canvas blockwallet signature

AiSpinner Documentation