binance_spot_http_public/
http_public.rs1use nautilus_binance::{
28 common::enums::BinanceEnvironment,
29 spot::http::{BinanceSpotHttpClient, DepthParams, TradesParams},
30};
31use tracing_subscriber::EnvFilter;
32
33#[tokio::main]
34async fn main() -> anyhow::Result<()> {
35 tracing_subscriber::fmt()
37 .with_env_filter(
38 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
39 )
40 .init();
41
42 tracing::info!("Starting Binance Spot SBE HTTP client test");
43 tracing::info!(
44 "Using SBE schema version: {}:{}",
45 BinanceSpotHttpClient::schema_id(),
46 BinanceSpotHttpClient::schema_version()
47 );
48
49 let client = BinanceSpotHttpClient::new(
51 BinanceEnvironment::Mainnet,
52 None, None, None, None, Some(30), None, )?;
59
60 tracing::info!("=== Test 1: Ping ===");
62 match client.ping().await {
63 Ok(()) => tracing::info!("Ping successful"),
64 Err(e) => tracing::error!("Ping failed: {e}"),
65 }
66
67 tracing::info!("=== Test 2: Server Time ===");
70 match client.server_time().await {
71 Ok(timestamp_us) => {
72 let timestamp_ms = timestamp_us / 1000;
73 let datetime = chrono::DateTime::from_timestamp_millis(timestamp_ms).map_or_else(
74 || "invalid timestamp".to_string(),
75 |dt| dt.format("%Y-%m-%d %H:%M:%S%.3f UTC").to_string(),
76 );
77 tracing::info!("Server time: {timestamp_us} µs ({datetime})");
78 }
79 Err(e) => tracing::error!("Server time failed: {e}"),
80 }
81
82 tracing::info!("=== Test 3: Depth (BTCUSDT) ===");
84 let depth_params = DepthParams::new("BTCUSDT").with_limit(5);
85 match client.depth(&depth_params).await {
86 Ok(depth) => {
87 tracing::info!("Last update ID: {}", depth.last_update_id);
88 tracing::info!(
89 "Price exponent: {}, Qty exponent: {}",
90 depth.price_exponent,
91 depth.qty_exponent
92 );
93 tracing::info!("Bids ({} levels):", depth.bids.len());
94 for (i, level) in depth.bids.iter().take(5).enumerate() {
95 let price = level.price_f64(depth.price_exponent);
96 let qty = level.qty_f64(depth.qty_exponent);
97 tracing::info!(" [{i}] Price: {price:.2}, Qty: {qty:.8}");
98 }
99 tracing::info!("Asks ({} levels):", depth.asks.len());
100 for (i, level) in depth.asks.iter().take(5).enumerate() {
101 let price = level.price_f64(depth.price_exponent);
102 let qty = level.qty_f64(depth.qty_exponent);
103 tracing::info!(" [{i}] Price: {price:.2}, Qty: {qty:.8}");
104 }
105 }
106 Err(e) => tracing::error!("Depth failed: {e}"),
107 }
108
109 tracing::info!("=== Test 4: Trades (BTCUSDT) ===");
111 let trades_params = TradesParams::new("BTCUSDT").with_limit(5);
112 match client.trades(&trades_params).await {
113 Ok(trades) => {
114 tracing::info!(
115 "Price exponent: {}, Qty exponent: {}",
116 trades.price_exponent,
117 trades.qty_exponent
118 );
119 tracing::info!("Trades ({} total):", trades.trades.len());
120 for trade in trades.trades.iter().take(5) {
121 let price = trade.price_f64(trades.price_exponent);
122 let qty = trade.qty_f64(trades.qty_exponent);
123 let side = if trade.is_buyer_maker { "SELL" } else { "BUY" };
124 let datetime = chrono::DateTime::from_timestamp_millis(trade.time).map_or_else(
125 || "?".to_string(),
126 |dt| dt.format("%H:%M:%S%.3f").to_string(),
127 );
128 tracing::info!(
129 " ID: {}, {side} {qty:.8} @ {price:.2} at {datetime}",
130 trade.id
131 );
132 }
133 }
134 Err(e) => tracing::error!("Trades failed: {e}"),
135 }
136
137 tracing::info!("=== Test 5: Depth (ETHUSDT) ===");
139 let depth_params = DepthParams::new("ETHUSDT").with_limit(3);
140 match client.depth(&depth_params).await {
141 Ok(depth) => {
142 tracing::info!("Last update ID: {}", depth.last_update_id);
143 tracing::info!(
144 "Best bid: {:.2}",
145 depth
146 .bids
147 .first()
148 .map_or(0.0, |l| l.price_f64(depth.price_exponent))
149 );
150 tracing::info!(
151 "Best ask: {:.2}",
152 depth
153 .asks
154 .first()
155 .map_or(0.0, |l| l.price_f64(depth.price_exponent))
156 );
157 }
158 Err(e) => tracing::error!("Depth (ETHUSDT) failed: {e}"),
159 }
160
161 tracing::info!("=== All tests completed ===");
162
163 Ok(())
164}