Skip to main content

rustrade_execution/client/binance/
mod.rs

1//! Binance execution clients.
2//!
3//! - [`BinanceSpot`] — Binance Spot `ExecutionClient` (REST + signed WebSocket API).
4//! - [`BinanceMargin`] — Binance Cross Margin `ExecutionClient` (REST orders/queries +
5//!   a hand-rolled `userListenToken` user-data stream). Configured via
6//!   [`BinanceMarginConfig`]/[`MarginSideEffect`].
7//!
8//! Both clients share exchange-agnostic infrastructure (reconnect/backoff,
9//! rate-limit tracking, event deduplication, error parsing, and the
10//! Binance-string parsers) from the `shared` module, so resilience behaviour is
11//! implemented once and reused rather than duplicated per client.
12//!
13//! # Every fill on the account is delivered
14//!
15//! Both clients' account streams report every fill on the account, whoever placed the order:
16//! this client, another API client, another program, or the venue's own app. Binance marks none
17//! of them as another client's, so each arrives as [`TradeOrigin::Order`](crate::trade::TradeOrigin::Order).
18//! Fill recovery after a reconnect and `fetch_trades` read the account's fills the same way.
19//!
20//! A consumer that trades the account outside the engine it feeds therefore filters those fills
21//! out itself. [`Trade::client_order_id`](crate::trade::Trade::client_order_id) carries the client
22//! order id each fill's order was placed with, so orders placed outside the engine under ids
23//! of their own, such as with a prefix, can be recognised by their fills.
24//!
25//! # Logging: `binance_sdk` writes request credentials at `DEBUG`
26//!
27//! Both clients run on the `binance-sdk` crate, whose WebSocket API client logs every outgoing
28//! request at `DEBUG`, after it has been signed:
29//!
30//! - [`BinanceSpot`] places and cancels orders and subscribes to its user-data stream with signed
31//!   requests, so each of those log lines carries the account's **API key** and the request's
32//!   **signature**.
33//! - [`BinanceMargin`] subscribes to its user-data stream with an unsigned request whose only
34//!   credential is the **listen token**, which is logged in the same way.
35//!
36//! The API secret and private key are never logged. The SDK logs these lines with `tracing`
37//! under the `binance_sdk` target.
38//!
39//! This library installs no subscriber, so what reaches your logs is decided by the filter your
40//! application builds. A bare `RUST_LOG=debug` enables these lines. To keep them out by default,
41//! seed a `binance_sdk=info` directive **before** your own:
42//!
43//! ```
44//! use tracing_subscriber::EnvFilter;
45//!
46//! let user = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_owned());
47//! let filter = EnvFilter::try_new(format!("binance_sdk=info,{user}"))?;
48//! # Ok::<(), Box<dyn std::error::Error>>(())
49//! ```
50//!
51//! `EnvFilter` applies the most specific matching directive, and a later directive for the same
52//! target replaces an earlier one. So a bare `debug` cannot lift the seeded `binance_sdk=info`,
53//! while an explicit `RUST_LOG=binance_sdk=debug` still can when you need the SDK's traffic.
54//! Adding the directive *after* reading the environment, as in
55//! `EnvFilter::from_default_env().add_directive(..)`, gets this backwards: it silently overrides
56//! an explicit request.
57
58mod margin;
59mod margin_risk;
60mod shared;
61mod spot;
62
63pub use margin::{BinanceMargin, BinanceMarginConfig, MarginForcedLiquidation, MarginSideEffect};
64pub use spot::{BinanceSpot, BinanceSpotConfig, BinanceSpotConfigError};