use std::env;
use nautilus_hyperliquid::http::{
client::HyperliquidHttpClient,
models::{
HyperliquidExecOrderKind, HyperliquidExecPlaceOrderRequest, HyperliquidExecTpSl,
HyperliquidExecTriggerParams,
},
};
use rust_decimal_macros::dec;
#[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 testnet = args.get(1).is_some_and(|s| s == "testnet");
let test_conditional = args.get(1).is_some_and(|s| s == "conditional")
|| args.get(2).is_some_and(|s| s == "conditional");
log::info!("Starting Hyperliquid HTTP private example");
if testnet {
log::info!(
"Testnet parameter provided - ensure HYPERLIQUID_TESTNET_PK environment variable is set"
);
} else {
log::info!("Mainnet mode - ensure HYPERLIQUID_PK environment variable is set");
}
if test_conditional {
log::info!("Conditional orders test mode enabled");
}
let client = match HyperliquidHttpClient::from_env(testnet) {
Ok(client) => {
log::info!("Testnet mode: {}", client.is_testnet());
client
}
Err(e) => {
let env_var = if testnet {
"HYPERLIQUID_TESTNET_PK"
} else {
"HYPERLIQUID_PK"
};
log::warn!(
"No credentials found in environment ({env_var}): {e}, skipping authenticated examples"
);
return Ok(());
}
};
let user_address = "0x0000000000000000000000000000000000000000";
if test_conditional {
log::info!("=== Testing Conditional Orders ===");
test_conditional_orders(&client).await?;
return Ok(());
}
match client.info_user_fills(user_address).await {
Ok(fills) => {
log::info!("Fetched {} fills", fills.len());
for (i, fill) in fills.iter().take(3).enumerate() {
log::info!("Fill {}: {} {} @ {}", i, fill.side, fill.sz, fill.px);
}
}
Err(e) => {
log::info!("Failed to fetch fills: {e}");
}
}
let example_order_id = 12345u64;
match client
.info_order_status(user_address, example_order_id)
.await
{
Ok(status) => {
log::info!("Order status: {status:?}");
}
Err(e) => {
log::info!("Order status query failed (expected for demo ID): {e}");
}
}
Ok(())
}
async fn test_conditional_orders(
_client: &HyperliquidHttpClient,
) -> Result<(), Box<dyn std::error::Error>> {
log::info!("Testing conditional order types:");
log::info!(" - StopMarket (is_market=true, tpsl=Sl)");
log::info!(" - StopLimit (is_market=false, tpsl=Sl)");
log::info!(" - MarketIfTouched (is_market=true, tpsl=Tp)");
log::info!(" - LimitIfTouched (is_market=false, tpsl=Tp)");
log::info!("");
let stop_market_buy = HyperliquidExecPlaceOrderRequest {
asset: 0, is_buy: true,
price: dec!(0), size: dec!(0.001),
reduce_only: false,
kind: HyperliquidExecOrderKind::Trigger {
trigger: HyperliquidExecTriggerParams {
is_market: true,
trigger_px: dec!(45000), tpsl: HyperliquidExecTpSl::Sl, },
},
cloid: None,
};
let _stop_limit_sell = HyperliquidExecPlaceOrderRequest {
asset: 0,
is_buy: false,
price: dec!(44900), size: dec!(0.001),
reduce_only: false,
kind: HyperliquidExecOrderKind::Trigger {
trigger: HyperliquidExecTriggerParams {
is_market: false,
trigger_px: dec!(45000), tpsl: HyperliquidExecTpSl::Sl, },
},
cloid: None,
};
let _market_if_touched_buy = HyperliquidExecPlaceOrderRequest {
asset: 0,
is_buy: true,
price: dec!(0), size: dec!(0.001),
reduce_only: false,
kind: HyperliquidExecOrderKind::Trigger {
trigger: HyperliquidExecTriggerParams {
is_market: true,
trigger_px: dec!(46000), tpsl: HyperliquidExecTpSl::Tp, },
},
cloid: None,
};
let _limit_if_touched_sell = HyperliquidExecPlaceOrderRequest {
asset: 0,
is_buy: false,
price: dec!(45900), size: dec!(0.001),
reduce_only: false,
kind: HyperliquidExecOrderKind::Trigger {
trigger: HyperliquidExecTriggerParams {
is_market: false,
trigger_px: dec!(46000), tpsl: HyperliquidExecTpSl::Tp, },
},
cloid: None,
};
log::info!("Example conditional order structures created:");
log::info!(" 1. Stop Market BUY @ trigger $45,000");
log::info!(" 2. Stop Limit SELL @ trigger $45,000, limit $44,900");
log::info!(" 3. Market If Touched BUY @ trigger $46,000");
log::info!(" 4. Limit If Touched SELL @ trigger $46,000, limit $45,900");
log::info!("");
log::info!(
"To actually place orders, create an ExchangeAction::Order and call client.post_action()"
);
log::info!("");
log::info!("Example code:");
log::info!(
"
let action = HyperliquidExecAction::Order {{
orders: vec![stop_market_buy],
grouping: HyperliquidExecGrouping::Na,
builder: None,
}};
let response = client.post_action(&action).await?;
"
);
let example_json = serde_json::to_string_pretty(&stop_market_buy)?;
log::info!("Stop Market order JSON format:");
log::info!("{example_json}");
Ok(())
}