16 min read
Overview
HIP-4 launched on Hyperliquid mainnet on May 2, 2026, adding fully collateralized binary outcome markets that settle to 0 or 1 in USDH. These markets live in HyperCore alongside perpetuals and spot, sharing the same CLOB infrastructure, the same WebSocket streams, and the same data endpoints you use for every other Hyperliquid asset. This guide walks you through the data model first, then takes you step by step through discovering markets, reading and streaming the orderbook, acquiring USDH, and placing trades using the Quicknode Hyperliquid TypeScript SDK.
- HIP-4 markets are binary YES/NO contracts that settle to 0 or 1 in USDH and trade on the HyperCore CLOB with zero open fee
- Each side appears as a
#Ncoin (for example,#20for YES and#21for NO) inallMids, datasets, and all streaming APIs - Quicknode builds and maintains SDKs for TypeScript, Python, Go, and Rust, plus a hosted REST API reference and gRPC streaming endpoints
- Full source code for this guide is in qn-guide-examples
- SQL Explorer lets you query historical HIP-4 trades and orders with plain SQL
What You Will Do
- Understand the HIP-4 data model:
#Ncoin notation,outcomeMeta,allMids, and the trades/orders/book-updates datasets - Set up a Quicknode Hyperliquid endpoint and initialize the TypeScript SDK
- Approve the builder fee (one-time per wallet)
- Discover active prediction markets and inspect YES/NO side shapes
- Read and stream the orderbook for both sides in real time
- Acquire USDH by swapping USDC via the spot market
- Place limit and market orders, cancel resting orders, and handle common errors
What You Will Need
- A Quicknode account with a Hyperliquid endpoint
- Node.js 20+ and a package manager (
npm,pnpm, oryarn) - A Hyperliquid wallet private key and at least some USDC in your spot balance (for the USDH swap step)
- Familiarity with TypeScript and basic prediction market concepts
What Are HIP-4 Outcome Markets?
HIP-4 introduces binary outcome markets to HyperCore. Each market poses a yes/no question (for example, "Will BTC be above 79,980 USD at expiry?"). Traders buy YES or NO positions using USDH as collateral. At expiry, the winning side settles to 1 USDH per unit and the losing side settles to 0. The price of a YES token at any moment represents the market's implied probability of the event occurring.
HIP-4 markets run:
- Onchain and permissionless. Settled directly on Hyperliquid L1 with no bridge or custodian.
- With zero open fee. Unlike perps and spot, HIP-4 charges no fee to open a position (the builder fee still applies).
- On the same CLOB as everything else. The same L2 book endpoints, WebSocket streams, and fill datasets cover HIP-4 alongside all other assets. If you already query Hyperliquid data, you are most of the way there.
The Quicknode Hyperliquid Developer Toolkit
Before writing any code, it is worth knowing what Quicknode provides for Hyperliquid so you can pick the right tool for what you want to build.
| Tool | What it gives you | Link |
|---|---|---|
| Hyperliquid SDKs (TypeScript, Python, Go, Rust) | Full trading and data SDK: orders, streams, account state | Hyperliquid SDKs |
| Datasets | Data streams that contain different types of blockchain and exchange events such as trades, orders, and book-updates via gRPC and JSON-RPC/WebSocket APIs | docs |
| WebSocket / JSON-RPC APIs | Real-time subscriptions (bookUpdates, allMids, trades) and state queries | docs |
| gRPC Streaming | Lowest-latency path to block-level orderbook and trade data, ideal for high-frequency strategies | docs |
| Info Endpoints | Snapshot queries: outcomeMeta, allMids, l2Book, clearinghouseState | docs |
| REST API (hyperliquidapi.com) | Zero-custody REST builder API for Hyperliquid, built by Quicknode | hyperliquidapi.com |
| SQL Explorer | Historical queries over indexed tables: hyperliquid_trades, hyperliquid_orders, and 35+ others | sql-explorer |
This guide uses the Hyperliquid SDK for TypeScript end-to-end. It allows you to access all data APIs and place trades with a single unified interface.
The Data Model
The SDK makes it easy to work with HIP-4 markets, but it is important to understand the underlying data model. HIP-4 data flows through the same APIs and datasets as every other Hyperliquid asset. The only distinguishing element is the #N coin notation. This section covers the three things you need to know before writing any code.
Market Identity and Discovery
Every HIP-4 outcome side is identified by a coin string prefixed with #, for example #20 (YES) and #21 (NO). This distinguishes outcome market coins from perpetuals (no prefix) and spot tokens (@N or xyz: prefix). The integer N is derived from the asset's numeric ID using the encoding N = 10 * outcomeIndex + sideIndex. The Hyperliquid Asset IDs specification covers the full mapping.
Two endpoints give you the complete picture of any active market:
outcomeMeta returns the market definition:
{
"outcomes": [
{
"outcome": 3,
"name": "Recurring",
"description": "class:priceBinary|underlying:BTC|expiry:20260506-0600|targetPrice:80930|period:1d",
"sideSpecs": [
{ "name": "Yes" },
{ "name": "No" }
]
}
],
"questions": []
}
| Field | Description |
|---|---|
outcomes[].outcome | Incrementing integer that identifies the market instance |
outcomes[].name | Market type label (for example, "Recurring") |
outcomes[].description | Pipe-delimited key:value pairs: class, underlying, expiry (format YYYYMMDD-HHMM), targetPrice, period |
outcomes[].sideSpecs | Array with one entry per side. sideSpecs[0] is YES, sideSpecs[1] is NO |
questions | Reserved for non-binary market types, empty for price binary markets |
allMids returns live mid prices for every asset on the exchange. HIP-4 markets appear as #N keys alongside normal perp and spot tickers:
{
"BTC": "96423.0",
"ETH": "1823.5",
"#20": "0.47",
"#21": "0.53"
}
Filter for keys starting with # to isolate outcome market mids. sdk.stream.allMids() gives you the same data as a continuous real-time stream.
What Activity Looks Like in Data
When orders are placed and trades are matched, the Quicknode Hyperliquid datasets capture the activity with #N identifiers throughout:
trades: Each trade row uses coin: "#N". The feeToken field uses the +N notation (for example, +20), and fee is always "0.0" because HIP-4 open orders carry no fee.
orders: Order records use the same coin: "#N" notation. Both sides of a matched outcome trade appear as Buy orders (side: "B").
book-updates: Each event includes a raw_book_diff field: {"new": {"sz": "..."}} (new order placed), "remove" (order cancelled or filled), or {"update": {"origSz": "...", "newSz": "..."}} (in-place size modification, HIP-4 only). Use these to maintain a local orderbook replica.
l2-book and l4-book: Aggregated and raw book snapshots queryable by coin. Pass "#N" as the coin filter to retrieve data for a specific outcome side.
Reading Prices: Implied Probabilities
Because YES and NO are complementary outcomes, their mid prices sum to approximately 1.0:
YES mid + NO mid ≈ 1.0
A YES mid of 0.47 means the market implies a 47% probability of the event occurring. A NO mid of 0.53 implies 53%. Minor deviations from 1.0 reflect the spread and any temporary arbitrage opportunity between the two sides.
The SDK abstracts most of this: sdk.predictionMarkets() resolves #N symbols for you, routes USDH swaps through the correct staking account, and handles type casting on API responses. The structures above matter when you are reading raw allMids, dataset records, or gRPC events directly. With that foundation in place, the rest of this guide is hands-on.
Trade HIP-4 Markets with Quicknode
This section walks through everything you need to go from zero to live trades on a HIP-4 market: approving the builder fee, verifying your setup, discovering active markets, reading and streaming the orderbook, acquiring USDH, and placing your first order.
The guide examples repository contains seven standalone scripts, each covering a specific aspect of working with HIP-4. You can follow along with the key excerpts below to understand each concept, or clone the full repo and run the scripts one by one to see live output from your own wallet.
Get the Example Code
git clone https://github.com/quiknode-labs/qn-guide-examples.git
cd qn-guide-examples/hyperliquid/hip4-prediction-markets
npm install
cp .env.example .env
Fill in .env with your endpoint, private key, and wallet address (covered in Set Up Your Quicknode Endpoint below), then build and run any script:
npm run build
node --env-file=.env dist/0-approve.js
Each script is self-contained:
| Script | What it covers |
|---|---|
0-approve.ts | One-time builder fee approval |
1-setup.ts | Health check: endpoint, active markets, account state |
2-list-markets.ts | Discover active markets and inspect the full PredictionMarket shape |
3-orderbook-snapshot.ts | Fetch L2 orderbook for YES and NO, compute implied probabilities |
4-stream-orderbook.ts | Subscribe to real-time bookUpdates and allMids WebSocket streams |
5-buy-usdh.ts | Swap USDC for USDH via spot market @230 |
6-trade.ts | Limit and market orders, cancel, and inspect PlacedOrder shape |
Set Up Your Quicknode Endpoint
- Log in to your Quicknode dashboard.
- Create a new endpoint and select Hyperliquid as the chain.
- Copy the HyperCore HTTPS endpoint URL and remove the
/hypercoresuffix. - Create a
.envfile in your project root:
QUICKNODE_ENDPOINT=https://your-endpoint.hype-mainnet.quiknode.pro/your-api-key/
PRIVATE_KEY=your_wallet_private_key_hex
WALLET_ADDRESS=your_wallet_address
USDH_AMOUNT=11
In any shell scripts or cURL examples, keep your endpoint as a variable: TEST_RPC=$QUICKNODE_ENDPOINT
Never commit .env to version control. Add it to .gitignore. The PRIVATE_KEY field gives full control over your wallet.
Initialize the SDK
Install the Quicknode Hyperliquid TypeScript SDK:
npm install @quicknode/hyperliquid-sdk
This guide uses the TypeScript SDK. Quicknode also maintains SDKs for Python, Go, and Rust (all with the same core primitives). You can find links to all SDKs on the Quicknode Hyperliquid docs hub. If you prefer raw HTTP, the REST API reference covers every endpoint used in this guide.
Initialize the SDK with your endpoint and signing credentials. The autoApprove: true flag automatically handles builder fee approval on the first trade, and maxFee: "1%" sets the maximum fee rate your wallet will accept:
import { HyperliquidSDK } from "@quicknode/hyperliquid-sdk";
const sdk = new HyperliquidSDK(process.env.QUICKNODE_ENDPOINT, {
privateKey: process.env.PRIVATE_KEY,
autoApprove: true,
maxFee: "1%",
});
Builder codes are a Hyperliquid-native mechanism that lets infrastructure providers charge a fee on top of exchange fees. You approve a maximum rate once and the actual charge is always at or below it.
Approve the Builder Fee
The builder fee must be approved before your wallet can trade. This is a one-time onchain action per wallet. With autoApprove: true the SDK handles this on your first trade, but running it explicitly shows you the before/after state and confirms everything is ready.
// 1. Check current status
const before = await sdk.approvalStatus() as any;
// 2. Approve
console.log(`\nApproving builder fee (maxFee: ${MAX_FEE})...`);
const result = await sdk.approveBuilderFee(MAX_FEE) as any;
// 3. Verify
const after = await sdk.approvalStatus() as any;
Full source: 0-approve.ts
Expected output (first run):
============================================================
BUILDER FEE APPROVAL
============================================================
── Current Status ───────────────────────────────────────
approved : true
maxFeeRate : 0%
canTradePerps: false
canTradeSpot : false
status msg : Your approval is below the minimum fee. Re-approve with a higher maxFeeRate.
Approving builder fee (maxFee: 1%)...
── Approval Result ──────────────────────────────────────
{
"status": "ok",
"response": { "type": "default" }
}
── Status After Approval ────────────────────────────────
approved : true
maxFeeRate : 1%
canTradePerps: true
canTradeSpot : true
status msg : You can trade both perps and spot.
Approval successful. You can now trade perps, spot, and HIP-4 markets.
Verify Your Connection and Active Markets
Before placing any orders, confirm that your endpoint is reachable, HIP-4 markets are live, and builder fee approval is in place.
const markets = await sdk.predictionMarkets();
console.log("Active HIP-4 markets:", markets.length);
for (const m of markets) {
console.log(` ${m.title}`);
console.log(` YES: ${m.yes.symbol} (assetId: ${m.yes.assetId}) | mid: ${m.yes.mid}`);
console.log(` NO: ${m.no.symbol} (assetId: ${m.no.assetId}) | mid: ${m.no.mid}`);
}
// ── All mid prices (filter HIP-4 # assets) ───────────────────
const allMids = await sdk.info.allMids() as any;
const hip4Mids = Object.entries(allMids).filter(([k]) => k.startsWith("#"));
const approval = await sdk.approvalStatus();
console.log("canTradePerps:", approval.canTradePerps);
console.log("canTradeSpot :", approval.canTradeSpot);
Full source: 1-setup.ts
Expected output (trimmed):
── HIP-4 Prediction Markets ─────────────────────────────
Active markets : 1
Title : BTC above 79980 (05/09 12:00 UTC)
Expiry : 2026-05-09T12:00:00.000Z
Collateral: USDH
Min order : 10 USDH
YES : #20 (assetId: 20) | mid: 0.47
NO : #21 (assetId: 21) | mid: 0.53
── HIP-4 Mid Prices (from allMids) ──────────────────────
#20 : 0.47
#21 : 0.53
── Builder Fee Approval ─────────────────────────────────
canTradePerps: true
canTradeSpot : true
✓ Builder fee approved. Ready to trade.
Browse Active Prediction Markets
sdk.predictionMarkets() returns the full PredictionMarket shape for every active HIP-4 market, including live mid prices, the pipe-delimited description used in outcomeMeta, and both side objects.
import { HyperliquidSDK, type PredictionMarket } from "@quicknode/hyperliquid-sdk";
const markets = await sdk.predictionMarkets();
for (const market of markets as PredictionMarket[]) {
console.log("Title :", market.title);
console.log("Description:", market.description);
console.log("Underlying :", market.underlying);
console.log("Target px :", market.targetPrice);
console.log("Expiry :", market.expiry);
console.log("Min Order :", market.minOrderValue, "USDH");
for (const side of market.sides) {
const liveMid = await sdk.getMid(side);
console.log(` ${side.name}: symbol=${side.symbol} assetId=${side.assetId} mid=${side.mid} liveMid=${liveMid}`);
}
}
Full source: 2-list-markets.ts
Expected output (trimmed):
────────────────────────────────────────────────────────────
Title : BTC above 79980 (05/09 12:00 UTC)
Description: Will BTC be above 79980|USD|2026-05-09T12:00:00.000Z
Slug : btc-above-79980-0509-1200-utc
Underlying : BTC
Target px : 79980
Expiry : 2026-05-09T12:00:00.000Z
Min Order : 10 USDH
Sides:
YES : symbol=#20 assetId=20 mid=0.47 liveMid=0.4712
NO : symbol=#21 assetId=21 mid=0.53 liveMid=0.5288
The market.yes and market.no shorthand properties give you direct access to each side without iterating market.sides. Use market.yes.symbol when you need the coin string (for example, to pass to l2Book or bookUpdates).
Read the Live Orderbook
Pass the YES or NO symbol to sdk.info.l2Book() to get the full aggregated orderbook. Each level has px (price), sz (total size), and n (number of resting orders). Fetching both sides in parallel minimizes latency.
const [yesBook, noBook] = await Promise.all([
sdk.info.l2Book(market.yes.symbol),
sdk.info.l2Book(market.no.symbol),
]);
const yesBids = yesBook.levels[0]; // sorted best-to-worst
const yesAsks = yesBook.levels[1];
const bestBid = parseFloat(yesBids[0].px);
const bestAsk = parseFloat(yesAsks[0].px);
const spread = bestAsk - bestBid;
const mid = (bestBid + bestAsk) / 2;
console.log("Spread:", spread.toFixed(5), "Mid:", mid.toFixed(5));
// Implied probabilities
const yesMid = parseFloat(market.yes.mid);
const noMid = parseFloat(market.no.mid);
console.log(`YES: ${(yesMid * 100).toFixed(2)}% NO: ${(noMid * 100).toFixed(2)}% Sum: ${((yesMid + noMid) * 100).toFixed(2)}%`);
Full source: 3-orderbook-snapshot.ts
Expected output (trimmed):
── #20 (YES) ────────────────────────────────────────────────
Best bid : 0.46
Best ask : 0.47
Spread : 0.01000 (2.128%)
Mid (book) : 0.46500
Bid depth : 1240 units across 5 levels
Ask depth : 980 units across 4 levels
── Implied Probabilities ─────────────────────────────────
YES mid : 47.00%
NO mid : 53.00%
Sum : 100.00% (should be ~100%)
Live getMid YES: 0.4712
Live getMid NO : 0.5288
A YES mid below 0.50 means the market currently considers the event unlikely. A YES mid above 0.50 means it is likely. Track both sides: the NO mid is not simply 1 - YES mid in a live orderbook because each side has its own spread.
Stream Real-Time Orderbook Updates
For live data, use sdk.stream.bookUpdates() to receive orderbook deltas as they arrive. Subscribe to allMids in parallel to track mid prices without polling. Both subscriptions run over the same WebSocket connection managed by the SDK.
// Stream allMids: filter for #N keys to track HIP-4 prices
sdk.stream.allMids((mids) => {
const hip4 = Object.fromEntries(Object.entries(mids).filter(([k]) => k.startsWith("#")));
console.log("[allMids] HIP-4:", JSON.stringify(hip4));
});
// Stream orderbook deltas for the YES side
sdk.stream.bookUpdates([market.yes.symbol], (data) => {
for (const ev of data.block.events) {
const side = ev.side === "A" ? "ASK" : "BID";
const action =
typeof ev.raw_book_diff === "object" &&
"new" in (ev.raw_book_diff as object)
? "+"
: typeof ev.raw_book_diff === "object" &&
"update" in (ev.raw_book_diff as object)
? "~"
: "-";
console.log(`[bookUpdate] ${action}${side} px=${ev.px} oid=${ev.oid}`);
}
});
await new Promise((r) => setTimeout(r, 30_000));
sdk.stream.stop();
This snippet omits TypeScript type annotations for readability. In the actual source, both callbacks receive data: Record<string, unknown> and use explicit casts (for example, (data as any).block) to access nested fields.
Full source: 4-stream-orderbook.ts
Expected output (trimmed):
[allMids] Stream live ✓
[allMids] HIP-4: {"#20":"0.47","#21":"0.53"}
[bookUpdate] +ASK px=0.48 oid=4829301
[bookUpdate] -BID px=0.46 oid=4829105
[allMids] tick #10 | HIP-4: {"#20":"0.4712","#21":"0.5288"}
STREAM SUMMARY
allMids ticks : 28
bookUpdate deltas : 14
l2Book snapshots : 6
Final HIP-4 mids : {"#20":"0.4712","#21":"0.5288"}
Buy USDH Collateral
HIP-4 markets require USDH, Hyperliquid's stablecoin, as collateral. You obtain it by swapping USDC through spot market @230. The SDK handles the routing automatically through the required staking account (cStaking/cWithdrawal). Just call buyUsdh() with the amount you want.
// Buy 11 USDH (min order is 10 USDH; the extra 1 is a safety buffer)
const result = await sdk.buyUsdh(11);
console.log("Status :", result.status);
console.log("isFilled :", result.isFilled);
console.log("avgPrice :", result.avgPrice);
console.log("filledSize:", result.filledSize);
Full source: 5-buy-usdh.ts
Expected output:
Swapping 11 USDC -> USDH via spot market @230...
(SDK routes through staking account as required by Hyperliquid)
=== USDH Swap Result ===
Status : ok
isFilled : true
avgPrice : 1.0001
filledSize : 11
Always buy slightly more USDH than you plan to trade. The minimum order value is 10 USDH (size * price >= 10), so buying exactly 10 leaves no buffer. If you receive a ValidationError when placing an order, check your USDH balance first with sdk.info.spotClearinghouseState(walletAddress).
Place Your First HIP-4 Trade
The SDK exposes sdk.buy() / sdk.sell() for limit orders and sdk.marketBuy() / sdk.marketSell() for market orders. Pass the side object (market.yes or market.no) as the first argument.
HIP-4 assets have szDecimals = 0, meaning size must be a whole integer. The minimum order notional is 10 USDH. Find the smallest valid size with Math.ceil(10 / price). The examples below add a buffer of 5 units on top of the minimum.
Limit Orders (GTC)
Limit orders rest on the book until filled or cancelled. Use tif: "gtc" (Good Till Cancel). Do not set priorityFee on HIP-4 orders. It is not supported and will return an error.
const midPrice = await sdk.getMid(market.yes);
const buyPrice = parseFloat((midPrice * 0.97).toFixed(4)); // 3% below mid
const sellPrice = parseFloat((midPrice * 1.03).toFixed(4)); // 3% above mid
const limitSize = Math.ceil(minOrderUSDH / buyPrice) + 5; // min 10 USDH + buffer
const limitBuy = await sdk.buy(market.yes, { size, price: buyPrice, tif: "gtc" });
const limitSell = await sdk.sell(market.yes, { size, price: sellPrice, tif: "gtc" });
console.log("BUY oid:", limitBuy.oid, "isResting:", limitBuy.isResting);
console.log("SELL oid:", limitSell.oid, "isResting:", limitSell.isResting);
// Cancel when done
if (limitBuy.isResting) await limitBuy.cancel();
if (limitSell.isResting) await limitSell.cancel();
Market Orders (IOC)
Market orders fill immediately at the best available price with a configurable slippage tolerance (default 3%). Size still must satisfy the 10 USDH minimum at the worst-case fill price.
const worstCasePx = midPrice * 1.03; // account for 3% slippage on a buy
const marketSize = Math.ceil(10 / worstCasePx) + 5;
const marketBuy = await sdk.marketBuy(market.yes, { size: marketSize, slippage: 0.03 });
const marketSell = await sdk.marketSell(market.yes, { size: marketSize, slippage: 0.03 });
console.log("Market BUY isFilled:", marketBuy.isFilled, "avgPrice:", marketBuy.avgPrice);
console.log("Market SELL isFilled:", marketSell.isFilled, "avgPrice:", marketSell.avgPrice);
Full source: 6-trade.ts
Expected output (trimmed):
── LIMIT BUY (YES) ──────────────────────────────────────
OID : 4830012
Status : resting
isResting : true
isFilled : false
isError : false
price : 0.4559
size : 27
filledSize : null
avgPrice : null
── MARKET BUY (YES) ─────────────────────────────────────
OID : null
Status : filled
isResting : false
isFilled : true
isError : false
price : 0.47
size : 22
filledSize : 22
avgPrice : 0.471
Limit BUY cancelled: {"status":"ok"}
Limit SELL cancelled: {"status":"ok"}
Common Mistakes
No USDH balance. HIP-4 orders fail silently or return a confusing error if you have no USDH. Always run the USDH acquisition step before placing orders and confirm your balance with sdk.info.spotClearinghouseState(walletAddress).
Order value below 10 USDH. Every HIP-4 order must satisfy size * price >= 10. If your price is 0.05, you need at least 200 units. Always compute size as Math.ceil(10 / price) + buffer rather than hardcoding a number.
priorityFee on HIP-4. The priorityFee parameter is not supported for outcome market orders. Passing it returns a ValidationError.
Fractional size. szDecimals = 0 for all HIP-4 assets. Sizes like 10.5 are rejected. Always use Math.ceil() or Math.floor().
Builder fee not approved. If sdk.approvalStatus() shows canTradeSpot: false, no trades will go through. Run the approval step first.
Conclusion
You now have a complete path from raw data to live trades for HIP-4 prediction markets on Hyperliquid. The key insight is that HIP-4 is not a separate system: it uses the same CLOB, the same WebSocket streams, and the same fill datasets as every other Hyperliquid asset. The #N coin notation is the only thing that distinguishes outcome market data in raw API responses. Once you understand that mapping, the entire Quicknode Hyperliquid toolkit works without modification.
What to Build Next
Now that you have the fundamentals, here are some ideas for what to build on top:
Live probability alert bot. Combine sdk.stream.allMids() with a messaging webhook (Telegram, Discord, or Slack). Stream #N mid prices in real time and fire a notification when a market's implied probability crosses a threshold you define (useful for monitoring markets close to expiry or after a major news event).
Pre-expiry behavior analysis with SQL Explorer. Use SQL Explorer to query hyperliquid_trades WHERE coin LIKE '#%' and measure trade volume, fill frequency, and price action in the hours before settlement. Combine with hyperliquid_orders to track order placement patterns across multiple market cycles.
YES/NO spread arbitrage scanner. Subscribe to bookUpdates for all active YES/NO pairs. When YES mid + NO mid deviates meaningfully from 1.0, flag the spread as a potential arbitrage opportunity. Layer in l2Book depth data to estimate fill probability before acting.
High-frequency market data pipeline with gRPC. For latency-sensitive strategies, Quicknode's gRPC streaming API gives you the lowest-latency path to block-level orderbook and trade data. Parse #N events server-side and react to each block with minimal overhead compared to WebSocket polling.
Resources
- Quicknode Hyperliquid docs hub: Full API reference for endpoints, datasets, streams, and all SDK options
- Datasets reference: All indexed Hyperliquid tables including
trades,orders,book-updates,l2-book, andl4-book - HIP-4 specification: Official Hyperliquid docs for prediction markets
- TypeScript SDK on npm: Package source and changelog
- Full guide examples repo: All 7 scripts from this guide
- SQL Explorer intelligence bot guide: Query Hyperliquid data with plain SQL
Frequently Asked Questions
What is USDH and why do I need it?
USDH is Hyperliquid's stablecoin and used as collateral for HIP-4 prediction markets. You obtain USDH by swapping USDC through spot market @230. The SDK's buyUsdh() method handles the routing automatically.
Why does YES mid + NO mid equal approximately 1.0?
YES and NO are complementary binary outcomes: exactly one settles to 1 and the other to 0. In an efficient market, their prices reflect the implied probabilities of each outcome, which must sum to 100%. Small deviations from 1.0 reflect the spread and temporary arbitrage opportunities between the two sides.
Can I trade HIP-4 markets without USDH?
No. USDH is the required collateral for all HIP-4 orders. Attempting to place an order without sufficient USDH balance will result in an error. Run sdk.buyUsdh() first, and verify your balance with sdk.info.spotClearinghouseState(walletAddress).
Why must HIP-4 order sizes be whole integers?
HIP-4 assets have szDecimals = 0 on Hyperliquid, meaning the exchange only accepts integer quantities. If you pass a fractional size like 10.5, the order will be rejected. Always use Math.ceil() to compute the minimum valid size: Math.ceil(10 / price).
What does a coin like `#20` mean in API responses?
The #N notation identifies a HIP-4 outcome market side. The number N is derived from the asset ID using N = 10 * outcomeIndex + sideIndex, where outcomeIndex identifies the outcome and sideIndex the trading side. The SDK abstracts this: sdk.predictionMarkets() returns market.yes.symbol and market.no.symbol already resolved. You encounter raw #N values when reading allMids, trades, orders, or book-updates dataset responses directly.
We ❤️ Feedback!
Let us know if you have any feedback or requests for new topics. We'd love to hear from you.