Understanding Hyperliquid’s WebSocket architecture
Hyperliquid provides two essential WebSocket channels for monitoring trading activity. These channels serve different purposes:orderUpdates
delivers WsOrder[]
events containing order status changes—when orders are placed, modified, or canceled. This is your primary signal for mirroring trading decisions.
userEvents
provides WsUserEvent
data including fills, funding payments, and liquidations. For this tutorial, the most important part is that the channel provides TWAP order updates not available in orderUpdates
.
Together, these channels give you a complete picture of a trader’s activity:
How spot markets work on Hyperliquid
Before diving into implementation, you need to understand how Hyperliquid distinguishes spot from perpetual assets. Thecoin
field format tells you the market type:
Perpetual contracts use simple asset names returned from the meta
endpoint:
BTC
— Bitcoin perpetualETH
— Ethereum perpetualSOL
— Solana perpetual
@{index}
— Numeric spot pair index (e.g.,@0
for BTC/USDC,@107
for HYPE/USDC){TOKEN}/USDC
— Human-readable pair names (e.g.,PURR/USDC
)
@index
format? It’s Hyperliquid’s internal representation—more efficient for the order book engine. When you receive WebSocket events, the coin
field typically contains the @index
format for spot trades.
This matters for copy trading because:
- You receive
@123
in WebSocket events - You need to query metadata using that index
- You place orders using the same
@index
format
spotMeta
endpoint, which provides crucial information like price precision and size decimals.
Detecting spot vs perpetual orders
Your bot monitors a trader who trades both spot and perps. Spot orders are cash trades (you own the asset), perps involve leverage and funding payments. For simplicity, you might want to mirror only spot trades initially. Thecoin
field in WebSocket events tells you the market type:
@
or contains /
, it’s a spot market. Otherwise, it’s a perpetual contract.
Filter to spot-only mirroring:
Dynamic order sizing for spot assets
A leader might trade $10,000 of BTC, but your bot has a $1,000 budget. You need proportional sizing based on your capital allocation. But it’s not just about scaling down—Hyperliquid enforces strict precision rules. According to the official documentation: Size precision — Round to the asset’sszDecimals
(found in meta
response):
szDecimals = 3
:1.001
valid,1.0001
invalidszDecimals = 1
:0.1
valid,0.01
invalid
MAX_DECIMALS - szDecimals
decimal places (spot: MAX_DECIMALS = 8
, perps: MAX_DECIMALS = 6
):
szDecimals = 0
:0.0001234
valid (8 decimals)szDecimals = 2
:0.0001234
invalid (exceeds 8-2=6 decimals)1234.5
valid,1234.56
invalid (too many sig figs)
szDecimals = 5
→ 0.00023076923...
rounds to 0.00023
.
Understanding order lifecycle and state transitions
Orders on Hyperliquid go through a lifecycle with specific state transitions. When you subscribe toorderUpdates
, you receive events for each state change.
Order state events explained
open
status — A new order has been placed on the book by the leader.
canceled
status — Order removed from the book, either by:
- Trader manually canceling
- Part of a modification (old order canceled, new order created with different ID)
- System cancellation (insufficient balance, delisting, etc.)
filled
status — Order fully executed. You’ll also see detailed fill information in the userEvents
channel.
How order modifications work
When a trader modifies an order on Hyperliquid (changes price or size), the exchange handles this atomically as:- Cancel the existing order (you receive
"canceled"
event) - Create a new order with the new parameters (you receive
"open"
event with new order ID)
order_mappings
dictionary tracks active orders by mapping each leader order ID to your corresponding follower order ID. This allows you to cancel the correct follower order when the leader cancels
Placing orders with the Hyperliquid SDK
The hyperliquid-python-sdk provides theexchange.order()
method for placing trades. Let’s break down each parameter and why it matters:
resting
and filled
? If you place a limit buy at $100 and the best ask is $99, your order fills immediately. You still need the order ID for tracking fills and state management.
Testing with same wallet (development only)
This section describes a development shortcut for testing. In production, you’ll use separate leader and follower wallets, and this infinite loop problem won’t exist.
1
Leader places order
The leader wallet (your test wallet) initiates a new order
2
Bot mirrors it as follower
Your bot detects the order and places a mirror order using the same wallet
3
Bot sees its own follower order
WebSocket receives the follower order as a “new leader order” (because you’re watching the same wallet)
4
Bot tries to mirror again
Bot attempts to mirror the follower order, creating another order
5
Infinite loop
Process repeats indefinitely, placing unlimited orders
{leader_order_id: follower_order_id}
. Later, when that follower order appears in the WebSocket feed (because you’re watching your own wallet), you check: “Is this order ID in my follower list?” If yes, ignore it.
Important: In production with separate wallets, leader and follower order IDs never overlap—you don’t need this check. This is purely for development convenience.
Sequential processing (simplified for testing)
This section describes a simplified architecture for testing. In production with high-frequency trading, you’d process events in parallel with proper concurrency controls.
- Process multiple order events simultaneously
- Requires locks/semaphores to prevent race conditions
- Optimal for high-frequency traders placing hundreds of orders per minute
- More complex to implement and debug
- Process one order event at a time
- No race conditions by design
- Simple to implement and reason about
- Sufficient for mirroring human traders (10-100 orders per hour)
Key takeaways
Spot vs perp identification
Spot vs perp identification
Hyperliquid uses naming conventions:
@index
or TOKEN/USDC
for spot, simple names like BTC
for perps.Order modifications are cancel + create
Order modifications are cancel + create
Modifications appear as canceled old order + new open order, with a different order ID for each.
No special modification handling needed
No special modification handling needed
Since Hyperliquid sends separate cancel and create events for modifications, your bot only needs to handle “open” and “canceled” statuses.
State management via order mappings
State management via order mappings
Track leader-to-follower order ID mappings to handle cancellations.
Dynamic sizing with metadata
Dynamic sizing with metadata
Query
szDecimals
from spot metadata to calculate properly rounded order sizes for each asset.Testing shortcuts don't scale
Testing shortcuts don't scale
Same-wallet testing and sequential processing simplify development but require changes for production.
Complete implementation: See the hyperliquid bot examples repository for the full working code.