Skip to content

Latest commit

 

History

History
225 lines (167 loc) · 8.71 KB

File metadata and controls

225 lines (167 loc) · 8.71 KB

hip4-python

PyPI version Python versions license


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.

Install

pip install hip4               # sync (requests + websocket-client)
pip install hip4[async]        # also installs httpx + websockets for the async client
from 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.

Examples

Quickstart (sync)

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()

Quickstart (async)

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())

API

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.

adapter.events

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

adapter.market_data

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.

adapter.account

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

adapter.trading

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"

adapter.wallet

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

adapter.auth

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.

Market Types

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"))

Signing

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):

  1. Sort action keys in canonical order
  2. MessagePack-encode
  3. Append nonce as big-endian u64
  4. Append vault marker byte
  5. Keccak-256 hash → connectionId
  6. EIP-712 sign with Agent type on chainId 1337

User-signed EIP-712 (transfers, withdrawals, sends):

  • Domain: HyperliquidSignTransaction, signatureChainId: 0x66eee (testnet) or 0xa4b1 (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.

Development

poetry install --all-extras --with dev
make test          # pytest
make lint          # ruff + mypy
make format        # black + isort

Python 3.10+ is required (uses kw_only dataclasses and PEP 604 unions in some places).

Acknowledgements

Signing implementation inspired by @nktkas/hyperliquid (TS) and the official Hyperliquid Python SDK.

License

BUSL-1.1 - same as the TypeScript SDK.