Back to Nautilus Trader

Binance SBE Codecs

crates/adapters/binance/src/spot/sbe/README.md

1.227.06.4 KB
Original Source

Binance SBE Codecs

  • generated/ contains Rust code generated by Real Logic's Simple Binary Encoding (SBE) generator from the Binance Spot API SBE schema (schema 3:4). Do not edit these files manually. Regenerate them with the Real Logic SBE tool when the schema changes.
  • stream/ contains hand-written decoders for Binance market data stream messages (schema 1:0).
  • Generic cursor/error utilities are shared from nautilus-serialization behind the sbe feature and re-exported from this module for compatibility.

Licensing

  • The generated/ codecs are generated using the Apache-2.0 licensed Real Logic SBE tool; see ../../../licenses/Apache-2.0-RealLogic-SBE.txt and the entry in ../../../licenses/THIRD_PARTY_LICENSES.md.
  • The hand-written stream/ code is covered by the NautilusTrader project license.

Modifications

The generated generated/ code has been modified from the original SBE generator output:

  • Added module-level lint suppression attributes in generated/mod.rs for clippy compatibility
  • Rewrote crate:: -> super:: and collapsed the three pub use crate::SBE_* lines into a single pub use super::{SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, SBE_SEMANTIC_VERSION};
  • Reordered the pub use decoder::...; pub use encoder::...; block to come before use super::*; (fixes rustfmt)
  • Removed unused codec modules (institutional/allocations, order amendments, user data stream management, block trades). See the strip list in the regeneration steps below.

Regeneration

The current generated/ tree was produced by Real Logic SBE v1.37.1 against Binance's spot_3_4.xml schema. Stay on the same SBE tool version when bumping the schema; SBE v1.38+ emits a different (fluent-encoder) API that would force call-site rewrites in spot/http/parse.rs, spot/http/client.rs, and spot/websocket/trading/decode_sbe.rs.

Prerequisites

  • JDK 17 or newer to run the SBE jar. A portable Temurin JRE works:

    bash
    mkdir -p /tmp/sbegen && cd /tmp/sbegen
    curl -fsSL -o jre.tar.gz \
      "https://api.adoptium.net/v3/binary/latest/21/ga/linux/x64/jre/hotspot/normal/eclipse?project=jdk"
    tar -xzf jre.tar.gz
    export JAVA="$PWD/$(ls -d jdk-21*-jre)/bin/java"
    
  • The SBE tool jar (Maven Central, uk.co.real-logic:sbe-all):

    bash
    curl -fsSL -o sbe-all-1.37.1.jar \
      "https://repo1.maven.org/maven2/uk/co/real-logic/sbe-all/1.37.1/sbe-all-1.37.1.jar"
    
  • The latest Binance Spot SBE schema:

    bash
    curl -fsSL -o spot_latest.xml \
      "https://raw.githubusercontent.com/binance/binance-spot-api-docs/master/sbe/schemas/spot_prod_latest.xml"
    

    spot_prod_latest.xml is a pointer file (one line) naming the active schema; the corresponding spot_<id>_<version>.xml lives in the same directory. The CHANGELOG for breaking and additive changes is at https://github.com/binance/binance-spot-api-docs/blob/master/CHANGELOG.md.

Generate

bash
mkdir -p /tmp/sbegen/out
"$JAVA" \
  --add-opens java.base/jdk.internal.misc=ALL-UNNAMED \
  -Dsbe.target.language=Rust \
  -Dsbe.output.dir=/tmp/sbegen/out \
  -Dsbe.errorLog=yes \
  -jar /tmp/sbegen/sbe-all-1.37.1.jar /tmp/sbegen/spot_3_4.xml

This produces /tmp/sbegen/out/spot_sbe/ shaped as a crate (with Cargo.toml, src/lib.rs, and one src/<message>.rs per codec). The numInGroup UINT8/UINT16 warnings on every group are from Binance's schema (they use groupSizeEncoding rather than a primitive) and can be ignored.

Transform and lift into generated/

Each generated file needs three text rewrites to fit the project's module layout:

  1. use crate::*; -> use super::*;
  2. pub use crate::SBE_SCHEMA_ID; + ..._VERSION; + ..._SEMANTIC_VERSION; (three lines) -> pub use super::{SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, SBE_SEMANTIC_VERSION};
  3. Remaining crate:: -> super::
  4. Move the pub use decoder::...; pub use encoder::...; block above the use super::*; line.

A reference Python script that does all four steps lives at /tmp/sbegen/transform.py while regenerating; see the commit history for crates/adapters/binance/src/spot/sbe/generated/ for the most recent regen for an example.

Strip unused codec modules

Delete these files from the generator output before copying to generated/:

  • account_allocations_response_codec.rs
  • allocation_report_event_codec.rs
  • allocation_report_type.rs
  • allocation_status.rs
  • allocation_transaction_type.rs
  • allocation_type.rs
  • block_trades_response_codec.rs
  • counter_party_role.rs
  • order_amend_keep_priority_response_codec.rs
  • order_amendments_response_codec.rs
  • user_data_stream_ping_response_codec.rs
  • user_data_stream_start_response_codec.rs
  • user_data_stream_stop_response_codec.rs
  • user_data_stream_subscribe_listen_token_response_codec.rs
  • user_data_stream_subscribe_response_codec.rs
  • user_data_stream_unsubscribe_response_codec.rs

These belong to features the adapter does not consume (institutional allocations, order amendments, user-data stream session management, historical block trades).

Rebuild mod.rs

Take the transformed file list and replace the existing pub mod declarations in generated/mod.rs. Keep the existing header (//! doc comment naming the schema version, the #![forbid(unsafe_code)] and #![allow(...)] / #![expect(...)] lint attributes, and the trait/buffer definitions below SBE_SEMANTIC_VERSION). Update:

  • The doc comment //! Generated SBE codecs for Binance Spot API (schema 3:N).
  • pub const SBE_SCHEMA_ID: u16 = <id>;
  • pub const SBE_SCHEMA_VERSION: u16 = <version>;
  • pub const SBE_SEMANTIC_VERSION: &str = "<semantic>";

Final fixups

  • Run cargo +nightly fmt -p nautilus-binance to normalise the generator's whitespace.
  • Bump the hand-written SBE_SCHEMA_HEADER constant in spot/http/client.rs (e.g. "3:4").
  • Update the two schema-version assertions in spot/http/client.rs::tests (test_schema_constants and test_default_headers_include_sbe).
  • Update the schema reference in this README.
  • cargo build -p nautilus-binance and cargo test -p nautilus-binance must pass.
  • cargo clippy -p nautilus-binance --all-targets must pass.

Forward compatibility note

The HTTP SBE parsers in spot/http/parse.rs use the header block_length to skip past unknown trailing fields, so a v3-built decoder can read v4 messages (and vice versa) at the wire level. The strict header.validate() check enforces an exact version match, however, so a schema bump still requires regenerating and updating the constants above.