#![allow(clippy::disallowed_methods)]
use ccxt_core::Exchange;
use ccxt_core::ExchangeConfig;
use ccxt_core::error::Result;
use ccxt_exchanges::binance::Binance;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
fn create_test_binance() -> Binance {
let config = ExchangeConfig {
id: "binance".to_string(),
name: "Binance".to_string(),
api_key: Some(ccxt_core::SecretString::new("test_api_key")),
secret: Some(ccxt_core::SecretString::new("test_api_secret")),
..Default::default()
};
Binance::new(config).expect("Failed to create Binance instance")
}
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_fetch_market_data() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
exchange.load_markets(false).await.unwrap();
let market = exchange.market("BTC/USDT").await.unwrap();
assert_eq!(market.symbol, "BTC/USDT");
assert!(market.active);
let markets = exchange.markets().await;
assert!(markets.contains_key("BTC/USDT"));
assert!(markets.contains_key("ETH/USDT"));
println!("Successfully fetched market data.");
}
#[cfg(test)]
mod tests {
use super::*;
use ccxt_core::types::{BidAsk, LastPrice, MarkPrice};
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_fetch_time() {
let binance = create_test_binance();
let server_time = binance.fetch_time().await.unwrap();
assert!(server_time.server_time > 0);
assert!(!server_time.datetime.is_empty());
println!(
"Server time: {} ({})",
server_time.server_time, server_time.datetime
);
}
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_fetch_bids_asks_single_symbol() {
let binance = create_test_binance();
binance.load_markets(false).await.unwrap();
let bid_asks = binance.fetch_bids_asks(Some("BTC/USDT")).await.unwrap();
assert!(!bid_asks.is_empty());
let bid_ask = &bid_asks[0];
assert!(bid_ask.bid_price > Decimal::ZERO);
assert!(bid_ask.ask_price > Decimal::ZERO);
assert!(bid_ask.ask_price >= bid_ask.bid_price);
println!(
"BTC/USDT bid: {}, ask: {}",
bid_ask.bid_price, bid_ask.ask_price
);
}
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_fetch_bids_asks_all_symbols() {
let binance = create_test_binance();
binance.load_markets(false).await.unwrap();
let bid_asks = binance.fetch_bids_asks(None).await.unwrap();
assert!(!bid_asks.is_empty());
println!("Total symbols with bid/ask: {}", bid_asks.len());
}
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_fetch_last_prices_single_symbol() {
let binance = create_test_binance();
binance.load_markets(false).await.unwrap();
let prices = binance.fetch_last_prices(Some("BTC/USDT")).await.unwrap();
assert!(!prices.is_empty());
let price = &prices[0];
assert!(price.price > Decimal::ZERO);
println!("BTC/USDT last price: {}", price.price);
}
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_fetch_last_prices_all_symbols() {
let binance = create_test_binance();
binance.load_markets(false).await.unwrap();
let prices = binance.fetch_last_prices(None).await.unwrap();
assert!(!prices.is_empty());
println!("Total symbols with prices: {}", prices.len());
}
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_fetch_mark_price_single_symbol() {
let binance = create_test_binance();
binance.load_markets(false).await.unwrap();
let mark_prices = binance
.fetch_mark_price(Some("BTC/USDT:USDT"))
.await
.unwrap();
assert!(!mark_prices.is_empty());
let mark_price = &mark_prices[0];
assert!(mark_price.mark_price > Decimal::ZERO);
println!("BTC/USDT:USDT mark price: {}", mark_price.mark_price);
if let Some(funding_rate) = mark_price.last_funding_rate {
println!("Funding rate: {}", funding_rate);
}
}
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_fetch_mark_price_all_symbols() {
let binance = create_test_binance();
binance.load_markets(false).await.unwrap();
let mark_prices = binance.fetch_mark_price(None).await.unwrap();
assert!(!mark_prices.is_empty());
println!(
"Total futures symbols with mark prices: {}",
mark_prices.len()
);
}
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_bid_ask_spread_analysis() {
let binance = create_test_binance();
binance.load_markets(false).await.unwrap();
let bid_asks = binance.fetch_bids_asks(Some("BTC/USDT")).await.unwrap();
assert!(!bid_asks.is_empty());
let bid_ask = &bid_asks[0];
let spread = bid_ask.spread();
let mid_price = bid_ask.mid_price();
let spread_percent = bid_ask.spread_percent();
assert!(spread >= Decimal::ZERO);
assert!(mid_price > Decimal::ZERO);
assert!(spread_percent >= Decimal::ZERO);
println!(
"Spread: {}, Mid price: {}, Spread %: {}",
spread, mid_price, spread_percent
);
}
#[tokio::test]
async fn test_market_data_types() -> Result<()> {
let bid_ask = BidAsk {
symbol: "BTC/USDT".to_string(),
bid_price: dec!(50000),
ask_price: dec!(50100),
bid_quantity: dec!(10),
ask_quantity: dec!(15),
timestamp: 1234567890000,
};
assert_eq!(bid_ask.symbol, "BTC/USDT");
assert_eq!(bid_ask.spread(), dec!(100));
assert_eq!(bid_ask.mid_price(), dec!(50050));
assert!(bid_ask.spread_percent() > Decimal::ZERO);
let last_price = LastPrice {
symbol: "BTC/USDT".to_string(),
price: dec!(50000),
timestamp: 1234567890000,
datetime: "2023-01-01T00:00:00.000Z".to_string(),
};
assert_eq!(last_price.symbol, "BTC/USDT");
assert_eq!(last_price.price, dec!(50000));
assert!(last_price.timestamp > 0);
let mark_price = MarkPrice {
symbol: "BTC/USDT:USDT".to_string(),
mark_price: dec!(50050),
index_price: Some(dec!(50000)),
estimated_settle_price: None,
last_funding_rate: Some(dec!(0.0001)),
interest_rate: Some(dec!(0.0003)),
next_funding_time: Some(1234567890000),
timestamp: 1234567890000,
};
assert_eq!(mark_price.symbol, "BTC/USDT:USDT");
assert_eq!(mark_price.mark_price, dec!(50050));
assert!(mark_price.last_funding_rate.is_some());
println!("✓ Market data types test passed");
Ok(())
}
}
#[cfg(test)]
mod integration_tests {
use super::*;
#[tokio::test]
#[ignore = "Requires network access to Binance API"]
async fn test_complete_market_data_workflow() {
let binance = create_test_binance();
binance.load_markets(false).await.unwrap();
let server_time = binance.fetch_time().await.unwrap();
assert!(server_time.server_time > 0);
println!("1. Server time: {}", server_time.datetime);
let bid_asks = binance.fetch_bids_asks(Some("BTC/USDT")).await.unwrap();
assert!(!bid_asks.is_empty());
println!(
"2. BTC/USDT bid/ask: {} / {}",
bid_asks[0].bid_price, bid_asks[0].ask_price
);
let prices = binance.fetch_last_prices(Some("BTC/USDT")).await.unwrap();
assert!(!prices.is_empty());
println!("3. BTC/USDT last price: {}", prices[0].price);
let mark_prices = binance
.fetch_mark_price(Some("BTC/USDT:USDT"))
.await
.unwrap();
assert!(!mark_prices.is_empty());
println!("4. BTC/USDT:USDT mark price: {}", mark_prices[0].mark_price);
println!("✓ Complete market data workflow test passed");
}
}