polyoxide-binance 0.38.0

Rust client library for Binance USDⓈ-M futures market data and streams
Documentation

polyoxide-binance

Rust client library for Binance USDⓈ-M futures public market data (fapi.binance.com): contracts, tickers, the premium index and funding, klines, open interest, aggregate trades and order book snapshots. With the ws feature it also streams the market streams on fstream.binance.com, described under Streaming below. No credentials are needed.

Every request is charged against a WeightBudget, because Binance limits each IP by request weight, which varies with the route and its parameters, rather than by request count. The budget follows the server's own count from the X-MBX-USED-WEIGHT-1M header, and a 429 or 418 holds every request until the server's wait is over.

More information about this crate can be found in the crate documentation.

Installation

[dependencies]
polyoxide-binance = "0.37"

Usage

use polyoxide_binance::{
    usdm::types::{Interval, Symbol},
    Usdm,
};

# async fn example() -> Result<(), Box<dyn std::error::Error>> {
let usdm = Usdm::new()?;
let btc = Symbol::new("BTCUSDT")?;

let index = usdm.market().premium_index(&btc).send().await?;
println!("mark {} index {}", index.mark_price, index.index_price);

let candles = usdm
    .market()
    .klines(&btc, Interval::H1)
    .limit(24)
    .send()
    .await?;
println!("{} hourly candles", candles.len());
# Ok(())
# }

Clients in one process should share one budget, since Binance counts weight per IP:

use polyoxide_binance::{Usdm, WeightBudget};

# fn example() -> Result<(), polyoxide_binance::BinanceError> {
let budget = WeightBudget::new();
let a = Usdm::builder().weight_budget(budget.clone()).build()?;
let b = Usdm::builder().weight_budget(budget).build()?;
# Ok(())
# }

Each client may have max_concurrent requests in flight (default 4), and the budget's reserve absorbs in-flight weight only while it stays under 240, so two clients that send weighted routes should each set max_concurrent(2) (2 × 2 × 40 = 160). A client that sends only the funding routes carries no weight and can keep the default.

Streaming

With the ws feature, the market streams arrive over one connection per routed path (/market for trades, klines, mark prices and tickers; /public for depth and book tickers). UsdmWsBuilder keeps each connection alive, replaces a dead one, rotates each before Binance's 24-hour cutoff, replays its streams at Binance's pace, and reports each outage: while the client runs, every Event::Disconnected { path } is followed by Event::Reconnected { path }, after which anything built from that path's streams should be rebuilt. Enable it with polyoxide-binance = { version = "0.37", features = ["ws"] }.

use futures_util::StreamExt;
use polyoxide_binance::usdm::{types::Symbol, ws::{Event, Recovery, StreamName, UsdmWsBuilder}};

let btc = Symbol::new("BTCUSDT")?;
let mut feed = UsdmWsBuilder::new()
    .streams([StreamName::MarkPrice(btc.clone()), StreamName::BookTicker(btc)])
    .connect()
    .await?;
while let Some(event) = feed.next().await {
    let event = match event {
        Ok(event) => event,
        // A frame that did not decode is skipped; anything else ends the stream.
        Err(err) if err.recovery() == Recovery::SkipFrame => continue,
        Err(err) => return Err(err.into()),
    };
    match event {
        Event::Update(update) => println!("{}", serde_json::to_string(&update)?),
        Event::Disconnected { path, reason } => eprintln!("{path} down: {reason}"),
        Event::Reconnected { path } => eprintln!("{path} back"),
        _ => {}
    }
}