#![allow(dead_code)]
use binance_rs_plus::api::*;
use binance_rs_plus::userstream::*;
use binance_rs_plus::websockets::*;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use anyhow::Result;
use binance_rs_plus::errors::Result as BinanceResult;
#[tokio::main]
async fn main() -> Result<()> {
market_websocket().await?;
Ok(())
}
async fn user_stream() -> Result<()> {
let api_key_user = Some("YOUR_API_KEY".into()); let user_stream: UserStream = Binance::new(api_key_user, None);
match user_stream.start().await {
Ok(answer) => {
println!("Data Stream Started ...");
let listen_key = answer.listen_key;
println!("Listen Key: {}", listen_key);
match user_stream.keep_alive(&listen_key).await {
Ok(msg) => println!("Keepalive user data stream: {:?}", msg),
Err(e) => eprintln!("Error keeping alive user data stream: {:?}", e),
}
match user_stream.close(&listen_key).await {
Ok(msg) => println!("Close user data stream: {:?}", msg),
Err(e) => eprintln!("Error closing user data stream: {:?}", e),
}
}
Err(e) => {
eprintln!(
"Not able to start an User Stream (Check your API_KEY): {:?}",
e
);
}
}
Ok(())
}
async fn user_stream_websocket() -> Result<()> {
let keep_running = Arc::new(AtomicBool::new(true));
let api_key_user = Some("YOUR_API_KEY".into()); let user_stream: UserStream = Binance::new(api_key_user, None);
match user_stream.start().await {
Ok(answer) => {
let listen_key = answer.listen_key;
println!("User stream started with listen key: {}", listen_key);
let mut web_socket: WebSockets<'_> = WebSockets::new(move |event: WebsocketEvent| {
Box::pin(async move {
match event {
WebsocketEvent::AccountUpdate(account_update) => {
println!("Account Update: {:?}", account_update.data);
for balance in &account_update.data.balances {
println!(
"Asset: {}, Wallet Balance: {}, Cross Wallet Balance: {}, Balance Change: {}",
balance.asset,
balance.wallet_balance,
balance.cross_wallet_balance,
balance.balance_change
);
}
}
WebsocketEvent::OrderTrade(trade) => {
println!(
"Order Trade Update: Symbol: {}, Side: {}, Price: {}, Execution Type: {}",
trade.symbol, trade.side, trade.price, trade.execution_type
);
}
_ => { }
};
Ok(()) as BinanceResult<()>
})
});
web_socket.connect(&listen_key).await?;
println!("Connected to user stream WebSocket.");
let keep_running_clone = keep_running.clone();
tokio::spawn(async move {
tokio::time::sleep(tokio::time::Duration::from_secs(30)).await;
println!("Signaling user stream WebSocket to stop...");
keep_running_clone.store(false, Ordering::Relaxed);
});
if let Err(e) = web_socket.event_loop(keep_running.clone()).await {
if e.to_string().contains("WebSocket closed by server")
|| e.to_string().contains("WebSocket stream ended")
{
println!("User stream WebSocket closed as expected or stream ended.");
} else {
eprintln!("Error in user stream WebSocket event loop: {:?}", e);
}
}
println!("Closing user stream channel with Binance...");
user_stream.close(&listen_key).await?;
println!("Disconnecting user stream WebSocket...");
web_socket.disconnect().await?;
println!("User stream closed and disconnected.");
}
Err(e) => {
eprintln!(
"Not able to start an User Stream (Check your API_KEY): {:?}",
e
);
}
}
Ok(())
}
async fn market_websocket() -> Result<()> {
let keep_running = Arc::new(AtomicBool::new(true));
let keep_running_for_event_loop = Arc::clone(&keep_running);
let agg_trade_stream_name = String::from("ethbtc@aggTrade");
let mut web_socket: WebSockets<'_> = WebSockets::new(move |event: WebsocketEvent| {
let keep_running_for_callback = Arc::clone(&keep_running);
Box::pin(async move {
match event {
WebsocketEvent::Trade(trade) => {
println!(
"Symbol: {}, price: {}, qty: {}",
trade.symbol, trade.price, trade.qty
);
}
WebsocketEvent::DepthOrderBook(depth_order_book) => {
println!(
"Symbol: {}, Bids: {:?}, Ask: {:?}",
depth_order_book.symbol, depth_order_book.bids, depth_order_book.asks
);
}
WebsocketEvent::OrderBook(order_book) => {
println!(
"last_update_id: {}, Bids: {:?}, Ask: {:?}",
order_book.last_update_id, order_book.bids, order_book.asks
);
}
WebsocketEvent::AggrTrades(agg_trade_event) => {
println!("Aggregated Trade: {:?}", agg_trade_event);
keep_running_for_callback.store(false, Ordering::Relaxed);
}
_ => { }
};
Ok(()) as BinanceResult<()>
})
});
web_socket.connect(&agg_trade_stream_name).await?;
println!("Connected to {} stream.", agg_trade_stream_name);
if let Err(e) = web_socket.event_loop(keep_running_for_event_loop).await {
if e.to_string().contains("WebSocket closed by server")
|| e.to_string().contains("WebSocket stream ended")
{
println!(
"Market WebSocket {} closed as expected or stream ended.",
agg_trade_stream_name
);
} else {
eprintln!(
"Error in market WebSocket event loop ({}): {:?}",
agg_trade_stream_name, e
);
}
}
web_socket.disconnect().await?;
println!("Disconnected from {} stream.", agg_trade_stream_name);
Ok(())
}
async fn all_trades_websocket() -> Result<()> {
let keep_running = Arc::new(AtomicBool::new(true));
let keep_running_for_event_loop = Arc::clone(&keep_running);
let all_tickers_stream = String::from("!ticker@arr");
let mut web_socket = WebSockets::new(move |event: WebsocketEvent| {
let keep_running_for_callback = Arc::clone(&keep_running);
Box::pin(async move {
if let WebsocketEvent::DayTickerAll(ticker_events) = event {
println!(
"Received a batch of {} DayTickerAll events.",
ticker_events.len()
);
for tick_event in ticker_events.iter().take(2) {
println!(
"Symbol: {}, price: {}, qty: {}",
tick_event.symbol, tick_event.best_bid, tick_event.best_bid_qty
);
}
keep_running_for_callback.store(false, Ordering::Relaxed);
}
Ok(()) as BinanceResult<()>
})
});
web_socket.connect(&all_tickers_stream).await?;
println!("Connected to {} stream.", all_tickers_stream);
if let Err(e) = web_socket.event_loop(keep_running_for_event_loop).await {
if e.to_string().contains("WebSocket closed by server")
|| e.to_string().contains("WebSocket stream ended")
{
println!(
"All trades WebSocket ({}) closed as expected or stream ended.",
all_tickers_stream
);
} else {
eprintln!(
"Error in all_trades_websocket event loop ({}): {:?}",
all_tickers_stream, e
);
}
}
web_socket.disconnect().await?;
println!("Disconnected from {} stream.", all_tickers_stream);
Ok(())
}
async fn kline_websocket() -> Result<()> {
let keep_running = Arc::new(AtomicBool::new(true));
let keep_running_for_event_loop = Arc::clone(&keep_running);
let kline_stream = String::from("ethbtc@kline_1m");
let mut web_socket = WebSockets::new(move |event: WebsocketEvent| {
let keep_running_for_callback = Arc::clone(&keep_running);
Box::pin(async move {
if let WebsocketEvent::Kline(kline_event) = event {
println!(
"Symbol: {}, high: {}, low: {}",
kline_event.kline.symbol, kline_event.kline.low, kline_event.kline.high
);
keep_running_for_callback.store(false, Ordering::Relaxed);
}
Ok(()) as BinanceResult<()>
})
});
web_socket.connect(&kline_stream).await?;
println!("Connected to {} stream.", kline_stream);
if let Err(e) = web_socket.event_loop(keep_running_for_event_loop).await {
if e.to_string().contains("WebSocket closed by server")
|| e.to_string().contains("WebSocket stream ended")
{
println!(
"Kline WebSocket ({}) closed as expected or stream ended.",
kline_stream
);
} else {
eprintln!(
"Error in kline_websocket event loop ({}): {:?}",
kline_stream, e
);
}
}
web_socket.disconnect().await?;
println!("Disconnected from {} stream.", kline_stream);
Ok(())
}
async fn last_price_for_one_symbol() -> Result<()> {
let keep_running = Arc::new(AtomicBool::new(true));
let keep_running_for_event_loop = Arc::clone(&keep_running);
let ticker_stream = String::from("btcusdt@ticker");
let mut web_socket = WebSockets::new(move |event: WebsocketEvent| {
let keep_running_for_callback = Arc::clone(&keep_running);
Box::pin(async move {
if let WebsocketEvent::DayTicker(ticker_event) = event {
let current_close_price: f32 =
ticker_event.current_close.parse().unwrap_or_default();
println!(
"BTCUSDT Ticker - Avg Price: {}, Current Close: {}",
ticker_event.average_price, current_close_price
);
keep_running_for_callback.store(false, Ordering::Relaxed);
}
Ok(()) as BinanceResult<()>
})
});
web_socket.connect(&ticker_stream).await?;
println!("Connected to {} stream.", ticker_stream);
if let Err(e) = web_socket.event_loop(keep_running_for_event_loop).await {
if e.to_string().contains("WebSocket closed by server")
|| e.to_string().contains("WebSocket stream ended")
{
println!(
"Ticker WebSocket ({}) closed as expected or stream ended.",
ticker_stream
);
} else {
eprintln!(
"Error in last_price_for_one_symbol event loop ({}): {:?}",
ticker_stream, e
);
}
}
web_socket.disconnect().await?;
println!("Disconnected from {} stream.", ticker_stream);
Ok(())
}
async fn multiple_streams() -> Result<()> {
let endpoints = ["ethbtc@depth@100ms", "bnbeth@depth@100ms"]
.map(String::from)
.to_vec();
let keep_running = Arc::new(AtomicBool::new(true));
let keep_running_for_event_loop = Arc::clone(&keep_running);
let mut web_socket: WebSockets<'_> = WebSockets::new(move |event: WebsocketEvent| {
let keep_running_for_callback = Arc::clone(&keep_running);
Box::pin(async move {
if let WebsocketEvent::DepthOrderBook(depth_order_book) = event {
println!("Multi-stream Depth: {:?}", depth_order_book.symbol);
static mut COUNT: u8 = 0;
unsafe {
COUNT += 1;
if COUNT > 5 {
keep_running_for_callback.store(false, Ordering::Relaxed);
}
}
}
Ok(()) as BinanceResult<()>
})
});
web_socket.connect_multiple_streams(&endpoints).await?;
println!("Connected to multiple streams: {:?}", endpoints);
if let Err(e) = web_socket.event_loop(keep_running_for_event_loop).await {
if e.to_string().contains("WebSocket closed by server")
|| e.to_string().contains("WebSocket stream ended")
{
println!("Multiple streams WebSocket closed as expected or stream ended.");
} else {
eprintln!("Error in multiple_streams event loop: {:?}", e);
}
}
web_socket.disconnect().await?;
println!("Disconnected from multiple streams.");
Ok(())
}