ostium-rust-sdk 0.1.0

Rust SDK for interacting with the Ostium trading platform on Arbitrum
Documentation
//! Price fetching functionality tests
//!
//! This test module validates price fetching capabilities for all available markets.

use ostium_rust_sdk::{Network, OstiumClient};

/// Helper function to create a test client
async fn create_test_client() -> Result<OstiumClient, Box<dyn std::error::Error>> {
    Ok(OstiumClient::new(Network::Testnet).await?)
}

#[tokio::test]
async fn test_price_fetching_functionality() {
    // Initialize logging
    tracing_subscriber::fmt::init();

    println!("🔍 Ostium Price Fetching Test - All Markets");
    println!("============================================\n");

    // Create client
    let client = create_test_client().await.unwrap();

    // First, get all available trading pairs
    println!("📈 Fetching all available trading pairs...");
    let pairs = client.get_pairs().await.unwrap();

    if pairs.is_empty() {
        println!("❌ No trading pairs found!");
        return;
    }

    println!("✅ Found {} total trading pairs:", pairs.len());

    // Separate active and inactive pairs
    let active_pairs: Vec<_> = pairs.iter().filter(|p| p.is_active).collect();
    let inactive_pairs: Vec<_> = pairs.iter().filter(|p| !p.is_active).collect();

    println!("  • Active pairs: {}", active_pairs.len());
    println!("  • Inactive pairs: {}", inactive_pairs.len());
    println!();

    // Display all pairs with their status
    println!("📋 All Available Markets:");
    println!("========================");
    for (i, pair) in pairs.iter().enumerate() {
        let status = if pair.is_active {
            "🟢 Active"
        } else {
            "🔴 Inactive"
        };
        println!(
            "  {}. {} - {} (Base: {}, Quote: {})",
            i + 1,
            pair.symbol,
            status,
            pair.base_asset,
            pair.quote_asset
        );
    }
    println!();

    // Test prices for all markets
    println!("💰 Testing prices for all markets:");
    println!("==================================");

    let mut successful_prices = 0;
    let mut failed_prices = 0;

    for pair in &pairs {
        println!(
            "\n📊 Testing price for: {} ({})",
            pair.symbol,
            if pair.is_active { "Active" } else { "Inactive" }
        );

        match client.get_price(&pair.symbol).await {
            Ok(price) => {
                successful_prices += 1;
                println!("  ✅ Success:");
                println!("    Mark Price: ${}", price.mark_price);
                println!("    Index Price: ${}", price.index_price);
                println!("    24h High: ${}", price.high_24h);
                println!("    24h Low: ${}", price.low_24h);
                println!("    Volume: ${}", price.volume_24h);
                println!("    Timestamp: {}", price.timestamp);

                // Calculate 24h change percentage
                let mid_price = (price.high_24h + price.low_24h) / rust_decimal::Decimal::from(2);
                if mid_price > rust_decimal::Decimal::ZERO {
                    let change_pct = ((price.mark_price - mid_price) / mid_price)
                        * rust_decimal::Decimal::from(100);
                    println!("    24h Change: {:.2}%", change_pct);
                }
            }
            Err(e) => {
                failed_prices += 1;
                println!("  ❌ Error: {}", e);

                // Try alternative symbol formats if the standard format fails
                if pair.symbol.contains('/') {
                    let alt_symbol = pair.symbol.replace('/', "");
                    println!("  🔄 Trying alternative format: {}", alt_symbol);

                    match client.get_price(&alt_symbol).await {
                        Ok(price) => {
                            successful_prices += 1;
                            failed_prices -= 1; // Adjust count since we succeeded
                            println!("  ✅ Success with alternative format:");
                            println!("    Mark Price: ${}", price.mark_price);
                            println!("    Index Price: ${}", price.index_price);
                        }
                        Err(e2) => {
                            println!("  ❌ Alternative format also failed: {}", e2);
                        }
                    }
                }
            }
        }
    }

    // Test trading hours for a few representative pairs
    println!("\n\n🕐 Testing trading hours for representative pairs:");
    println!("=================================================");

    let test_pairs = if !active_pairs.is_empty() {
        // Test active pairs first
        active_pairs
            .iter()
            .take(3)
            .map(|p| p.symbol.as_str())
            .collect::<Vec<_>>()
    } else {
        // Fallback to any available pairs
        pairs
            .iter()
            .take(3)
            .map(|p| p.symbol.as_str())
            .collect::<Vec<_>>()
    };

    for symbol in test_pairs {
        println!("\n🕐 Testing trading hours for: {}", symbol);
        match client.get_trading_hours(symbol).await {
            Ok(hours) => {
                let status = if hours.is_open {
                    "🟢 OPEN"
                } else {
                    "🔴 CLOSED"
                };
                println!("  ✅ Market Status: {}", status);

                if let Some(next_open) = hours.next_open {
                    println!("  📅 Next Open: {}", next_open);
                }
                if let Some(next_close) = hours.next_close {
                    println!("  📅 Next Close: {}", next_close);
                }
            }
            Err(e) => {
                println!("  ❌ Error: {}", e);
            }
        }
    }

    // Summary
    println!("\n\n📊 Summary:");
    println!("===========");
    println!("Total markets found: {}", pairs.len());
    println!("Active markets: {}", active_pairs.len());
    println!("Inactive markets: {}", inactive_pairs.len());
    println!("Successful price fetches: {}", successful_prices);
    println!("Failed price fetches: {}", failed_prices);

    let success_rate = if !pairs.is_empty() {
        (successful_prices as f64 / pairs.len() as f64) * 100.0
    } else {
        0.0
    };
    println!("Success rate: {:.1}%", success_rate);

    if !active_pairs.is_empty() {
        println!("\n🎯 Recommended markets for trading:");
        for pair in active_pairs.iter().take(5) {
            println!("{}", pair.symbol);
        }
    }

    if !inactive_pairs.is_empty() {
        println!("\n⚠️  Inactive markets (not recommended for trading):");
        for pair in inactive_pairs.iter().take(5) {
            println!("{}", pair.symbol);
        }
        if inactive_pairs.len() > 5 {
            println!(
                "  ... and {} more inactive markets",
                inactive_pairs.len() - 5
            );
        }
    }

    println!("\n✨ Price test completed for all markets!");

    // Assert that we got reasonable results
    assert!(
        pairs.len() > 0,
        "Should have found at least one trading pair"
    );
    assert!(
        successful_prices > 0,
        "Should have successfully fetched at least one price"
    );
}