hyperliquid_http_private/
http_private.rs1use std::env;
17
18use nautilus_hyperliquid::http::{
19 client::HyperliquidHttpClient,
20 models::{
21 HyperliquidExecOrderKind, HyperliquidExecPlaceOrderRequest, HyperliquidExecTpSl,
22 HyperliquidExecTriggerParams,
23 },
24};
25use rust_decimal_macros::dec;
26use tracing::level_filters::LevelFilter;
27
28#[tokio::main]
29async fn main() -> Result<(), Box<dyn std::error::Error>> {
30 tracing_subscriber::fmt()
31 .with_max_level(LevelFilter::INFO)
32 .init();
33
34 let args: Vec<String> = env::args().collect();
35 let testnet = args.get(1).is_some_and(|s| s == "testnet");
36 let test_conditional = args.get(1).is_some_and(|s| s == "conditional")
37 || args.get(2).is_some_and(|s| s == "conditional");
38
39 tracing::info!("Starting Hyperliquid HTTP private example");
40 if testnet {
41 tracing::info!(
42 "Testnet parameter provided - ensure HYPERLIQUID_TESTNET_PK environment variable is set"
43 );
44 } else {
45 tracing::info!("Mainnet mode - ensure HYPERLIQUID_PK environment variable is set");
46 }
47 if test_conditional {
48 tracing::info!("Conditional orders test mode enabled");
49 }
50
51 let client = match HyperliquidHttpClient::from_env() {
53 Ok(client) => {
54 tracing::info!("Testnet mode: {}", client.is_testnet());
55 client
56 }
57 Err(_) => {
58 tracing::warn!(
59 "No credentials found in environment (HYPERLIQUID_PK). Skipping authenticated examples."
60 );
61 return Ok(());
62 }
63 };
64
65 let user_address = "0x0000000000000000000000000000000000000000";
67
68 if test_conditional {
70 tracing::info!("=== Testing Conditional Orders ===");
71 test_conditional_orders(&client).await?;
72 return Ok(());
73 }
74
75 match client.info_user_fills(user_address).await {
77 Ok(fills) => {
78 tracing::info!("Fetched {} fills", fills.len());
79 for (i, fill) in fills.iter().take(3).enumerate() {
80 tracing::info!("Fill {}: {} {} @ {}", i, fill.side, fill.sz, fill.px);
81 }
82 }
83 Err(e) => {
84 tracing::info!("Failed to fetch fills: {}", e);
85 }
86 }
87
88 let example_order_id = 12345u64;
90 match client
91 .info_order_status(user_address, example_order_id)
92 .await
93 {
94 Ok(status) => {
95 tracing::info!("Order status: {:?}", status);
96 }
97 Err(e) => {
98 tracing::info!("Order status query failed (expected for demo ID): {}", e);
99 }
100 }
101
102 Ok(())
103}
104
105async fn test_conditional_orders(
107 _client: &HyperliquidHttpClient,
108) -> Result<(), Box<dyn std::error::Error>> {
109 tracing::info!("Testing conditional order types:");
110 tracing::info!(" - StopMarket (is_market=true, tpsl=Sl)");
111 tracing::info!(" - StopLimit (is_market=false, tpsl=Sl)");
112 tracing::info!(" - MarketIfTouched (is_market=true, tpsl=Tp)");
113 tracing::info!(" - LimitIfTouched (is_market=false, tpsl=Tp)");
114 tracing::info!("");
115
116 let stop_market_buy = HyperliquidExecPlaceOrderRequest {
119 asset: 0, is_buy: true,
121 price: dec!(0), size: dec!(0.001),
123 reduce_only: false,
124 kind: HyperliquidExecOrderKind::Trigger {
125 trigger: HyperliquidExecTriggerParams {
126 is_market: true,
127 trigger_px: dec!(45000), tpsl: HyperliquidExecTpSl::Sl, },
130 },
131 cloid: None,
132 };
133
134 let _stop_limit_sell = HyperliquidExecPlaceOrderRequest {
137 asset: 0,
138 is_buy: false,
139 price: dec!(44900), size: dec!(0.001),
141 reduce_only: false,
142 kind: HyperliquidExecOrderKind::Trigger {
143 trigger: HyperliquidExecTriggerParams {
144 is_market: false,
145 trigger_px: dec!(45000), tpsl: HyperliquidExecTpSl::Sl, },
148 },
149 cloid: None,
150 };
151
152 let _market_if_touched_buy = HyperliquidExecPlaceOrderRequest {
155 asset: 0,
156 is_buy: true,
157 price: dec!(0), size: dec!(0.001),
159 reduce_only: false,
160 kind: HyperliquidExecOrderKind::Trigger {
161 trigger: HyperliquidExecTriggerParams {
162 is_market: true,
163 trigger_px: dec!(46000), tpsl: HyperliquidExecTpSl::Tp, },
166 },
167 cloid: None,
168 };
169
170 let _limit_if_touched_sell = HyperliquidExecPlaceOrderRequest {
173 asset: 0,
174 is_buy: false,
175 price: dec!(45900), size: dec!(0.001),
177 reduce_only: false,
178 kind: HyperliquidExecOrderKind::Trigger {
179 trigger: HyperliquidExecTriggerParams {
180 is_market: false,
181 trigger_px: dec!(46000), tpsl: HyperliquidExecTpSl::Tp, },
184 },
185 cloid: None,
186 };
187
188 tracing::info!("Example conditional order structures created:");
189 tracing::info!(" 1. Stop Market BUY @ trigger $45,000");
190 tracing::info!(" 2. Stop Limit SELL @ trigger $45,000, limit $44,900");
191 tracing::info!(" 3. Market If Touched BUY @ trigger $46,000");
192 tracing::info!(" 4. Limit If Touched SELL @ trigger $46,000, limit $45,900");
193 tracing::info!("");
194 tracing::info!(
195 "To actually place orders, create an ExchangeAction::Order and call client.post_action()"
196 );
197 tracing::info!("");
198 tracing::info!("Example code:");
199 tracing::info!(
200 r#"
201 let action = HyperliquidExecAction::Order {{
202 orders: vec![stop_market_buy],
203 grouping: HyperliquidExecGrouping::Na,
204 builder: None,
205 }};
206 let response = client.post_action(&action).await?;
207 "#
208 );
209
210 let example_json = serde_json::to_string_pretty(&stop_market_buy)?;
212 tracing::info!("Stop Market order JSON format:");
213 tracing::info!("{}", example_json);
214
215 Ok(())
216}