Public Hyperliquid market data in Rust: discover markets, stream trades and level-2 books (L2), or replay saved JSON frames. Supports spot, perpetuals, HIP-3 assets, and HIP-4 outcomes on mainnet and testnet.
The client uses hl-depth for decimal types, metadata, and book validation. Access is read-only and needs no API key or wallet.
Requires Rust 1.90 or newer.
git clone https://github.com/arthur-x88/hl-flow.git
cd hl-flow
# Replay the bundled synthetic fixture offline.
cargo run --locked --example replay
# Resolve BTC from metadata, then stream for 15 seconds.
cargo run --locked --example live -- BTC 15The replay accepts three trades, suppresses one duplicate, and closes one one-minute bar. It leaves the final bar open. To replay your own file:
cargo run --locked --example replay -- path/to/frames.ndjsonEach line must contain a complete Hyperliquid JSON text frame. Live data and replay use the same decoder.
List identifiers and precision before subscribing:
cargo run --locked --example markets -- mainnet
cargo run --locked --example markets -- mainnet xyz
cargo run --locked --example markets -- mainnet --outcomes| Market | Example subscription coin |
|---|---|
| Perpetual | BTC |
| Spot | @107 |
| HIP-3 perpetual | xyz:XYZ100 |
| HIP-4 outcome side | #12090 |
Use an identifier returned by the selected network. Examples can expire or be unavailable, and mainnet and testnet have separate listings.
cargo run --locked --example live -- '@107' 15 mainnet
cargo run --locked --example live -- xyz:XYZ100 15 mainnet
cargo run --locked --example live -- '#12090' 15 mainnet
cargo run --locked --example live -- BTC 15 testnetQuote # coins in your shell. The live example resolves metadata before opening
the socket: meta and spotMeta for spot/perps, or outcomeMeta for outcomes.
A dex:COIN selects that HIP-3 DEX. Unknown coins and delisted perps fail before
subscription. The duration starts after metadata discovery.
Add these Git and runtime dependencies to Cargo.toml. The crate is distributed
through Git, with hl-depth pinned to a public revision.
[dependencies]
hl-flow = { git = "https://github.com/arthur-x88/hl-flow" }
tokio = { version = "1", features = ["full"] }use hl_flow::{
client::{Client, Config},
primitives::types::Coin,
protocol::Event,
};
use tokio::sync::mpsc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new(Config::mainnet(vec![Coin::new("BTC")?]))?;
let (tx, mut rx) = mpsc::channel::<Event>(256);
let worker = tokio::spawn(client.run(tx));
while let Some(event) = rx.recv().await {
println!("{event:?}");
// Consumers that keep a book must clear it on Event::Disconnected.
}
worker.await??; // Surface terminal errors, including SlowConsumer.
Ok(())
}Client subscribes to the coins supplied by the caller. To resolve an instrument
and its precision first, use InfoClient:
use hl_flow::{info::InfoClient, network::Network, primitives::types::Coin};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let info = InfoClient::new(Network::Mainnet)?;
let catalog = info.catalog(None).await?;
let coin = Coin::new("@107")?;
let market = catalog.resolve(&coin).ok_or("market unavailable")?;
if let Some(rules) = market.rules() {
println!("{}: size precision {}", market.label(), rules.size_decimals());
}
Ok(())
}Use the same Network for discovery and streaming. Refresh catalogs when needed;
metadata calls are separate requests and do not form an atomic snapshot.
The client sends a JSON ping every 20 seconds, times out after 50 seconds without
a received frame, and gives each connection or write operation 10 seconds. It
allows five retries over a run, using capped exponential delays. Each connection
resends both subscriptions for every coin. Connected means the requests were
sent; acknowledgements and market data follow separately.
Consumers own their cached state. On Disconnected, clear books and mark the
affected candle interval incomplete. Reconnecting cannot recover every trade
missed during the gap. If the bounded queue fills, run returns SlowConsumer.
Monitor the worker's result and invalidate cached state on terminal errors too.
Dropping the receiver cancels the client.
| Component | Behavior |
|---|---|
protocol |
Decodes trades and l2Book; rejects an entire trade batch if any print is invalid. Unknown channels become Ignored; malformed payloads and server errors end the run. |
dedup |
Tracks (time, coin, tid) in a bounded FIFO window. Keep it across reconnects; an evicted key can be accepted again. |
candle |
Builds OHLCV in exchange-time order. A later nonempty bucket closes the current bar. Late trades return an error; gaps stay empty. |
The live example prints raw trades and replaces book snapshots. The replay example also applies deduplication and candle aggregation. Account access and order execution are outside this library.
InfoClient::outcome_catalog() resolves both sides of each listed outcome. For
outcome 1, the market coins are #10 and #11. The corresponding + token
names are rejected as subscription coins. Labels and resolution descriptions
come from metadata.
Outcome books and trades use the same decoding and aggregation APIs as other
markets. Instrument::rules() returns None for outcomes because outcomeMeta
does not expose szDecimals. Order precision, settlement, question-level
portfolio accounting, and split/merge/negate actions are not implemented.
cargo fmt --check
cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
cargo doc --locked --no-depsCI runs on Linux and Windows without exchange access. Local servers test HTTP metadata requests, WebSocket reconnects, resubscription, heartbeats, timeouts, and queue overflow. The Rust examples above are compiled as doctests. Recorded results, including mainnet and testnet checks, are in VALIDATION.md.
For 0.1 users: replace Config::endpoint assignments with
Config::new(Network::Mainnet, coins) or Config::testnet(coins). Read the URL
through config.endpoint(). Error::Exchange is now Error::Hyperliquid.
See the changelog.
- Subscriptions and payloads
- Heartbeats
- Perpetual metadata
- Spot and outcome metadata
- HIP-4 markets
- Outcome identifiers
Released under the MIT License. The license file contains the terms and retained copyright notices, including those for adapted code. This project is not affiliated with Hyperliquid.