Skip to main content

Module spot

Module spot 

Source
Expand description

Hyperliquid spot trading ExecutionClient implementation.

Uses the same hyperliquid_rust_sdk clients as the perpetuals client, but with spot-specific endpoints and data handling.

§Differences from Perpetuals

  • Coin naming: Spot pairs are named @{index} ("@107" is HYPE/USDC), except "PURR/USDC"; perps by their asset ("BTC"). See Spot coins.
  • Asset indices: Spot uses 10000+ (vs 0-9999 for perps)
  • Balances: Uses user_token_balances() instead of user_state() margin summary
  • No positions: Spot has no margin/leverage concepts
  • $10 minimum: Spot orders require minimum $10 notional value

§Unified Account Model

Hyperliquid uses a unified account model:

  • Spot balances count as perpetual collateral
  • Separate wallets within the unified account (explicit transfer required)
  • Perpetual liquidation cannot sweep spot holdings

§WebSocket Events

UserFills and OrderUpdates subscriptions deliver both spot and perp events, intermingled in the same stream. Events are filtered by the shape of the coin name, with CoinKind::of: this client keeps only spot coins ("@107", "PURR/USDC").

If a user has both perp and spot clients for the same wallet, events will be duplicated. Consumers should use one client type per account, or deduplicate externally.

§Spot coins

Hyperliquid names every spot pair but PURR/USDC by its index ("@107"), which does not name its assets. The client reads Hyperliquid’s spotMeta when it is created, and fails to be created if it cannot, and resolves each coin through it to the instrument BASE-QUOTE-SPOT, named from the pair’s tokens ("@107" is HYPE-USDC-SPOT, "@207" is HYPE-USDT0-SPOT).

A spot coin missing from spotMeta, such as a pair listed after the client was created, makes it read spotMeta again, at most once every ten seconds, each read abandoned after five. A coin still missing after that is:

Since every report names a pair from its tokens as Hyperliquid spells them, an order’s instrument must spell them the same way: kPEPE-USDC-SPOT, not KPEPE-USDC-SPOT. ExecutionClient::open_order refuses an order under another spelling unsent, with ApiError::InstrumentInvalid naming the one to use. An order is then reported under the name it was placed under, and the reads that take instruments, which match names exactly, find it. The perpetuals client matches names exactly too.

Neither the reads nor cancel_order check the spelling. An instruments filter naming a pair in another spelling, or no listed pair, matches nothing, so the read returns nothing for it without an error. ExecutionClient::cancel_order sends the coin as the instrument spells it, so a cancel under another spelling fails in the SDK.

Orders are placed through the SDK’s ExchangeClient, which reads spotMeta once, when it is created, and is never refreshed. So a pair listed after the client was created can be reported but not traded until the client is created again.

§Conditional Orders (Stop, TakeProfit)

See super module documentation for conditional order support details. The same constraints apply to spot:

  • Supported: Stop, StopLimit, TakeProfit, TakeProfitLimit
  • Unsupported: TrailingStop, TrailingStopLimit, Market

§Client order ids

As for perpetuals, every order must be placed under a client id in ClientOrderId::uuid() form. See the super module documentation for why.

Structs§

HyperliquidSpotClient
Hyperliquid spot trading execution client.