#![allow(clippy::disallowed_methods)]
use ccxt_core::{ExchangeConfig, types::Market};
use ccxt_exchanges::binance::Binance;
use serde_json::json;
use std::collections::HashMap;
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
#[ignore]
async fn test_watch_ticker() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
match exchange.watch_ticker("BTC/USDT", None).await {
Ok(ticker) => {
println!("✓ watch_ticker succeeded");
println!(" Symbol: {}", ticker.symbol);
println!(" Last: {:?}", ticker.last);
println!(" Bid: {:?}", ticker.bid);
println!(" Ask: {:?}", ticker.ask);
println!(" Volume: {:?}", ticker.base_volume);
assert_eq!(ticker.symbol, "BTC/USDT");
assert!(ticker.last.is_some());
}
Err(e) => {
println!("✗ watch_ticker failed: {}", e);
panic!("Test failed: {}", e);
}
}
}
#[tokio::test]
#[ignore]
async fn test_watch_mini_ticker() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
let mut params = HashMap::new();
params.insert("name".to_string(), json!("miniTicker"));
match exchange.watch_ticker("ETH/USDT", Some(params)).await {
Ok(ticker) => {
println!("✓ watch_ticker with miniTicker succeeded");
println!(" Symbol: {}", ticker.symbol);
println!(" Last: {:?}", ticker.last);
assert_eq!(ticker.symbol, "ETH/USDT");
}
Err(e) => {
println!("✗ watch_ticker with miniTicker failed: {}", e);
panic!("Test failed: {}", e);
}
}
}
#[tokio::test]
#[ignore]
async fn test_watch_tickers_multiple() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
let symbols = vec![
"BTC/USDT".to_string(),
"ETH/USDT".to_string(),
"BNB/USDT".to_string(),
];
match exchange.watch_tickers(Some(symbols.clone()), None).await {
Ok(tickers) => {
println!(
"✓ watch_tickers succeeded, received {} tickers",
tickers.len()
);
for symbol in &symbols {
if let Some(ticker) = tickers.get(symbol) {
println!(" {} - Last: {:?}", ticker.symbol, ticker.last);
}
}
assert!(tickers.len() > 0);
}
Err(e) => {
println!("✗ watch_tickers failed: {}", e);
panic!("Test failed: {}", e);
}
}
}
#[tokio::test]
#[ignore]
async fn test_watch_all_tickers() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
match exchange.watch_tickers(None, None).await {
Ok(tickers) => {
println!(
"✓ watch_tickers (all) succeeded, received {} tickers",
tickers.len()
);
for (i, (symbol, ticker)) in tickers.iter().enumerate() {
if i >= 5 {
break;
}
println!(" {} - Last: {:?}", symbol, ticker.last);
}
assert!(!tickers.is_empty());
}
Err(e) => {
println!("✗ watch_tickers (all) failed: {}", e);
panic!("Test failed: {}", e);
}
}
}
#[tokio::test]
#[ignore]
async fn test_watch_mark_price() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
match exchange.watch_mark_price("BTC/USDT:USDT", None).await {
Ok(mark_price) => {
println!("✓ watch_mark_price succeeded");
println!(" Symbol: {}", mark_price.symbol);
println!(" Mark Price: {:?}", mark_price.mark_price);
println!(" Index Price: {:?}", mark_price.index_price);
assert!(mark_price.symbol.contains("BTC") || mark_price.symbol.contains("btc"));
}
Err(e) => {
println!("✗ watch_mark_price failed: {}", e);
panic!("Test failed: {}", e);
}
}
}
#[tokio::test]
#[ignore]
async fn test_watch_mark_price_3s() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
let mut params = HashMap::new();
params.insert("use1sFreq".to_string(), json!(false));
match exchange
.watch_mark_price("ETH/USDT:USDT", Some(params))
.await
{
Ok(mark_price) => {
println!("✓ watch_mark_price (3s update) succeeded");
println!(" Symbol: {}", mark_price.symbol);
println!(" Mark Price: {:?}", mark_price.mark_price);
assert!(mark_price.symbol.contains("ETH") || mark_price.symbol.contains("eth"));
}
Err(e) => {
println!("✗ watch_mark_price (3s update) failed: {}", e);
panic!("Test failed: {}", e);
}
}
}
#[tokio::test]
#[ignore]
async fn test_watch_mark_prices() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
let symbols = vec!["BTC/USDT:USDT".to_string(), "ETH/USDT:USDT".to_string()];
match exchange
.watch_mark_prices(Some(symbols.clone()), None)
.await
{
Ok(mark_prices) => {
println!(
"✓ watch_mark_prices succeeded, received {} mark prices",
mark_prices.len()
);
for (symbol, mark_price) in &mark_prices {
println!(" {} - Mark: {:?}", symbol, mark_price.mark_price);
}
assert!(mark_prices.len() > 0);
}
Err(e) => {
println!("✗ watch_mark_prices failed: {}", e);
panic!("Test failed: {}", e);
}
}
}
#[tokio::test]
async fn test_watch_tickers_reject_book_ticker() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
let market = Market {
id: "BTCUSDT".to_string(),
symbol: "BTC/USDT".to_string(),
..Market::default()
};
exchange
.base()
.set_markets(vec![market], None)
.await
.unwrap();
let mut params = HashMap::new();
params.insert("name".to_string(), json!("bookTicker"));
match exchange
.watch_tickers(Some(vec!["BTC/USDT".to_string()]), Some(params))
.await
{
Ok(_) => {
panic!("Should reject bookTicker channel");
}
Err(e) => {
println!("✓ Correctly rejected bookTicker: {}", e);
assert!(e.to_string().contains("watch_bids_asks"));
}
}
}
#[tokio::test]
async fn test_watch_mark_price_reject_spot() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
let market = Market::new_spot(
"BTCUSDT".to_string(),
"BTC/USDT".to_string(),
"BTC".to_string(),
"USDT".to_string(),
);
exchange
.base()
.set_markets(vec![market], None)
.await
.unwrap();
match exchange.watch_mark_price("BTC/USDT", None).await {
Ok(_) => {
panic!("Should reject spot market");
}
Err(e) => {
println!("✓ Correctly rejected spot market: {}", e);
assert!(e.to_string().contains("does not support"));
}
}
}
#[tokio::test]
#[ignore]
async fn test_ticker_cache() {
let exchange = Binance::new(ExchangeConfig::default()).unwrap();
let _ws = exchange.create_ws();
println!("✓ Ticker cache functionality pending (requires public API)");
}
#[test]
fn test_stream_format() {
assert_eq!(format!("{}@{}", "btcusdt", "ticker"), "btcusdt@ticker");
assert_eq!(
format!("{}@{}", "ethusdt", "miniTicker"),
"ethusdt@miniTicker"
);
assert_eq!(
format!("{}@{}", "btcusdt", "markPrice@1s"),
"btcusdt@markPrice@1s"
);
assert_eq!(
format!("{}@{}", "btcusdt", "markPrice"),
"btcusdt@markPrice"
);
assert_eq!(format!("!{}@arr", "ticker"), "!ticker@arr");
assert_eq!(format!("!{}@arr", "miniTicker"), "!miniTicker@arr");
println!("✓ Stream format validation");
}
}