use std::{env, time::Duration};
use nautilus_hyperliquid::{
common::{consts::ws_url, enums::HyperliquidEnvironment},
http::HyperliquidHttpClient,
websocket::client::HyperliquidWebSocketClient,
};
use nautilus_model::instruments::{Instrument, InstrumentAny};
use nautilus_network::websocket::TransportBackend;
use tokio::{pin, signal};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
nautilus_common::logging::ensure_logging_initialized();
let args: Vec<String> = env::args().collect();
let environment = if args.get(1).is_some_and(|s| s == "testnet") {
HyperliquidEnvironment::Testnet
} else {
HyperliquidEnvironment::Mainnet
};
log::info!("Starting Hyperliquid WebSocket data example");
log::info!("Environment: {environment:?}");
let http_client = HyperliquidHttpClient::new(environment, 60, None)?;
let instruments = http_client.request_instruments().await?;
log::info!("Loaded {} instruments", instruments.len());
let btc_inst = instruments
.iter()
.find(|i| i.raw_symbol().as_str() == "BTC")
.ok_or("BTC-USD-PERP instrument not found")?;
let instrument_id = match btc_inst {
InstrumentAny::CryptoPerpetual(inst) => inst.id,
_ => return Err("Expected CryptoPerpetual instrument".into()),
};
log::info!("Using instrument: {instrument_id}");
let ws_url = ws_url(environment);
log::info!("WebSocket URL: {ws_url}");
let mut client = HyperliquidWebSocketClient::new(
Some(ws_url.to_string()),
environment,
None,
TransportBackend::default(),
None,
);
client.cache_instruments(instruments);
client.connect().await?;
log::info!("Connected to Hyperliquid WebSocket");
tokio::time::sleep(Duration::from_millis(500)).await;
log::info!("Subscribing to trades for {instrument_id}");
client.subscribe_trades(instrument_id).await?;
log::info!("Subscribing to BBO for {instrument_id}");
client.subscribe_quotes(instrument_id).await?;
tokio::time::sleep(Duration::from_secs(1)).await;
let sigint = signal::ctrl_c();
pin!(sigint);
let mut message_count = 0;
loop {
tokio::select! {
Some(message) = client.next_event() => {
message_count += 1;
log::info!("Message #{message_count}: {message:?}");
}
_ = &mut sigint => {
log::info!("Received SIGINT, closing connection...");
client.disconnect().await?;
break;
}
else => break,
}
}
log::info!("Received {message_count} total messages");
Ok(())
}