TypeScript SDK for Hyperliquid HIP-4 prediction markets. Zero runtime dependencies.
The SDK is structured around a single adapter with typed sub-modules for each domain - events, market data, account state, trading, wallet, and auth. Everything returns typed responses, WebSocket subscriptions return unsubscribe functions, and all signing (L1 agent + EIP-712) is handled internally with no external crypto dependencies.
pnpm add @perps/hip4import { createHIP4Adapter } from "@perps/hip4";
const hip4 = createHIP4Adapter({ testnet: true });
await hip4.initialize();auth-eoa.ts- Agent key approval and auth setupget-all-markets.ts- Fetch all markets grouped by typeget-multi-outcome.ts- Multi-outcome markets with live pricesget-recurring-markets.ts- Recurring markets with expiry countdownsplace-limit-order.ts- Limit order with price validationplace-market-order.ts- Market order with FrontendMarket TIFstream-prices.ts- Stream live prices via WebSocketusdh-ramp.ts- End-to-end USDH on/off-ramp via Coinbase + Across
| Method | Description |
|---|---|
fetchEvents(params?) |
List events. Filters: category, active, limit, offset, query |
fetchEvent(eventId) |
Single event by ID |
fetchCategories() |
Available categories |
fetchMarkets(params?) |
Typed HIP-4 markets with optional grouping by type or question |
fetchSettledOutcome(outcomeId) |
Settlement details for a resolved outcome. Returns null if not settled |
| Method | Description |
|---|---|
fetchOrderBook(marketId, sideIndex?) |
L2 snapshot |
fetchPrice(marketId) |
Both sides, 5s cache |
fetchTrades(marketId, limit?) |
Recent trades |
fetchCandles(marketId, interval?, start?, end?) |
OHLCV candles |
subscribeOrderBook(marketId, cb) |
Real-time L2 book |
subscribePrice(marketId, cb) |
Real-time prices |
subscribeTrades(marketId, cb) |
Real-time trades |
subscribeAllMids(cb) |
All mid-prices across every market |
subscribeActiveAssetCtx(coin, cb) |
Per-spot-coin context (vol, OI, mark) |
subscribeSpotAssetCtxs(cb) |
Bulk spot-asset context updates |
subscribePerpAssetCtx(coin, cb) |
Per-perp-coin context (mark, oracle, funding) |
| Method | Description |
|---|---|
fetchPositions(address) |
Outcome positions with resolved side names |
fetchActivity(address) |
Fills, last 30 days |
fetchBalance(address) |
Spot balances |
fetchOpenOrders(address) |
Resting orders |
subscribePositions(address, cb) |
Polling at 10s |
| Method | Description |
|---|---|
placeOrder(params) |
Place market or limit order. Returns { success, orderId?, error? } |
placeOrders(params[]) |
Batch place orders in a single signed request |
modifyOrder(params) |
Modify a resting order (price and/or size); preserves queue priority on size-only edits |
cancelOrder(params[]) |
Cancel one or more resting orders. Returns HLCancelResponse |
scheduleCancel(time) |
Dead-man's switch — registers a future timestamp at which HL cancels every open order from this agent. Pass null to clear |
splitOutcome(params) |
Split X quote tokens into X Yes + X No shares of one outcome |
mergeOutcome(params) |
Merge X paired Yes+No shares back into X quote tokens |
mergeQuestion(params) |
Merge X Yes shares from every outcome of a question into X quote tokens |
negateOutcome(params) |
Convert X No shares of one outcome into X Yes shares of every other outcome in the question |
| Method | Signing | Description |
|---|---|---|
setSigner(signer) |
- | Set user wallet for EIP-712 ops |
buyUsdh(amount) |
L1 agent | Buy USDH on spot |
sellUsdh(amount) |
L1 agent | Sell USDH on spot |
transferToSpot(amount) |
EIP-712 | Perp -> Spot |
transferToPerps(amount) |
EIP-712 | Spot -> Perp |
withdraw({ destination, amount }) |
EIP-712 | Withdraw to external address |
usdSend({ destination, amount }) |
EIP-712 | Send to another HL address |
| Method | Description |
|---|---|
initAuth(walletAddress, signer) |
Accepts viem PrivateKeyAccount or ethers Signer |
getAuthStatus() |
"disconnected" | "pending_approval" | "ready" |
clearAuth() |
Reset auth state |
fetchMarkets() classifies every HIP-4 outcome into one of four types:
| Type | Description | Parsed Fields |
|---|---|---|
defaultBinary |
Recurring price markets (BTC > $67250 1d) | underlying, targetPrice, expiry, period |
labelledBinary |
Standalone binary with custom sides (Hypurr vs Usain Bolt) | Custom side labels |
multiOutcome |
Grouped under a question, with fallback | questionId, questionName, isFallback |
priceBucket |
Recurring multi-bucket price markets (per-bucket Yes/No) | underlying, expiry, priceThresholds, period, bucketIndex, lowerBound, upperBound |
// Filter by type
const binaries = await hip4.events.fetchMarkets({ type: "defaultBinary" });
// Group by type
const grouped = await hip4.events.fetchMarkets({ groupBy: "type" });
// Group multi-outcome by question
const byQuestion = await hip4.events.fetchMarkets({ groupBy: "question" });const hip4 = createHIP4Adapter({
testnet: true,
// Builder fee — collected on every order placed by this adapter
builderAddress: "0xYourBuilderAddress",
builderFee: 100, // 0.1% (tenths of a basis point, 0–1000)
logger: (level, msg, data) => console.log(level, msg, data),
});Per-order builder address/fee can also be passed on placeOrder to override the adapter-level config.
Drop-in price feeds backed by HL's WebSocket. Each takes a callback and returns an unsubscribe function. The snapshot includes the rolling candle history plus the current mid.
import { createPriceFeed, createPerpPriceFeed } from "@perps/hip4";
// HIP-4 outcome side (uses sideIndex 0 by default)
const unsub = createPriceFeed(
hip4.marketData,
"1758",
(snapshot) => console.log(snapshot.currentMid, snapshot.candles),
{ interval: "1h" },
);
unsub();| Helper | Use |
|---|---|
createPriceFeed(marketData, marketId, onSnapshot, opts?) |
Live mid + tick-aggregated candle history for a HIP-4 outcome side |
createPerpPriceFeed(client, coin, onSnapshot, opts?) |
Same shape for an HL perp coin |
processTick, candleBoundaryMs, intervalToMs |
Lower-level candle utilities |
Built-in fiat ↔ USDH ramp via Coinbase + Across. Buy: fiat → Coinbase onramp → USDC (Arbitrum) → Across counterfactual → USDH (HyperCore). Sell: USDH (HyperEVM) → Across swap → USDC (Arbitrum) → Coinbase offramp → fiat. See examples/usdh-ramp.ts for the full flow.
import { computeTradeCost, computeEstimatedCost, computePotentialReturn } from "@perps/hip4";
const cost = computeTradeCost({
tokenAmount: 100,
orderType: "limit",
limitPriceCents: 55, // 0.55 in cents
});
// → { estimatedCost, potentialReturn, displayShares }Both Hyperliquid signing flows are implemented from scratch.
L1 agent signing (orders, cancels, USDH spot):
- Sort action keys in canonical order
- MessagePack encode
- Append nonce as BE u64
- Append vault marker byte
- Keccak-256 hash ->
connectionId - EIP-712 sign with
Agenttype on chainId1337
User-signed EIP-712 (transfers, withdrawals, sends):
- Domain:
HyperliquidSignTransaction,signatureChainId: 0x66eee - Message filtered to EIP-712 type keys only
- Requires user wallet, agent keys rejected
Signing implementation inspired by @nktkas/hyperliquid.
BUSL-1.1