Python SDK for Hyperliquid HIP-4 prediction markets. Sync and async clients, with EIP-712 signing handled internally.
This is the Python port of @perps/hip4. The TypeScript SDK remains the reference implementation; this port mirrors its public surface, types, and signing behaviour.
pip install hip4 # sync (requests + websocket-client)
pip install hip4[async] # also installs httpx + websockets for the async clientfrom hip4 import create_hip4_adapter
adapter = create_hip4_adapter() # testnet by default
adapter.initialize()
events = adapter.events.fetch_events(active=True, limit=20)For async, use hip4.aio.create_async_hip4_adapter with async with.
auth_eoa.py– Agent key approval and auth setupget_all_markets.py– Fetch all markets grouped by typeplace_limit_order.py– Limit order with price validationplace_market_order.py– Market order withFrontendMarketTIFstream_prices.py– Stream live prices via WebSocketasync_get_all_markets.py– Async market fetch
import os
from hip4 import LocalSigner, create_hip4_adapter
from hip4.types import PredictionOrderParams
adapter = create_hip4_adapter()
adapter.initialize()
# Agent key (separate from the user's wallet - sign with the user's wallet
# once via auth_eoa.py to approve, then store the agent key for trading).
agent = LocalSigner(os.environ["HIP4_AGENT_PRIVATE_KEY"])
adapter.auth.init_auth(os.environ["HIP4_USER_ADDRESS"], agent)
result = adapter.trading.place_order(PredictionOrderParams(
market_id="123",
outcome="#1230",
side="buy",
type="limit",
price="0.5",
amount="20",
time_in_force="GTC",
))
print(result) # PredictionOrderResult(success=True, order_id="...", ...)
adapter.destroy()import asyncio
from hip4.aio import create_async_hip4_adapter
async def main():
async with create_async_hip4_adapter() as adapter:
await adapter.initialize()
events = await adapter.events.fetch_events(active=True, limit=20)
print(len(events), "active events")
asyncio.run(main())The Python API is a snake_case mirror of the TypeScript SDK. All sub-adapters live on the top-level HIP4Adapter (sync) / AsyncHIP4Adapter (async) facade.
| Method | Description |
|---|---|
fetch_events(category, active, limit, offset, query) |
List events with optional filters |
fetch_event(event_id) |
Single event by ID |
fetch_categories() |
Available categories |
fetch_markets(params) |
Typed HIP-4 markets with optional grouping by type or question |
fetch_settled_outcome(outcome_id) |
Settlement details for a resolved outcome |
ensure_side_names() |
Pre-load side-name mappings |
get_side_name_resolver() |
Returns a sync resolver for side names by outcome ID |
| Method | Description |
|---|---|
fetch_order_book(market_id, side_index=0) |
L2 snapshot |
fetch_price(market_id) |
Both sides, 5s cache |
fetch_trades(market_id, limit=50, side_index=0) |
Recent trades |
fetch_candles(market_id, interval, start_time, end_time) |
OHLCV candles |
subscribe_order_book(market_id, on_data) |
Real-time L2 book |
subscribe_price(market_id, on_data) |
Real-time prices |
subscribe_trades(market_id, on_data) |
Real-time trades |
subscribe_all_mids(on_data) |
Bulk mid-price updates |
subscribe_active_asset_ctx(coin, on_data) |
Spot asset context |
subscribe_perp_asset_ctx(coin, on_data) |
Perp asset context |
Subscriptions return an unsubscribe callable.
| Method | Description |
|---|---|
fetch_positions(address) |
Outcome positions with resolved side names |
fetch_activity(address) |
Fills, last 30 days |
fetch_balance(address) |
Spot balances (incl. USDH) |
fetch_open_orders(address) |
Resting orders |
subscribe_positions(address, on_data) |
Polls every 10 s |
| Method | Description |
|---|---|
place_order(params) |
Place a market or limit order |
place_orders(params_list) |
Batch order placement |
cancel_order(params_list) |
Cancel one or more resting orders |
modify_order(params) |
Modify a resting order (preserves queue priority on size-only changes) |
split_outcome(...), merge_outcome(...), merge_question(...), negate_outcome(...) |
HIP-4 share-conversion primitives |
schedule_cancel(time_ms) |
HL "dead-man's switch" |
| Method | Signing | Description |
|---|---|---|
set_signer(signer) |
– | Set user wallet for EIP-712 ops |
buy_usdh(amount) |
L1 agent | Buy USDH on spot |
sell_usdh(amount) |
L1 agent | Sell USDH on spot |
transfer_to_spot(amount) |
EIP-712 | Perp → Spot |
transfer_to_perps(amount) |
EIP-712 | Spot → Perp |
withdraw(...) |
EIP-712 | Withdraw to external address |
usd_send(...) |
EIP-712 | Send USDC to another HL address |
spot_send(...) |
EIP-712 | Send arbitrary spot token |
send_asset(...) |
EIP-712 | Unified-account-compatible transfer primitive |
| Method | Description |
|---|---|
init_auth(wallet_address, signer) |
Sets the active signer used by trading & USDH ops |
get_auth_status() |
"disconnected" | "pending_approval" | "ready" |
clear_auth() |
Reset auth state |
The signer must implement the hip4.types.hl.Signer protocol (get_address() + sign_typed_data(domain, types, value)). Use hip4.LocalSigner for in-memory keys, or wrap your own custodian / hardware-wallet bridge.
adapter.events.fetch_markets() classifies every HIP-4 outcome into one of four types:
| Type | Description | Parsed Fields |
|---|---|---|
defaultBinary |
Recurring price markets (BTC > $67,250 1d) | underlying, target_price, expiry, period |
labelledBinary |
Standalone binary with custom sides (Hypurr vs Usain Bolt) | Custom side labels |
multiOutcome |
Outcomes grouped under a question with fallback | question_id, question_name, is_fallback |
priceBucket |
Recurring multi-bucket price markets | underlying, expiry, price_thresholds, period, lower_bound, upper_bound |
from hip4.types import FetchMarketsParams
# Filter by type
binaries = adapter.events.fetch_markets(FetchMarketsParams(type="defaultBinary"))
# Group by type
grouped = adapter.events.fetch_markets(FetchMarketsParams(group_by="type"))
# Group multi-outcome by question
by_question = adapter.events.fetch_markets(FetchMarketsParams(group_by="question"))Both Hyperliquid signing flows are implemented from scratch, using msgpack, eth-utils.keccak, and eth-account for EIP-712. They produce byte-for-byte equivalent signatures to the TypeScript SDK (verified by parity tests).
L1 agent signing (orders, cancels, USDH spot, share conversions, scheduleCancel):
- Sort action keys in canonical order
- MessagePack-encode
- Append nonce as big-endian 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(testnet) or0xa4b1(mainnet) - Message filtered to EIP-712 type keys only
- Requires the user wallet (agent keys are rejected)
The pure helpers (sign_l1_action, sign_user_signed_action, sort_*, encode_msgpack, create_l1_action_hash) are exposed at the top level for callers who want to sign outside the adapter.
poetry install --all-extras --with dev
make test # pytest
make lint # ruff + mypy
make format # black + isortPython 3.10+ is required (uses kw_only dataclasses and PEP 604 unions in some places).
Signing implementation inspired by @nktkas/hyperliquid (TS) and the official Hyperliquid Python SDK.
BUSL-1.1 - same as the TypeScript SDK.