CCXT
Rust Examples

Binance Typed

Binance Typed — CCXT Rust code example.

// CCXT Rust — Binance typed-wrapper example.
//
// Compared to `binance_basics.rs` (which uses the untyped `BinanceCore` and
// works with `Value` enums + manual panic handling), this example uses
// the codegen'd typed `Binance` wrapper. The unified API surface returns
// native Rust types (`Ticker`, `Vec<Trade>`, `OrderBook`, …) wrapped in
// `Result<T, ccxt::ExchangeError>`, so error handling is idiomatic Rust:
//
//   match binance.fetch_ticker("BTC/USDT", Params::none()).await {
//       Ok(t)  => println!("last = {:?}", t.last),
//       Err(e) => eprintln!("[{}] {}", e.kind, e.message),
//   }
//
// The typed wrapper is regenerated by `build/generateRustWrappers.ts`
// alongside the other Rust transpiler outputs.

use ccxt::Binance;
use ccxt::Params;

#[tokio::main]
async fn main() {
    println!("=== Binance — CCXT Rust typed-wrapper example ===\n");

    // Construct the typed facade. Internally this wraps a `BinanceCore`
    // and exposes typed unified-API methods via `Deref<Target = BinanceCore>`
    // (so untyped methods stay reachable) plus per-method `*_typed`
    // overrides that decode to `ccxt::types::*`.
    let mut binance = Binance::new(None);

    // 1. load_markets — required to resolve a unified symbol to the
    //    exchange-specific id used downstream. It isn't in the `*_typed`
    //    surface, so the wrapper exposes it as an explicit convenience
    //    method (routed through the audited pin projection).
    println!("→ load_markets() …");
    binance.load_markets(false).await;
    // Typed accessor — no `Value` handling needed to read the loaded markets.
    let market_count = binance.markets().len();
    println!("   ✓ {} markets loaded\n", market_count);

    // 2. fetch_ticker_typed → returns a `Ticker` struct.
    println!("→ fetch_ticker(\"BTC/USDT\") …");
    match binance.fetch_ticker("BTC/USDT", Params::none()).await {
        Ok(t) => {
            println!(
                "   ✓ symbol={}  last={:?}  bid={:?}  ask={:?}",
                t.symbol, t.last, t.bid, t.ask
            );
        }
        Err(e) => eprintln!("   ✗ [{}] {}", e.kind, e.message),
    }
    println!();

    // 3. fetch_trades_typed → returns Vec<Trade>.
    println!("→ fetch_trades(\"BTC/USDT\", since=None, limit=5) …");
    match binance
        .fetch_trades("BTC/USDT", None, Some(5), Params::none())
        .await
    {
        Ok(trades) => {
            println!("   ✓ {} trades", trades.len());
            for t in trades.iter().take(5) {
                println!(
                    "     {:?}  side={:?}  px={:?}  amt={:?}",
                    t.id, t.side, t.price, t.amount
                );
            }
        }
        Err(e) => eprintln!("   ✗ [{}] {}", e.kind, e.message),
    }
    println!();

    // 4. fetch_order_book_typed → returns an `OrderBook`.
    println!("→ fetch_order_book(\"BTC/USDT\", limit=5) …");
    match binance
        .fetch_order_book("BTC/USDT", Some(5), Params::none())
        .await
    {
        Ok(ob) => {
            println!(
                "   ✓ symbol={:?}  bids={}  asks={}",
                ob.symbol,
                ob.bids.len(),
                ob.asks.len()
            );
            if let Some(top_bid) = ob.bids.first() {
                println!("     top bid: price={} amount={}", top_bid[0], top_bid[1]);
            }
            if let Some(top_ask) = ob.asks.first() {
                println!("     top ask: price={} amount={}", top_ask[0], top_ask[1]);
            }
        }
        Err(e) => eprintln!("   ✗ [{}] {}", e.kind, e.message),
    }
}