asterdex-sdk 0.1.2

AsterDex Futures SDK v3 — Rust async client for REST and WebSocket APIs
Documentation
// US-004: Integration test — requires testnet credentials in env
// US-005: Integration test stubs — requires testnet credentials in env
// US-016: Raw passthrough and M1 full-flow integration tests
// Run with: cargo test --test integration -- --ignored

#[tokio::test]
#[ignore]
async fn test_place_limit_order_integration() {
    let client = asterdex_sdk::FuturesClient::from_env().unwrap();
    let params = asterdex_sdk::PlaceOrderParams {
        symbol: "BTCUSDT".to_string(),
        side: "BUY".to_string(),
        order_type: "LIMIT".to_string(),
        quantity: "0.001".to_string(),
        price: Some("20000.0".to_string()),
        time_in_force: Some("GTC".to_string()),
        ..Default::default()
    };
    let result = client.place_order(params).await;
    assert!(result.is_ok(), "place_order failed: {:?}", result);
    let resp = result.unwrap();
    assert_ne!(resp.data.order_id, 0);
    assert_eq!(resp.data.symbol, "BTCUSDT");
}

#[tokio::test]
#[ignore]
async fn test_cancel_order_integration() {
    let client = asterdex_sdk::FuturesClient::from_env().unwrap();
    let params = asterdex_sdk::CancelOrderParams {
        symbol: "BTCUSDT".to_string(),
        order_id: Some(999_999_999),
        ..Default::default()
    };
    // Note: will return ApiError(-2011) if no such order exists — that is expected
    let _result = client.cancel_order(params).await;
}

#[tokio::test]
#[ignore]
async fn test_get_open_orders_integration() {
    let client = asterdex_sdk::FuturesClient::from_env().unwrap();
    let result = client.get_open_orders(Some("BTCUSDT")).await;
    assert!(result.is_ok(), "get_open_orders failed: {:?}", result);
}

#[tokio::test]
#[ignore]
async fn test_get_positions_integration() {
    let client = asterdex_sdk::FuturesClient::from_env().unwrap();
    let result = client.get_position_risk(None).await;
    assert!(result.is_ok(), "get_position_risk failed: {:?}", result);
}

// US-016: M5 integration tests — verify raw passthrough
#[tokio::test]
#[ignore]
async fn test_raw_get_exchange_info() {
    let client = asterdex_sdk::FuturesClient::new_public("https://fapi.asterdex-testnet.com").unwrap();
    let resp = client.raw_get("/fapi/v3/exchangeInfo", &[]).await;
    assert!(resp.is_ok(), "raw_get failed: {:?}", resp);
    let resp = resp.unwrap();
    assert!(resp.data.is_object(), "Expected JSON object");
    assert!(resp.data.get("symbols").is_some(), "Expected 'symbols' field");
}

#[tokio::test]
#[ignore]
async fn test_raw_signed_get_balance() {
    let client = asterdex_sdk::FuturesClient::from_env().unwrap();
    let resp = client.raw_signed_get("/fapi/v3/balance", &[]).await;
    assert!(resp.is_ok(), "raw_signed_get failed: {:?}", resp);
    assert!(resp.unwrap().data.is_array());
}

// M1 group — full end-to-end test
#[tokio::test]
#[ignore]
async fn m1_full_flow_integration() {
    let client = asterdex_sdk::FuturesClient::from_env().unwrap();
    use asterdex_sdk::futures::models::trading::{PlaceOrderParams, CancelOrderParams};

    // 1. Server time
    let st = client.get_server_time().await.unwrap();
    let now_ms = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH).unwrap()
        .as_millis() as u64;
    assert!((st.data.server_time as i64 - now_ms as i64).abs() < 30_000);

    // 2. Place order
    let params = PlaceOrderParams {
        symbol: "BTCUSDT".to_string(),
        side: "BUY".to_string(),
        order_type: "LIMIT".to_string(),
        quantity: "0.001".to_string(),
        price: Some("20000.0".to_string()),
        time_in_force: Some("GTC".to_string()),
        ..Default::default()
    };
    let order = client.place_order(params).await.unwrap();
    let order_id = order.data.order_id;
    assert_ne!(order_id, 0);

    // 3. Cancel order
    let cancel = client.cancel_order(CancelOrderParams {
        symbol: "BTCUSDT".to_string(),
        order_id: Some(order_id),
        ..Default::default()
    }).await.unwrap();
    assert_eq!(cancel.data.status, "CANCELED");

    // 4. Open orders (should not contain the canceled order)
    let open = client.get_open_orders(Some("BTCUSDT")).await.unwrap();
    assert!(!open.data.iter().any(|o| o.order_id == order_id));

    // 5. Positions
    let positions = client.get_position_risk(Some("BTCUSDT")).await.unwrap();
    // May be empty — just assert no panic
    let _ = positions.data;
}