pub struct HyperliquidConnector { /* private fields */ }Expand description
Hyperliquid DEX connector
Implementations§
Source§impl HyperliquidConnector
impl HyperliquidConnector
Sourcepub async fn new(
credentials: Option<Credentials>,
is_testnet: bool,
) -> ExchangeResult<Self>
pub async fn new( credentials: Option<Credentials>, is_testnet: bool, ) -> ExchangeResult<Self>
Create new connector
§Arguments
credentials- Wallet credentials (private key in api_secret, address in api_key)is_testnet- Use testnet if true
Sourcepub async fn public(is_testnet: bool) -> ExchangeResult<Self>
pub async fn public(is_testnet: bool) -> ExchangeResult<Self>
Create public connector (no authentication, market data only)
Examples found in repository?
307async fn test_hyperliquid_rest() -> RestTally {
308 println!("\n── Hyperliquid REST ─────────────────────────────────────────");
309 let mut tally = RestTally { exchange: "Hyperliquid".into(), tested: 0, passed: 0, failed: 0 };
310
311 let conn = match HyperliquidConnector::public(false).await {
312 Ok(c) => c,
313 Err(e) => {
314 println!(" FAIL: connector init -> {}", e);
315 tally.failed += 1;
316 tally.tested += 1;
317 return tally;
318 }
319 };
320
321 // get_meta_and_asset_ctxs
322 tally.tested += 1;
323 match conn.get_meta_and_asset_ctxs().await {
324 Ok(v) => {
325 let summary = if v.is_array() {
326 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
327 } else {
328 abbrev(&v)
329 };
330 println!(" OK: get_meta_and_asset_ctxs -> {}", summary);
331 tally.passed += 1;
332 }
333 Err(e) => { fail_rest!("get_meta_and_asset_ctxs", e); tally.failed += 1; }
334 }
335
336 // get_predicted_fundings
337 tally.tested += 1;
338 match conn.get_predicted_fundings().await {
339 Ok(v) => {
340 let summary = if v.is_array() {
341 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
342 } else {
343 abbrev(&v)
344 };
345 println!(" OK: get_predicted_fundings -> {}", summary);
346 tally.passed += 1;
347 }
348 Err(e) => { fail_rest!("get_predicted_fundings", e); tally.failed += 1; }
349 }
350
351 // NEW: get_spot_meta_and_asset_ctxs
352 tally.tested += 1;
353 match conn.get_spot_meta_and_asset_ctxs().await {
354 Ok(v) => {
355 let summary = if v.is_array() {
356 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
357 } else {
358 abbrev(&v)
359 };
360 println!(" OK: get_spot_meta_and_asset_ctxs -> {}", summary);
361 tally.passed += 1;
362 }
363 Err(e) => { fail_rest!("get_spot_meta_and_asset_ctxs", e); tally.failed += 1; }
364 }
365
366 // NEW: get_non_funding_ledger_updates (zero address — expect empty array)
367 tally.tested += 1;
368 let now_ms = std::time::SystemTime::now()
369 .duration_since(std::time::UNIX_EPOCH)
370 .map(|d| d.as_millis() as i64)
371 .unwrap_or(0);
372 match conn.get_non_funding_ledger_updates(
373 "0x0000000000000000000000000000000000000000",
374 0,
375 Some(now_ms),
376 ).await {
377 Ok(v) => {
378 let summary = if v.is_array() {
379 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
380 } else {
381 abbrev(&v)
382 };
383 println!(" OK: get_non_funding_ledger_updates(zero_addr) -> {}", summary);
384 tally.passed += 1;
385 }
386 Err(e) => { fail_rest!("get_non_funding_ledger_updates", e); tally.failed += 1; }
387 }
388
389 // NEW: get_vault_details (HLP vault)
390 tally.tested += 1;
391 match conn.get_vault_details("0xa15099a30bbf2e68942d6f4c43d70d04faeab0a0").await {
392 Ok(v) => {
393 let summary = if v.is_null() { "null (unknown vault)".to_string() } else { abbrev(&v) };
394 println!(" OK: get_vault_details(HLP) -> {}", summary);
395 tally.passed += 1;
396 }
397 Err(e) => { fail_rest!("get_vault_details", e); tally.failed += 1; }
398 }
399
400 tally
401}Sourcepub async fn get_metadata(&self) -> ExchangeResult<Value>
pub async fn get_metadata(&self) -> ExchangeResult<Value>
Get perpetuals metadata (asset index mapping)
Sourcepub async fn get_spot_metadata(&self) -> ExchangeResult<Value>
pub async fn get_spot_metadata(&self) -> ExchangeResult<Value>
Get spot metadata
Sourcepub async fn get_all_mids(&self) -> ExchangeResult<Value>
pub async fn get_all_mids(&self) -> ExchangeResult<Value>
Get all mid prices
Sourcepub async fn get_meta_and_asset_ctxs(&self) -> ExchangeResult<Value>
pub async fn get_meta_and_asset_ctxs(&self) -> ExchangeResult<Value>
Get perpetuals metadata combined with all asset contexts in one call.
POSTs {"type":"metaAndAssetCtxs"} to the /info endpoint.
Returns the raw JSON response which is a two-element array:
[meta_object, array_of_asset_ctx_objects].
Useful for bootstrapping: get the full universe + current mark/index prices
- funding rates + OI in a single round-trip instead of two separate calls.
Examples found in repository?
307async fn test_hyperliquid_rest() -> RestTally {
308 println!("\n── Hyperliquid REST ─────────────────────────────────────────");
309 let mut tally = RestTally { exchange: "Hyperliquid".into(), tested: 0, passed: 0, failed: 0 };
310
311 let conn = match HyperliquidConnector::public(false).await {
312 Ok(c) => c,
313 Err(e) => {
314 println!(" FAIL: connector init -> {}", e);
315 tally.failed += 1;
316 tally.tested += 1;
317 return tally;
318 }
319 };
320
321 // get_meta_and_asset_ctxs
322 tally.tested += 1;
323 match conn.get_meta_and_asset_ctxs().await {
324 Ok(v) => {
325 let summary = if v.is_array() {
326 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
327 } else {
328 abbrev(&v)
329 };
330 println!(" OK: get_meta_and_asset_ctxs -> {}", summary);
331 tally.passed += 1;
332 }
333 Err(e) => { fail_rest!("get_meta_and_asset_ctxs", e); tally.failed += 1; }
334 }
335
336 // get_predicted_fundings
337 tally.tested += 1;
338 match conn.get_predicted_fundings().await {
339 Ok(v) => {
340 let summary = if v.is_array() {
341 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
342 } else {
343 abbrev(&v)
344 };
345 println!(" OK: get_predicted_fundings -> {}", summary);
346 tally.passed += 1;
347 }
348 Err(e) => { fail_rest!("get_predicted_fundings", e); tally.failed += 1; }
349 }
350
351 // NEW: get_spot_meta_and_asset_ctxs
352 tally.tested += 1;
353 match conn.get_spot_meta_and_asset_ctxs().await {
354 Ok(v) => {
355 let summary = if v.is_array() {
356 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
357 } else {
358 abbrev(&v)
359 };
360 println!(" OK: get_spot_meta_and_asset_ctxs -> {}", summary);
361 tally.passed += 1;
362 }
363 Err(e) => { fail_rest!("get_spot_meta_and_asset_ctxs", e); tally.failed += 1; }
364 }
365
366 // NEW: get_non_funding_ledger_updates (zero address — expect empty array)
367 tally.tested += 1;
368 let now_ms = std::time::SystemTime::now()
369 .duration_since(std::time::UNIX_EPOCH)
370 .map(|d| d.as_millis() as i64)
371 .unwrap_or(0);
372 match conn.get_non_funding_ledger_updates(
373 "0x0000000000000000000000000000000000000000",
374 0,
375 Some(now_ms),
376 ).await {
377 Ok(v) => {
378 let summary = if v.is_array() {
379 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
380 } else {
381 abbrev(&v)
382 };
383 println!(" OK: get_non_funding_ledger_updates(zero_addr) -> {}", summary);
384 tally.passed += 1;
385 }
386 Err(e) => { fail_rest!("get_non_funding_ledger_updates", e); tally.failed += 1; }
387 }
388
389 // NEW: get_vault_details (HLP vault)
390 tally.tested += 1;
391 match conn.get_vault_details("0xa15099a30bbf2e68942d6f4c43d70d04faeab0a0").await {
392 Ok(v) => {
393 let summary = if v.is_null() { "null (unknown vault)".to_string() } else { abbrev(&v) };
394 println!(" OK: get_vault_details(HLP) -> {}", summary);
395 tally.passed += 1;
396 }
397 Err(e) => { fail_rest!("get_vault_details", e); tally.failed += 1; }
398 }
399
400 tally
401}Sourcepub async fn get_clearinghouse_state(&self, user: &str) -> ExchangeResult<Value>
pub async fn get_clearinghouse_state(&self, user: &str) -> ExchangeResult<Value>
Get the clearinghouse state for a user address.
POSTs {"type":"clearinghouseState","user":"<address>"} to /info.
Returns account value, margin summary, and all open positions.
No cryptographic signature required — only the wallet address.
Source§impl HyperliquidConnector
impl HyperliquidConnector
Sourcepub async fn batch_amend_orders(
&self,
modifies: Vec<(String, f64, f64, String)>,
) -> ExchangeResult<Value>
pub async fn batch_amend_orders( &self, modifies: Vec<(String, f64, f64, String)>, ) -> ExchangeResult<Value>
Batch modify (amend) multiple existing orders via the batchModify action on /exchange.
Each entry in modifies is (order_id_str, new_price, new_size, asset_symbol).
All four fields are required per Hyperliquid’s batchModify spec.
Max 10 modifies per batch.
Returns the raw JSON exchange response.
Source§impl HyperliquidConnector
impl HyperliquidConnector
Sourcepub async fn get_predicted_fundings(&self) -> ExchangeResult<Value>
pub async fn get_predicted_fundings(&self) -> ExchangeResult<Value>
Get predicted (next-epoch) funding rates for all perpetual assets.
POSTs {"type": "predictedFundings"} to the info endpoint.
Returns the raw JSON value — callers can parse the array of
[coin, [[venue, predicted_rate], ...]] entries as needed.
Examples found in repository?
307async fn test_hyperliquid_rest() -> RestTally {
308 println!("\n── Hyperliquid REST ─────────────────────────────────────────");
309 let mut tally = RestTally { exchange: "Hyperliquid".into(), tested: 0, passed: 0, failed: 0 };
310
311 let conn = match HyperliquidConnector::public(false).await {
312 Ok(c) => c,
313 Err(e) => {
314 println!(" FAIL: connector init -> {}", e);
315 tally.failed += 1;
316 tally.tested += 1;
317 return tally;
318 }
319 };
320
321 // get_meta_and_asset_ctxs
322 tally.tested += 1;
323 match conn.get_meta_and_asset_ctxs().await {
324 Ok(v) => {
325 let summary = if v.is_array() {
326 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
327 } else {
328 abbrev(&v)
329 };
330 println!(" OK: get_meta_and_asset_ctxs -> {}", summary);
331 tally.passed += 1;
332 }
333 Err(e) => { fail_rest!("get_meta_and_asset_ctxs", e); tally.failed += 1; }
334 }
335
336 // get_predicted_fundings
337 tally.tested += 1;
338 match conn.get_predicted_fundings().await {
339 Ok(v) => {
340 let summary = if v.is_array() {
341 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
342 } else {
343 abbrev(&v)
344 };
345 println!(" OK: get_predicted_fundings -> {}", summary);
346 tally.passed += 1;
347 }
348 Err(e) => { fail_rest!("get_predicted_fundings", e); tally.failed += 1; }
349 }
350
351 // NEW: get_spot_meta_and_asset_ctxs
352 tally.tested += 1;
353 match conn.get_spot_meta_and_asset_ctxs().await {
354 Ok(v) => {
355 let summary = if v.is_array() {
356 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
357 } else {
358 abbrev(&v)
359 };
360 println!(" OK: get_spot_meta_and_asset_ctxs -> {}", summary);
361 tally.passed += 1;
362 }
363 Err(e) => { fail_rest!("get_spot_meta_and_asset_ctxs", e); tally.failed += 1; }
364 }
365
366 // NEW: get_non_funding_ledger_updates (zero address — expect empty array)
367 tally.tested += 1;
368 let now_ms = std::time::SystemTime::now()
369 .duration_since(std::time::UNIX_EPOCH)
370 .map(|d| d.as_millis() as i64)
371 .unwrap_or(0);
372 match conn.get_non_funding_ledger_updates(
373 "0x0000000000000000000000000000000000000000",
374 0,
375 Some(now_ms),
376 ).await {
377 Ok(v) => {
378 let summary = if v.is_array() {
379 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
380 } else {
381 abbrev(&v)
382 };
383 println!(" OK: get_non_funding_ledger_updates(zero_addr) -> {}", summary);
384 tally.passed += 1;
385 }
386 Err(e) => { fail_rest!("get_non_funding_ledger_updates", e); tally.failed += 1; }
387 }
388
389 // NEW: get_vault_details (HLP vault)
390 tally.tested += 1;
391 match conn.get_vault_details("0xa15099a30bbf2e68942d6f4c43d70d04faeab0a0").await {
392 Ok(v) => {
393 let summary = if v.is_null() { "null (unknown vault)".to_string() } else { abbrev(&v) };
394 println!(" OK: get_vault_details(HLP) -> {}", summary);
395 tally.passed += 1;
396 }
397 Err(e) => { fail_rest!("get_vault_details", e); tally.failed += 1; }
398 }
399
400 tally
401}Sourcepub async fn get_vault_details(
&self,
vault_address: &str,
) -> ExchangeResult<Value>
pub async fn get_vault_details( &self, vault_address: &str, ) -> ExchangeResult<Value>
Get vault details for a vault address.
POSTs {"type":"vaultDetails","vaultAddress":"<addr>"} to /info.
Returns null for unknown vaults, or a JSON object with vault state.
No authentication required.
Examples found in repository?
307async fn test_hyperliquid_rest() -> RestTally {
308 println!("\n── Hyperliquid REST ─────────────────────────────────────────");
309 let mut tally = RestTally { exchange: "Hyperliquid".into(), tested: 0, passed: 0, failed: 0 };
310
311 let conn = match HyperliquidConnector::public(false).await {
312 Ok(c) => c,
313 Err(e) => {
314 println!(" FAIL: connector init -> {}", e);
315 tally.failed += 1;
316 tally.tested += 1;
317 return tally;
318 }
319 };
320
321 // get_meta_and_asset_ctxs
322 tally.tested += 1;
323 match conn.get_meta_and_asset_ctxs().await {
324 Ok(v) => {
325 let summary = if v.is_array() {
326 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
327 } else {
328 abbrev(&v)
329 };
330 println!(" OK: get_meta_and_asset_ctxs -> {}", summary);
331 tally.passed += 1;
332 }
333 Err(e) => { fail_rest!("get_meta_and_asset_ctxs", e); tally.failed += 1; }
334 }
335
336 // get_predicted_fundings
337 tally.tested += 1;
338 match conn.get_predicted_fundings().await {
339 Ok(v) => {
340 let summary = if v.is_array() {
341 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
342 } else {
343 abbrev(&v)
344 };
345 println!(" OK: get_predicted_fundings -> {}", summary);
346 tally.passed += 1;
347 }
348 Err(e) => { fail_rest!("get_predicted_fundings", e); tally.failed += 1; }
349 }
350
351 // NEW: get_spot_meta_and_asset_ctxs
352 tally.tested += 1;
353 match conn.get_spot_meta_and_asset_ctxs().await {
354 Ok(v) => {
355 let summary = if v.is_array() {
356 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
357 } else {
358 abbrev(&v)
359 };
360 println!(" OK: get_spot_meta_and_asset_ctxs -> {}", summary);
361 tally.passed += 1;
362 }
363 Err(e) => { fail_rest!("get_spot_meta_and_asset_ctxs", e); tally.failed += 1; }
364 }
365
366 // NEW: get_non_funding_ledger_updates (zero address — expect empty array)
367 tally.tested += 1;
368 let now_ms = std::time::SystemTime::now()
369 .duration_since(std::time::UNIX_EPOCH)
370 .map(|d| d.as_millis() as i64)
371 .unwrap_or(0);
372 match conn.get_non_funding_ledger_updates(
373 "0x0000000000000000000000000000000000000000",
374 0,
375 Some(now_ms),
376 ).await {
377 Ok(v) => {
378 let summary = if v.is_array() {
379 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
380 } else {
381 abbrev(&v)
382 };
383 println!(" OK: get_non_funding_ledger_updates(zero_addr) -> {}", summary);
384 tally.passed += 1;
385 }
386 Err(e) => { fail_rest!("get_non_funding_ledger_updates", e); tally.failed += 1; }
387 }
388
389 // NEW: get_vault_details (HLP vault)
390 tally.tested += 1;
391 match conn.get_vault_details("0xa15099a30bbf2e68942d6f4c43d70d04faeab0a0").await {
392 Ok(v) => {
393 let summary = if v.is_null() { "null (unknown vault)".to_string() } else { abbrev(&v) };
394 println!(" OK: get_vault_details(HLP) -> {}", summary);
395 tally.passed += 1;
396 }
397 Err(e) => { fail_rest!("get_vault_details", e); tally.failed += 1; }
398 }
399
400 tally
401}Sourcepub async fn get_spot_meta_and_asset_ctxs(&self) -> ExchangeResult<Value>
pub async fn get_spot_meta_and_asset_ctxs(&self) -> ExchangeResult<Value>
Get spot metadata combined with all spot asset contexts in one call.
POSTs {"type":"spotMetaAndAssetCtxs"} to the /info endpoint.
Returns a two-element array: [spot_meta_object, array_of_spot_asset_ctx_objects].
Shape mirrors metaAndAssetCtxs but for spot markets.
Examples found in repository?
307async fn test_hyperliquid_rest() -> RestTally {
308 println!("\n── Hyperliquid REST ─────────────────────────────────────────");
309 let mut tally = RestTally { exchange: "Hyperliquid".into(), tested: 0, passed: 0, failed: 0 };
310
311 let conn = match HyperliquidConnector::public(false).await {
312 Ok(c) => c,
313 Err(e) => {
314 println!(" FAIL: connector init -> {}", e);
315 tally.failed += 1;
316 tally.tested += 1;
317 return tally;
318 }
319 };
320
321 // get_meta_and_asset_ctxs
322 tally.tested += 1;
323 match conn.get_meta_and_asset_ctxs().await {
324 Ok(v) => {
325 let summary = if v.is_array() {
326 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
327 } else {
328 abbrev(&v)
329 };
330 println!(" OK: get_meta_and_asset_ctxs -> {}", summary);
331 tally.passed += 1;
332 }
333 Err(e) => { fail_rest!("get_meta_and_asset_ctxs", e); tally.failed += 1; }
334 }
335
336 // get_predicted_fundings
337 tally.tested += 1;
338 match conn.get_predicted_fundings().await {
339 Ok(v) => {
340 let summary = if v.is_array() {
341 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
342 } else {
343 abbrev(&v)
344 };
345 println!(" OK: get_predicted_fundings -> {}", summary);
346 tally.passed += 1;
347 }
348 Err(e) => { fail_rest!("get_predicted_fundings", e); tally.failed += 1; }
349 }
350
351 // NEW: get_spot_meta_and_asset_ctxs
352 tally.tested += 1;
353 match conn.get_spot_meta_and_asset_ctxs().await {
354 Ok(v) => {
355 let summary = if v.is_array() {
356 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
357 } else {
358 abbrev(&v)
359 };
360 println!(" OK: get_spot_meta_and_asset_ctxs -> {}", summary);
361 tally.passed += 1;
362 }
363 Err(e) => { fail_rest!("get_spot_meta_and_asset_ctxs", e); tally.failed += 1; }
364 }
365
366 // NEW: get_non_funding_ledger_updates (zero address — expect empty array)
367 tally.tested += 1;
368 let now_ms = std::time::SystemTime::now()
369 .duration_since(std::time::UNIX_EPOCH)
370 .map(|d| d.as_millis() as i64)
371 .unwrap_or(0);
372 match conn.get_non_funding_ledger_updates(
373 "0x0000000000000000000000000000000000000000",
374 0,
375 Some(now_ms),
376 ).await {
377 Ok(v) => {
378 let summary = if v.is_array() {
379 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
380 } else {
381 abbrev(&v)
382 };
383 println!(" OK: get_non_funding_ledger_updates(zero_addr) -> {}", summary);
384 tally.passed += 1;
385 }
386 Err(e) => { fail_rest!("get_non_funding_ledger_updates", e); tally.failed += 1; }
387 }
388
389 // NEW: get_vault_details (HLP vault)
390 tally.tested += 1;
391 match conn.get_vault_details("0xa15099a30bbf2e68942d6f4c43d70d04faeab0a0").await {
392 Ok(v) => {
393 let summary = if v.is_null() { "null (unknown vault)".to_string() } else { abbrev(&v) };
394 println!(" OK: get_vault_details(HLP) -> {}", summary);
395 tally.passed += 1;
396 }
397 Err(e) => { fail_rest!("get_vault_details", e); tally.failed += 1; }
398 }
399
400 tally
401}Sourcepub async fn get_non_funding_ledger_updates(
&self,
user: &str,
start_time: i64,
end_time: Option<i64>,
) -> ExchangeResult<Value>
pub async fn get_non_funding_ledger_updates( &self, user: &str, start_time: i64, end_time: Option<i64>, ) -> ExchangeResult<Value>
Get non-funding ledger entries for a user (deposits, withdrawals, internal transfers).
POSTs {"type":"userNonFundingLedgerUpdates","user":"<addr>","startTime":<ms>} to /info.
Returns an array of ledger entries ordered by time ascending.
No authentication required — only the wallet address.
Examples found in repository?
307async fn test_hyperliquid_rest() -> RestTally {
308 println!("\n── Hyperliquid REST ─────────────────────────────────────────");
309 let mut tally = RestTally { exchange: "Hyperliquid".into(), tested: 0, passed: 0, failed: 0 };
310
311 let conn = match HyperliquidConnector::public(false).await {
312 Ok(c) => c,
313 Err(e) => {
314 println!(" FAIL: connector init -> {}", e);
315 tally.failed += 1;
316 tally.tested += 1;
317 return tally;
318 }
319 };
320
321 // get_meta_and_asset_ctxs
322 tally.tested += 1;
323 match conn.get_meta_and_asset_ctxs().await {
324 Ok(v) => {
325 let summary = if v.is_array() {
326 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
327 } else {
328 abbrev(&v)
329 };
330 println!(" OK: get_meta_and_asset_ctxs -> {}", summary);
331 tally.passed += 1;
332 }
333 Err(e) => { fail_rest!("get_meta_and_asset_ctxs", e); tally.failed += 1; }
334 }
335
336 // get_predicted_fundings
337 tally.tested += 1;
338 match conn.get_predicted_fundings().await {
339 Ok(v) => {
340 let summary = if v.is_array() {
341 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
342 } else {
343 abbrev(&v)
344 };
345 println!(" OK: get_predicted_fundings -> {}", summary);
346 tally.passed += 1;
347 }
348 Err(e) => { fail_rest!("get_predicted_fundings", e); tally.failed += 1; }
349 }
350
351 // NEW: get_spot_meta_and_asset_ctxs
352 tally.tested += 1;
353 match conn.get_spot_meta_and_asset_ctxs().await {
354 Ok(v) => {
355 let summary = if v.is_array() {
356 format!("[{} elements]", v.as_array().map(|a| a.len()).unwrap_or(0))
357 } else {
358 abbrev(&v)
359 };
360 println!(" OK: get_spot_meta_and_asset_ctxs -> {}", summary);
361 tally.passed += 1;
362 }
363 Err(e) => { fail_rest!("get_spot_meta_and_asset_ctxs", e); tally.failed += 1; }
364 }
365
366 // NEW: get_non_funding_ledger_updates (zero address — expect empty array)
367 tally.tested += 1;
368 let now_ms = std::time::SystemTime::now()
369 .duration_since(std::time::UNIX_EPOCH)
370 .map(|d| d.as_millis() as i64)
371 .unwrap_or(0);
372 match conn.get_non_funding_ledger_updates(
373 "0x0000000000000000000000000000000000000000",
374 0,
375 Some(now_ms),
376 ).await {
377 Ok(v) => {
378 let summary = if v.is_array() {
379 format!("[{} entries]", v.as_array().map(|a| a.len()).unwrap_or(0))
380 } else {
381 abbrev(&v)
382 };
383 println!(" OK: get_non_funding_ledger_updates(zero_addr) -> {}", summary);
384 tally.passed += 1;
385 }
386 Err(e) => { fail_rest!("get_non_funding_ledger_updates", e); tally.failed += 1; }
387 }
388
389 // NEW: get_vault_details (HLP vault)
390 tally.tested += 1;
391 match conn.get_vault_details("0xa15099a30bbf2e68942d6f4c43d70d04faeab0a0").await {
392 Ok(v) => {
393 let summary = if v.is_null() { "null (unknown vault)".to_string() } else { abbrev(&v) };
394 println!(" OK: get_vault_details(HLP) -> {}", summary);
395 tally.passed += 1;
396 }
397 Err(e) => { fail_rest!("get_vault_details", e); tally.failed += 1; }
398 }
399
400 tally
401}Trait Implementations§
Source§impl Account for HyperliquidConnector
impl Account for HyperliquidConnector
Source§fn get_balance<'life0, 'async_trait>(
&'life0 self,
query: BalanceQuery,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Balance>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_balance<'life0, 'async_trait>(
&'life0 self,
query: BalanceQuery,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Balance>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Get account balances.
For Spot accounts: uses spotClearinghouseState → returns per-token balances.
For Perp accounts: uses clearinghouseState → returns USDC balance summary.
No signature required — only wallet address.
Source§fn get_account_info<'life0, 'async_trait>(
&'life0 self,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<AccountInfo>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_account_info<'life0, 'async_trait>(
&'life0 self,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<AccountInfo>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Get account info (permissions, margin summary, balances).
Uses clearinghouseState for perp account metadata.
Source§fn get_fees<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: Option<&'life1 str>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<FeeInfo>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_fees<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: Option<&'life1 str>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<FeeInfo>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Get fee schedule for the account.
Uses userFees endpoint to get the current tier.
Source§fn account_capabilities(&self, account_type: AccountType) -> AccountCapabilities
fn account_capabilities(&self, account_type: AccountType) -> AccountCapabilities
Source§impl AccountLedger for HyperliquidConnector
impl AccountLedger for HyperliquidConnector
Source§fn get_ledger<'life0, 'async_trait>(
&'life0 self,
filter: LedgerFilter,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<LedgerEntry>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_ledger<'life0, 'async_trait>(
&'life0 self,
filter: LedgerFilter,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<LedgerEntry>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§impl AccountTransfers for HyperliquidConnector
impl AccountTransfers for HyperliquidConnector
Source§fn transfer<'life0, 'async_trait>(
&'life0 self,
req: TransferRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<TransferResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn transfer<'life0, 'async_trait>(
&'life0 self,
req: TransferRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<TransferResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Transfer USDC between Spot and Perp wallets.
Uses the usdClassTransfer action on /exchange.
- Spot → Perp:
from_account = Spot, to_account = FuturesCross→toPerp: true - Perp → Spot:
from_account = FuturesCross, to_account = Spot→toPerp: false
Only USDC transfers between Spot and Perp are supported.
Other asset/account combinations return UnsupportedOperation.
Source§fn get_transfer_history<'life0, 'async_trait>(
&'life0 self,
_filter: TransferHistoryFilter,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<TransferResponse>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_transfer_history<'life0, 'async_trait>(
&'life0 self,
_filter: TransferHistoryFilter,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<TransferResponse>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Get transfer history between Spot and Perp.
Hyperliquid does not expose a transfer history endpoint — returns empty vec.
Source§impl AmendOrder for HyperliquidConnector
impl AmendOrder for HyperliquidConnector
Source§fn amend_order<'life0, 'async_trait>(
&'life0 self,
req: AmendRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Order>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn amend_order<'life0, 'async_trait>(
&'life0 self,
req: AmendRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Order>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Modify a live order using the native modify action on /exchange.
Hyperliquid’s modify action requires the full order spec (asset, side, price, size, reduce_only, order type) alongside the order ID to amend.
Source§impl BatchOrders for HyperliquidConnector
impl BatchOrders for HyperliquidConnector
Source§fn place_orders_batch<'life0, 'async_trait>(
&'life0 self,
orders: Vec<OrderRequest>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<OrderResult>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn place_orders_batch<'life0, 'async_trait>(
&'life0 self,
orders: Vec<OrderRequest>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<OrderResult>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Place multiple orders in a single native batch request.
Hyperliquid’s order action natively accepts an array of orders — this IS the batch
endpoint. Uses grouping="na" (no bracket/TP-SL grouping).
Source§fn cancel_orders_batch<'life0, 'life1, 'async_trait>(
&'life0 self,
order_ids: Vec<String>,
symbol: Option<&'life1 str>,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<OrderResult>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn cancel_orders_batch<'life0, 'life1, 'async_trait>(
&'life0 self,
order_ids: Vec<String>,
symbol: Option<&'life1 str>,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<OrderResult>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Cancel multiple orders in a single native batch request.
Hyperliquid’s cancel action natively accepts an array of {a, o} pairs.
symbol hint is used to look up the asset index; all order IDs are assumed
to belong to the same asset if a symbol is provided.
Source§fn max_batch_place_size(&self) -> usize
fn max_batch_place_size(&self) -> usize
Source§fn max_batch_cancel_size(&self) -> usize
fn max_batch_cancel_size(&self) -> usize
Source§impl CancelAll for HyperliquidConnector
impl CancelAll for HyperliquidConnector
Source§fn cancel_all_orders<'life0, 'async_trait>(
&'life0 self,
scope: CancelScope,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<CancelAllResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn cancel_all_orders<'life0, 'async_trait>(
&'life0 self,
scope: CancelScope,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<CancelAllResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Cancel all open orders, optionally scoped to a symbol.
Hyperliquid has no native cancel-all endpoint. Implementation:
- Fetch all open orders via
POST /info {"type": "openOrders", "user": "0x..."} - Filter by symbol if scope is
BySymbolorAll { symbol: Some(...) } - Send a single batch cancel via
POST /exchangewith all (asset, oid) pairs
This is a single batch cancel request — NOT a loop over cancel_order.
Source§impl CustodialFunds for HyperliquidConnector
impl CustodialFunds for HyperliquidConnector
Source§fn get_deposit_address<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
asset: &'life1 str,
network: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<DepositAddress>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_deposit_address<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
asset: &'life1 str,
network: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<DepositAddress>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn withdraw<'life0, 'async_trait>(
&'life0 self,
req: WithdrawRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<WithdrawResponse>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
fn withdraw<'life0, 'async_trait>(
&'life0 self,
req: WithdrawRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<WithdrawResponse>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
Source§fn get_funds_history<'life0, 'async_trait>(
&'life0 self,
filter: FundsHistoryFilter,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<FundsRecord>>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
fn get_funds_history<'life0, 'async_trait>(
&'life0 self,
filter: FundsHistoryFilter,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<FundsRecord>>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
Source§impl ExchangeIdentity for HyperliquidConnector
impl ExchangeIdentity for HyperliquidConnector
Source§fn exchange_id(&self) -> ExchangeId
fn exchange_id(&self) -> ExchangeId
Source§fn metrics(&self) -> ConnectorStats
fn metrics(&self) -> ConnectorStats
Source§fn is_testnet(&self) -> bool
fn is_testnet(&self) -> bool
Source§fn supported_account_types(&self) -> Vec<AccountType>
fn supported_account_types(&self) -> Vec<AccountType>
Source§fn exchange_type(&self) -> ExchangeType
fn exchange_type(&self) -> ExchangeType
Source§fn rate_limit_capabilities(&self) -> RateLimitCapabilities
fn rate_limit_capabilities(&self) -> RateLimitCapabilities
Source§fn orderbook_capabilities(
&self,
_account_type: AccountType,
) -> OrderbookCapabilities
fn orderbook_capabilities( &self, _account_type: AccountType, ) -> OrderbookCapabilities
Source§fn exchange_name(&self) -> &'static str
fn exchange_name(&self) -> &'static str
Source§impl FundingHistory for HyperliquidConnector
impl FundingHistory for HyperliquidConnector
Source§fn get_funding_payments<'life0, 'async_trait>(
&'life0 self,
filter: FundingFilter,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<FundingPayment>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_funding_payments<'life0, 'async_trait>(
&'life0 self,
filter: FundingFilter,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<FundingPayment>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Get historical funding payments from POST /info with type: userFunding.
The wallet address is taken from credentials (api_key). No cryptographic
signature is required for this endpoint — only the address in the request body.
Source§impl HasCapabilities for HyperliquidConnector
impl HasCapabilities for HyperliquidConnector
Source§fn capabilities(&self) -> ConnectorCapabilities
fn capabilities(&self) -> ConnectorCapabilities
Source§fn validation_status(&self) -> Option<&'static ValidationStamp>
fn validation_status(&self) -> Option<&'static ValidationStamp>
e2e_smoke harness run. Read moreSource§impl MarketData for HyperliquidConnector
impl MarketData for HyperliquidConnector
Source§fn get_price<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Price>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_price<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Price>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_orderbook<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
_depth: Option<u16>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<OrderBook>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_orderbook<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
_depth: Option<u16>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<OrderBook>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_klines<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
interval: &'life2 str,
limit: Option<u16>,
account_type: AccountType,
end_time: Option<i64>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Kline>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_klines<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
interval: &'life2 str,
limit: Option<u16>,
account_type: AccountType,
end_time: Option<i64>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Kline>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn get_ticker<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Ticker>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_ticker<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Ticker>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn ping<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ExchangeResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn ping<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ExchangeResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_exchange_info<'life0, 'async_trait>(
&'life0 self,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<SymbolInfo>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_exchange_info<'life0, 'async_trait>(
&'life0 self,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<SymbolInfo>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn market_data_capabilities(
&self,
_account_type: AccountType,
) -> MarketDataCapabilities
fn market_data_capabilities( &self, _account_type: AccountType, ) -> MarketDataCapabilities
Source§impl MarketDataPublic for HyperliquidConnector
impl MarketDataPublic for HyperliquidConnector
Source§fn get_recent_trades<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
_limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<PublicTrade>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_recent_trades<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
_limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<PublicTrade>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_liquidation_history<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: Option<SymbolInput<'life1>>,
start_time: Option<i64>,
end_time: Option<i64>,
limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Liquidation>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_liquidation_history<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: Option<SymbolInput<'life1>>,
start_time: Option<i64>,
end_time: Option<i64>,
limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Liquidation>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_open_interest_history<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
period: &'life2 str,
start_time: Option<i64>,
end_time: Option<i64>,
limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<OpenInterest>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_open_interest_history<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
period: &'life2 str,
start_time: Option<i64>,
end_time: Option<i64>,
limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<OpenInterest>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn get_long_short_ratio_history<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
period: &'life2 str,
start_time: Option<i64>,
end_time: Option<i64>,
limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<LongShortRatio>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_long_short_ratio_history<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
period: &'life2 str,
start_time: Option<i64>,
end_time: Option<i64>,
limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<LongShortRatio>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn get_mark_price_klines<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
interval: &'life2 str,
limit: Option<u32>,
account_type: AccountType,
end_time: Option<i64>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Kline>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_mark_price_klines<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
interval: &'life2 str,
limit: Option<u32>,
account_type: AccountType,
end_time: Option<i64>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Kline>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn get_index_price_klines<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
interval: &'life2 str,
limit: Option<u32>,
account_type: AccountType,
end_time: Option<i64>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Kline>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_index_price_klines<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
interval: &'life2 str,
limit: Option<u32>,
account_type: AccountType,
end_time: Option<i64>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Kline>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn get_funding_rate_history<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
start_time: Option<i64>,
end_time: Option<i64>,
limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<FundingRate>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_funding_rate_history<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: SymbolInput<'life1>,
start_time: Option<i64>,
end_time: Option<i64>,
limit: Option<u32>,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<FundingRate>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§impl Positions for HyperliquidConnector
impl Positions for HyperliquidConnector
Source§fn get_positions<'life0, 'async_trait>(
&'life0 self,
query: PositionQuery,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Position>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_positions<'life0, 'async_trait>(
&'life0 self,
query: PositionQuery,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Position>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Get open perpetual positions.
Uses clearinghouseState — no signature required, only wallet address.
Source§fn get_funding_rate<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: &'life1 str,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<FundingRate>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_funding_rate<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: &'life1 str,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<FundingRate>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Get the current funding rate for a perpetual symbol.
Uses metaAndAssetCtxs to find the symbol’s funding rate.
Source§fn get_mark_price<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: &'life1 str,
) -> Pin<Box<dyn Future<Output = ExchangeResult<MarkPrice>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_mark_price<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: &'life1 str,
) -> Pin<Box<dyn Future<Output = ExchangeResult<MarkPrice>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Get the current mark price for a perpetual symbol.
Uses metaAndAssetCtxs — the same endpoint as get_funding_rate — and
extracts markPx and oraclePx from the asset context at the symbol index.
metaAndAssetCtxs response: [{universe:[{name,szDecimals,...}]}, [{markPx,oraclePx,funding,...},...]]
Source§fn modify_position<'life0, 'async_trait>(
&'life0 self,
req: PositionModification,
) -> Pin<Box<dyn Future<Output = ExchangeResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn modify_position<'life0, 'async_trait>(
&'life0 self,
req: PositionModification,
) -> Pin<Box<dyn Future<Output = ExchangeResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Modify a position — leverage, margin mode, add/remove margin, or close.
Supported modifications:
- SetLeverage: POST /exchange updateLeverage
- SetMarginMode: POST /exchange updateLeverage with isCross flag
- AddMargin: POST /exchange updateIsolatedMargin (positive ntli)
- RemoveMargin: POST /exchange updateIsolatedMargin (negative ntli)
- ClosePosition: place a reduce-only market order for the full position size
Unsupported: SetTpSl (Hyperliquid TP/SL is set at order placement, not separately)
Source§fn get_open_interest<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: &'life1 str,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<OpenInterest>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_open_interest<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: &'life1 str,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<OpenInterest>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_closed_pnl<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: Option<&'life1 str>,
start_time: Option<u64>,
end_time: Option<u64>,
limit: Option<u32>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<ClosedPnlRecord>>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_closed_pnl<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: Option<&'life1 str>,
start_time: Option<u64>,
end_time: Option<u64>,
limit: Option<u32>,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<ClosedPnlRecord>>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_long_short_ratio<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: &'life1 str,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<LongShortRatio>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_long_short_ratio<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: &'life1 str,
account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<LongShortRatio>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§impl SubAccounts for HyperliquidConnector
impl SubAccounts for HyperliquidConnector
Source§fn sub_account_operation<'life0, 'async_trait>(
&'life0 self,
op: SubAccountOperation,
) -> Pin<Box<dyn Future<Output = ExchangeResult<SubAccountResult>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
fn sub_account_operation<'life0, 'async_trait>(
&'life0 self,
op: SubAccountOperation,
) -> Pin<Box<dyn Future<Output = ExchangeResult<SubAccountResult>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
Source§impl Trading for HyperliquidConnector
impl Trading for HyperliquidConnector
Source§fn place_order<'life0, 'async_trait>(
&'life0 self,
req: OrderRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<PlaceOrderResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn place_order<'life0, 'async_trait>(
&'life0 self,
req: OrderRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<PlaceOrderResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Place an order on Hyperliquid.
Supported order types:
- Market (implemented as aggressive IOC limit)
- Limit (GTC)
- PostOnly (ALO — Add-Liquidity-Only)
- IOC
- FOK
- StopMarket (trigger order, tpsl=“sl”, isMarket=true)
- StopLimit (trigger order, tpsl=“sl”, isMarket=false)
- ReduceOnly (limit or market with reduce_only=true)
Unsupported: TrailingStop, OCO, Bracket, Iceberg, TWAP, GTD
Source§fn cancel_order<'life0, 'async_trait>(
&'life0 self,
req: CancelRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Order>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn cancel_order<'life0, 'async_trait>(
&'life0 self,
req: CancelRequest,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Order>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Cancel an order (single, batch, all, or by symbol).
Returns the first cancelled order’s state (or a placeholder for batch/all).
Source§fn get_order<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_symbol: &'life1 str,
order_id: &'life2 str,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Order>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_order<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_symbol: &'life1 str,
order_id: &'life2 str,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Order>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Get the current state of a single order by ID.
Requires authentication (wallet address).
Source§fn get_open_orders<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: Option<&'life1 str>,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Order>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_open_orders<'life0, 'life1, 'async_trait>(
&'life0 self,
symbol: Option<&'life1 str>,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Order>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Get all open orders, optionally filtered by symbol.
Requires authentication (wallet address).
Source§fn get_order_history<'life0, 'async_trait>(
&'life0 self,
filter: OrderHistoryFilter,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Order>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_order_history<'life0, 'async_trait>(
&'life0 self,
filter: OrderHistoryFilter,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<Order>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Get order history (fills / closed orders).
Uses userFills for recent fills or historicalOrders for order history.
Requires authentication (wallet address).
Source§fn get_user_trades<'life0, 'async_trait>(
&'life0 self,
filter: UserTradeFilter,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<UserTrade>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_user_trades<'life0, 'async_trait>(
&'life0 self,
filter: UserTradeFilter,
_account_type: AccountType,
) -> Pin<Box<dyn Future<Output = ExchangeResult<Vec<UserTrade>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Fetch trade fills for the authenticated wallet address.
Uses userFillsByTime when a time range is specified, otherwise
falls back to userFills (returns up to the last 2000 fills).
No authentication signature needed — only the wallet address.