{"id":29072748,"url":"https://github.com/praying/binance-rs-plus","last_synced_at":"2025-06-27T14:08:52.062Z","repository":{"id":297914118,"uuid":"998237324","full_name":"Praying/binance-rs-plus","owner":"Praying","description":"Unofficial Rust Library for the Binance API and Binance Futures API.","archived":false,"fork":false,"pushed_at":"2025-06-14T00:00:41.000Z","size":3093,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-27T14:08:50.045Z","etag":null,"topics":["binance","cryptocurrencies","trading"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/binance-rs-plus","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Praying.png","metadata":{"files":{"readme":"README-CN.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-08T06:57:03.000Z","updated_at":"2025-06-10T01:56:51.000Z","dependencies_parsed_at":"2025-06-08T10:29:24.688Z","dependency_job_id":null,"html_url":"https://github.com/Praying/binance-rs-plus","commit_stats":null,"previous_names":["praying/binance-rs-plus"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Praying/binance-rs-plus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Praying%2Fbinance-rs-plus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Praying%2Fbinance-rs-plus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Praying%2Fbinance-rs-plus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Praying%2Fbinance-rs-plus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Praying","download_url":"https://codeload.github.com/Praying/binance-rs-plus/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Praying%2Fbinance-rs-plus/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262270426,"owners_count":23285165,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["binance","cryptocurrencies","trading"],"created_at":"2025-06-27T14:08:48.938Z","updated_at":"2025-06-27T14:08:52.044Z","avatar_url":"https://github.com/Praying.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# 🚀  binance-rs-plus \n\n[![Fork Relationship](https://img.shields.io/badge/Origin-wisespace__io/binance__rs-6f42c1?style=flat\u0026logo=git)](https://github.com/wisespace-io/binance-rs-plus)\n\n\u003e 📢 **衍生声明**：此项目衍生自 [binance-rs](https://github.com/wisespace-io/binance-rs)，  \n\u003e 感谢原始作者 [@wisespace-io](https://github.com/wisespace-io) 的贡献\n\n\u003c/div\u003e\n\n一个非官方的 Rust 库，用于 [Binance API](https://github.com/binance/binance-spot-api-docs) (币安现货 API) 和 [Binance Futures API](https://binance-docs.github.io/apidocs/futures/en/#general-info) (币安合约 API)。\n\n[![Crates.io](https://img.shields.io/crates/v/binance-rs-plus.svg)](https://crates.io/crates/binance-rs-plus)\n[![Build Status](https://travis-ci.org/Praying/binance-rs-plus.png?branch=main)](https://travis-ci.org/Praying/binance-rs-plus)\n[![CI](https://github.com/Praying/binance-rs-plus/workflows/Rust/badge.svg)](https://github.com/Praying/binance-rs-plus/actions?query=workflow%3ARust)\n[![MIT licensed](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE-MIT)\n\n[docs.rs 上的文档](https://docs.rs/crate/binance-rs-plus/)\n\n## 风险提示\n\n这是一个个人项目，请自行承担风险。我不会对您的投资损失负责。\n加密货币投资存在较高的市场风险。\n\n## 如何使用\n\n将以下内容添加到您的 `Cargo.toml` 文件中：\n\n```toml\n[dependencies]\nbinance-rs-plus = \"0.1.2\" # 或者 crates.io 上的最新版本\n# binance-rs-plus = { git = \"https://github.com/Praying/binance-rs-plus\" }\ntokio = { version = \"1\", features = [\"full\"] }\nanyhow = \"1.0\"\n```\n\n## Rust \u003e= 1.87.0 (Edition 2024)\n\n```sh\nrustup update stable\n```\n\n## 目录\n- [现货 API](#现货-api)\n  - [市场数据 (现货)](#市场数据-现货)\n  - [账户 (现货)](#账户-现货)\n  - [用户数据流 (现货)](#用户数据流-现货)\n  - [WEBSOCKETS (现货)](#websockets-现货)\n    - [用户数据流数据 (现货)](#用户数据流数据-现货)\n    - [成交 (现货)](#成交-现货)\n    - [K线 (现货)](#k线-现货)\n    - [多流订阅 (现货)](#多流订阅-现货)\n- [合约 API](#合约-api)\n  - [通用 (合约)](#通用-合约)\n  - [市场数据 (合约)](#市场数据-合约)\n  - [用户数据流 (合约)](#用户数据流-合约)\n  - [WEBSOCKETS (合约)](#websockets-合约)\n- [错误处理](#错误处理)\n- [测试网和API集群](#测试网和api集群)\n- [其他交易所](#其他交易所)\n\n## 现货 API\n\n### 市场数据 (现货)\n\n```rust\nuse binance_rs_plus::api::*;\nuse binance_rs_plus::model::*;\nuse binance_rs_plus::market::*;\nuse anyhow::Result;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let market: Market = Binance::new(None, None);\n\n    // 获取默认深度的订单簿\n    match market.get_depth(\"BNBETH\").await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {}\", e),\n    }\n\n    // 获取深度为 500 的订单簿\n    match market.get_custom_depth(\"BNBETH\", 500).await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {}\", e),\n    }\n\n    // 获取所有交易对的最新价格\n    match market.get_all_prices().await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 获取单个交易对的最新价格\n    match market.get_price(\"BNBETH\").await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 获取单个交易对的当前平均价格\n    match market.get_average_price(\"BNBETH\").await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 获取所有交易对订单簿上的最优买卖价/量\n    match market.get_all_book_tickers().await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 获取单个交易对订单簿上的最优买卖价/量\n    match market.get_book_ticker(\"BNBETH\").await {\n        Ok(answer) =\u003e println!(\n            \"买单价: {}, 卖单价: {}\",\n            answer.bid_price, answer.ask_price\n        ),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 24小时价格变动统计\n    match market.get_24h_price_stats(\"BNBETH\").await {\n        Ok(answer) =\u003e println!(\n            \"开盘价: {}, 最高价: {}, 最低价: {:?}\",\n            answer.open_price, answer.high_price, answer.low_price\n        ),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 获取某个交易对最近10条5分钟K线数据:\n    match market.get_klines(\"BNBETH\", \"5m\", 10, None, None).await {\n        Ok(klines) =\u003e {   \n            match klines {\n                binance_rs_plus::model::KlineSummaries::AllKlineSummaries(klines) =\u003e {\n                    if let Some(kline) = klines.first() { // 示例：打印第一条K线\n                        println!(\n                            \"开盘价: {}, 最高价: {}, 最低价: {}\",\n                            kline.open, kline.high, kline.low\n                        );\n                    }\n                }\n            }\n        },\n        Err(e) =\u003e println!(\"错误: {}\", e),\n    }\n    Ok(())\n}\n```\n\n### 账户 (现货)\n\n```rust\nuse binance_rs_plus::api::*;\nuse binance_rs_plus::account::*;\nuse anyhow::Result;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let api_key = Some(\"YOUR_API_KEY\".into()); // 替换为你的API Key\n    let secret_key = Some(\"YOUR_SECRET_KEY\".into()); // 替换为你的Secret Key\n\n    let account: Account = Binance::new(api_key, secret_key);\n\n    // 获取账户信息\n    match account.get_account().await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer.balances),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 获取某个交易对的当前挂单\n    match account.get_open_orders(\"WTCETH\").await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 限价买入 (数量类型已更新为 f64)\n    match account.limit_buy(\"WTCETH\", 10.0, 0.014000).await { \n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 市价买入 (数量类型已更新为 f64)\n    match account.market_buy(\"WTCETH\", 5.0).await { \n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 限价卖出 (数量类型已更新为 f64)\n    match account.limit_sell(\"WTCETH\", 10.0, 0.035000).await { \n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 市价卖出 (数量类型已更新为 f64)\n    match account.market_sell(\"WTCETH\", 5.0).await { \n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n    \n    // 自定义订单 (custom_order 的数量参数之前是 i64, 如果新标准是 f64 请确保类型正确)\n    match account.custom_order(\"WTCETH\", 9999.0, 0.0123, \"SELL\", \"LIMIT\", \"IOC\", None, None, None, None, None).await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    let order_id = 1_957_528;\n    // 查询订单状态\n    match account.order_status(\"WTCETH\", order_id).await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 取消订单\n    match account.cancel_order(\"WTCETH\", order_id).await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 取消某个交易对的所有挂单\n    match account.cancel_all_open_orders(\"WTCETH\").await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 获取特定资产的余额\n    match account.get_balance(\"KNC\").await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n\n    // 获取某个交易对的成交历史\n    match account.trade_history(\"WTCETH\").await {\n        Ok(answer) =\u003e println!(\"{:?}\", answer),\n        Err(e) =\u003e println!(\"错误: {:?}\", e),\n    }\n    Ok(())\n}\n```\n\n### 用户数据流 (现货)\n\n```rust\nuse binance_rs_plus::api::*;\nuse binance_rs_plus::userstream::*;\nuse anyhow::Result;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let api_key_user = Some(\"YOUR_API_KEY\".into()); // 替换为你的API Key\n    let user_stream: UserStream = Binance::new(api_key_user.clone(), None);\n\n    // 开启用户数据流\n    if let Ok(answer) = user_stream.start().await {\n        println!(\"用户数据流已启动 ...\");\n        let listen_key = answer.listen_key;\n        println!(\"Listen Key: {}\", listen_key);\n\n        // 保持用户数据流连接\n        match user_stream.keep_alive(\u0026listen_key).await {\n            Ok(msg) =\u003e println!(\"保持用户数据流连接: {:?}\", msg),\n            Err(e) =\u003e println!(\"错误: {:?}\", e),\n        }\n\n        // 示例：在一段时间或操作后关闭数据流\n        // tokio::time::sleep(tokio::time::Duration::from_secs(60)).await;\n\n        // 关闭用户数据流\n        match user_stream.close(\u0026listen_key).await {\n            Ok(msg) =\u003e println!(\"关闭用户数据流: {:?}\", msg),\n            Err(e) =\u003e println!(\"错误: {:?}\", e),\n        }\n    } else {\n        println!(\"无法启动用户数据流 (请检查您的 API_KEY)\");\n    }\n    Ok(())\n}\n```\n\n### WEBSOCKETS (现货)\n\n#### 用户数据流数据 (现货)\n\n监听账户更新和订单成交。\n\n```rust\nuse binance_rs_plus::api::*;\nuse binance_rs_plus::userstream::*;\nuse binance_rs_plus::websockets::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::Arc;\nuse anyhow::Result;\nuse std::pin::Pin;\nuse std::future::Future;\nuse binance_rs_plus::errors::Result as BinanceResult;\n\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let api_key_user = Some(\"YOUR_API_KEY\".into()); // 重要：替换为您的 API Key\n    let user_stream: UserStream = Binance::new(api_key_user, None);\n\n    match user_stream.start().await {\n        Ok(answer) =\u003e {\n            let listen_key = answer.listen_key;\n            println!(\"Listen Key: {}\", listen_key);\n\n            let keep_running = Arc::new(AtomicBool::new(true));\n            let kr_clone = keep_running.clone();\n\n            let mut web_socket: WebSockets\u003c'_,_\u003e = WebSockets::new(move |event: WebsocketEvent| -\u003e Pin\u003cBox\u003cdyn Future\u003cOutput = BinanceResult\u003c()\u003e\u003e + Send + 'static\u003e\u003e {\n                let kr_handler_clone = kr_clone.clone();\n                Box::pin(async move {\n                    match event {\n                        WebsocketEvent::AccountUpdate(account_update) =\u003e {\n                            println!(\"账户更新: {:?}\", account_update.data);\n                            // 示例：在第一次账户更新后停止\n                            // kr_handler_clone.store(false, Ordering::Relaxed); \n                        },\n                        WebsocketEvent::OrderTrade(trade) =\u003e {\n                            println!(\"订单成交: {:?}\", trade);\n                        },\n                        WebsocketEvent::OcoOrderTrade(oco_trade) =\u003e {\n                            println!(\"OCO 订单成交: {:?}\", oco_trade);\n                        }\n                        _ =\u003e println!(\"未处理事件: {:?}\", event),\n                    };\n                    Ok(())\n                })\n            });\n            \n            if let Err(e) = web_socket.connect(\u0026listen_key).await { // 用户数据流端点\n                println!(\"连接现货用户数据流错误: {:?}\", e);\n                return Ok(());\n            }\n\n            if let Err(e) = web_socket.event_loop(keep_running.clone()).await {\n                println!(\"现货用户数据流事件循环错误: {:?}\", e);\n            }\n            \n            web_socket.disconnect().await.unwrap();\n            println!(\"现货用户数据流已断开\");\n\n        }\n        Err(e) =\u003e println!(\"无法启动现货用户数据流: {:?}\", e),\n    }\n    Ok(())\n}\n```\n\n#### 成交 (现货)\n\n监听单个成交信息。\n\n```rust\nuse binance_rs_plus::websockets::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::Arc;\nuse anyhow::Result;\nuse std::pin::Pin;\nuse std::future::Future;\nuse binance_rs_plus::errors::Result as BinanceResult;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let keep_running = Arc::new(AtomicBool::new(true));\n    let kr_clone = keep_running.clone();\n    let trade_symbol = \"bnbbtc\"; // 示例交易对\n    let stream_name = format!(\"{}@trade\", trade_symbol);\n\n    let mut web_socket: WebSockets\u003c'_,_\u003e = WebSockets::new(move |event: WebsocketEvent| -\u003e Pin\u003cBox\u003cdyn Future\u003cOutput = BinanceResult\u003c()\u003e\u003e + Send + 'static\u003e\u003e {\n        let kr_handler_clone = kr_clone.clone();\n        Box::pin(async move {\n            match event {\n                WebsocketEvent::Trade(trade_event) =\u003e {\n                    println!(\"交易对: {}, 价格: {}, 数量: {}\", trade_event.symbol, trade_event.price, trade_event.qty);\n                    // kr_handler_clone.store(false, Ordering::Relaxed); // 第一次成交后停止\n                }\n                _ =\u003e (),\n            };\n            Ok(())\n        })\n    });\n\n    if let Err(e) = web_socket.connect(\u0026stream_name).await {\n        println!(\"连接 {} 数据流错误: {:?}\", stream_name, e);\n        return Ok(());\n    }\n    if let Err(e) = web_socket.event_loop(keep_running.clone()).await {\n        println!(\"事件循环错误: {:?}\", e);\n    }\n    web_socket.disconnect().await.unwrap();\n    println!(\"已从 {} 数据流断开\", stream_name);\n    Ok(())\n}\n```\n\n#### K线 (现货)\n\n监听K线 (蜡烛图) 数据。\n\n```rust\nuse binance_rs_plus::websockets::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::Arc;\nuse anyhow::Result;\nuse std::pin::Pin;\nuse std::future::Future;\nuse binance_rs_plus::errors::Result as BinanceResult;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let keep_running = Arc::new(AtomicBool::new(true));\n    let kr_clone = keep_running.clone();\n    let symbol = \"ethbtc\";\n    let interval = \"1m\";\n    let stream_name = format!(\"{}@kline_{}\", symbol, interval);\n\n    let mut web_socket: WebSockets\u003c'_,_\u003e = WebSockets::new(move |event: WebsocketEvent| -\u003e Pin\u003cBox\u003cdyn Future\u003cOutput = BinanceResult\u003c()\u003e\u003e + Send + 'static\u003e\u003e {\n        let kr_handler_clone = kr_clone.clone();\n        Box::pin(async move {\n            if let WebsocketEvent::Kline(kline_event) = event {\n                println!(\"交易对: {}, 时间间隔: {}, 开: {}, 收: {}, 高: {}, 低: {}\", \n                    kline_event.kline.symbol, kline_event.kline.interval, kline_event.kline.open, \n                    kline_event.kline.close, kline_event.kline.high, kline_event.kline.low);\n                // kr_handler_clone.store(false, Ordering::Relaxed); // 第一条K线后停止\n            }\n            Ok(())\n        })\n    });\n\n    if let Err(e) = web_socket.connect(\u0026stream_name).await {\n        println!(\"连接 {} 数据流错误: {:?}\", stream_name, e);\n        return Ok(());\n    }\n    if let Err(e) = web_socket.event_loop(keep_running.clone()).await {\n        println!(\"事件循环错误: {:?}\", e);\n    }\n    web_socket.disconnect().await.unwrap();\n    println!(\"已从 {} 数据流断开\", stream_name);\n    Ok(())\n}\n```\n\n#### 多流订阅 (现货)\n\n同时连接多个数据流。\n\n```rust\nuse binance_rs_plus::websockets::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::Arc;\nuse anyhow::Result;\nuse std::pin::Pin;\nuse std::future::Future;\nuse binance_rs_plus::errors::Result as BinanceResult;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let streams = vec![\n        \"ethbtc@kline_1m\".to_string(),\n        \"bnbbtc@depth@100ms\".to_string(),\n        \"ltcbtc@trade\".to_string(),\n    ];\n\n    let keep_running = Arc::new(AtomicBool::new(true));\n    let kr_clone = keep_running.clone();\n\n    let mut web_socket: WebSockets\u003c'_,_\u003e = WebSockets::new(move |event: WebsocketEvent| -\u003e Pin\u003cBox\u003cdyn Future\u003cOutput = BinanceResult\u003c()\u003e\u003e + Send + 'static\u003e\u003e {\n        let _kr_handler_clone = kr_clone.clone(); // 如果希望根据事件停止，请使用此克隆\n        Box::pin(async move {\n            println!(\"收到事件: {:?}\", event);\n            // 示例：为演示目的，在收到任意3个事件后停止。\n            // static COUNTER: AtomicUsize = AtomicUsize::new(0);\n            // if COUNTER.fetch_add(1, Ordering::Relaxed) \u003e= 2 {\n            //     _kr_handler_clone.store(false, Ordering::Relaxed);\n            // }\n            Ok(())\n        })\n    });\n\n    if let Err(e) = web_socket.connect_multiple_streams(\u0026streams).await {\n         println!(\"连接多数据流错误: {:?}\", e);\n        return Ok(());\n    }\n    \n    if let Err(e) = web_socket.event_loop(keep_running.clone()).await {\n        println!(\"事件循环错误: {:?}\", e);\n    }\n    web_socket.disconnect().await.unwrap();\n    println!(\"已从多数据流断开\");\n    Ok(())\n}\n```\n\n## 合约 API\n\n合约 API 客户端允许与 USD-M (USDT本位) 和 COIN-M (币本位) 合约进行交互。\n\n### 通用 (合约)\n\n币安合约的通用端点。\n\n```rust\nuse binance::api::*;\nuse binance::futures::general::*;\nuse anyhow::Result;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let general: FuturesGeneral = Binance::new(None, None);\n\n    // Ping USD-M 合约\n    match general.ping().await { // 默认为 USD-M\n        Ok(answer) =\u003e println!(\"合约 Ping (USD-M) 成功: {:?}\", answer),\n        Err(err) =\u003e println!(\"Ping USD-M 合约错误: {:?}\", err),\n    }\n    \n    // Ping COIN-M 合约\n    match general.ping_coin_m().await {\n        Ok(answer) =\u003e println!(\"合约 Ping (COIN-M) 成功: {:?}\", answer),\n        Err(err) =\u003e println!(\"Ping COIN-M 合约错误: {:?}\", err),\n    }\n\n    // 服务器时间 (USD-M)\n    match general.get_server_time().await { // 默认为 USD-M\n        Ok(answer) =\u003e println!(\"合约服务器时间 (USD-M): {}\", answer.server_time),\n        Err(e) =\u003e println!(\"获取 USD-M 合约服务器时间错误: {:?}\", e),\n    }\n    \n    // 服务器时间 (COIN-M)\n    match general.get_server_time_coin_m().await {\n        Ok(answer) =\u003e println!(\"合约服务器时间 (COIN-M): {}\", answer.server_time),\n        Err(e) =\u003e println!(\"获取 COIN-M 合约服务器时间错误: {:?}\", e),\n    }\n\n    // 交易规则 (USD-M)\n    match general.exchange_info().await { // 默认为 USD-M\n        Ok(answer) =\u003e println!(\"合约交易规则 (USD-M): {} 个交易对\", answer.symbols.len()),\n        Err(e) =\u003e println!(\"获取 USD-M 合约交易规则错误: {:?}\", e),\n    }\n\n    // 交易规则 (COIN-M)\n    match general.exchange_info_coin_m().await {\n        Ok(answer) =\u003e println!(\"合约交易规则 (COIN-M): {} 个交易对\", answer.symbols.len()),\n        Err(e) =\u003e println!(\"获取 COIN-M 合约交易规则错误: {:?}\", e),\n    }\n    Ok(())\n}\n```\n\n### 市场数据 (合约)\n\n访问合约的市场数据。\n\n```rust\nuse binance::api::*;\nuse binance::futures::market::*;\nuse binance::futures::model::*; // 用于 Trades, KlineSummaries 等枚举\nuse anyhow::Result;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let market: FuturesMarket = Binance::new(None, None);\n\n    // USD-M 合约示例 (默认)\n    let symbol_usdm = \"BTCUSDT\";\n    println!(\"--- {} USD-M 合约 ---\", symbol_usdm);\n\n    match market.get_depth(symbol_usdm).await { // 默认为 USD-M\n        Ok(answer) =\u003e println!(\"深度 (USD-M) 更新 ID: {:?}\", answer.last_update_id),\n        Err(e) =\u003e println!(\"获取 USD-M 深度错误: {:?}\", e),\n    }\n\n    match market.get_klines(symbol_usdm, \"5m\", 10, None, None).await { // 默认为 USD-M\n        Ok(KlineSummaries::AllKlineSummaries(answer)) =\u003e {\n            if let Some(kline) = answer.first() {\n                println!(\"第一条 K 线 (USD-M): {:?}\", kline);\n            }\n        },\n        Err(e) =\u003e println!(\"获取 USD-M K 线错误: {:?}\", e),\n    }\n\n    // COIN-M 合约示例\n    let symbol_coinm = \"BTCUSD_PERP\"; // 或特定交割合约，如 BTCUSD_240927\n    println!(\"\\n--- {} COIN-M 合约 ---\", symbol_coinm);\n\n    match market.get_depth_coin_m(symbol_coinm).await {\n        Ok(answer) =\u003e println!(\"深度 (COIN-M) 更新 ID: {:?}\", answer.last_update_id),\n        Err(e) =\u003e println!(\"获取 COIN-M 深度错误: {:?}\", e),\n    }\n\n    match market.get_klines_coin_m(symbol_coinm, \"15m\", 5, None, None).await {\n         Ok(KlineSummaries::AllKlineSummaries(answer)) =\u003e {\n            if let Some(kline) = answer.first() {\n                println!(\"第一条 K 线 (COIN-M): {:?}\", kline);\n            }\n        },\n        Err(e) =\u003e println!(\"获取 COIN-M K 线错误: {:?}\", e),\n    }\n    \n    // 其他市场数据端点 (显示 USD-M, COIN-M 版本添加 _coin_m 后缀)\n    // 例如: get_trades, get_agg_trades, get_24h_price_stats, get_price, get_all_book_tickers 等。\n    // 示例:\n    match market.get_price(symbol_usdm).await {\n        Ok(price_ticker) =\u003e println!(\"{} 价格 (USD-M): {}\", symbol_usdm, price_ticker.price),\n        Err(e) =\u003e  println!(\"错误: {:?}\", e)\n    }\n    \n    match market.get_price_coin_m(symbol_coinm).await {\n        Ok(price_ticker) =\u003e println!(\"{} 价格 (COIN-M): {}\", symbol_coinm, price_ticker.price),\n        Err(e) =\u003e  println!(\"错误: {:?}\", e)\n    }\n\n    Ok(())\n}\n```\n\n### 用户数据流 (合约)\n\n管理合约的用户数据流。需要 API Key。\n\n```rust\nuse binance::api::*;\nuse binance::futures::userstream::*;\nuse anyhow::Result;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let api_key = Some(\"YOUR_FUTURES_API_KEY\".into()); // 替换为你的合约 API Key\n    // 如果币安更改要求，某些用户数据流相关操作可能需要 Secret Key。\n    // 对于 start/keep_alive/close，通常只需要具有正确权限的 API Key。\n    let user_stream: FuturesUserStream = Binance::new(api_key, None); \n\n    // USD-M 用户数据流\n    println!(\"--- USD-M 合约用户数据流 ---\");\n    match user_stream.start().await { // 默认为 USD-M\n        Ok(answer) =\u003e {\n            println!(\"USD-M 数据流已启动。Listen Key: {}\", answer.listen_key);\n            let listen_key = answer.listen_key;\n\n            match user_stream.keep_alive(\u0026listen_key).await {\n                Ok(msg) =\u003e println!(\"保持 USD-M 数据流连接: {:?}\", msg),\n                Err(e) =\u003e println!(\"保持 USD-M 数据流连接错误: {:?}\", e),\n            }\n            // tokio::time::sleep(tokio::time::Duration::from_secs(10)).await; // 保持数据流开启\n            match user_stream.close(\u0026listen_key).await {\n                Ok(msg) =\u003e println!(\"已关闭 USD-M 数据流: {:?}\", msg),\n                Err(e) =\u003e println!(\"关闭 USD-M 数据流错误: {:?}\", e),\n            }\n        }\n        Err(e) =\u003e println!(\"无法启动 USD-M 用户数据流: {:?}\", e),\n    }\n\n    // COIN-M 用户数据流\n    println!(\"\\n--- COIN-M 合约用户数据流 ---\");\n    match user_stream.start_coin_m().await {\n        Ok(answer) =\u003e {\n            println!(\"COIN-M 数据流已启动。Listen Key: {}\", answer.listen_key);\n            let listen_key_coinm = answer.listen_key;\n\n            match user_stream.keep_alive_coin_m(\u0026listen_key_coinm).await {\n                Ok(msg) =\u003e println!(\"保持 COIN-M 数据流连接: {:?}\", msg),\n                Err(e) =\u003e println!(\"保持 COIN-M 数据流连接错误: {:?}\", e),\n            }\n            // tokio::time::sleep(tokio::time::Duration::from_secs(10)).await; // 保持数据流开启\n            match user_stream.close_coin_m(\u0026listen_key_coinm).await {\n                Ok(msg) =\u003e println!(\"已关闭 COIN-M 数据流: {:?}\", msg),\n                Err(e) =\u003e println!(\"关闭 COIN-M 数据流错误: {:?}\", e),\n            }\n        }\n        Err(e) =\u003e println!(\"无法启动 COIN-M 用户数据流: {:?}\", e),\n    }\n    Ok(())\n}\n```\n\n### WEBSOCKETS (合约)\n\n连接到 USD-M 和 COIN-M 合约的市场数据 WebSocket 流。\n对于用户数据流 (账户更新、订单更新)，请使用从 `FuturesUserStream` 的 `start()` 或 `start_coin_m()` 方法获取的 `listen_key`，并连接到相应的 USD-M 或 COIN-M 用户数据 WebSocket 端点。\n\n```rust\nuse binance::futures::websockets::{FuturesWebSockets, FuturesWebsocketEvent, FuturesMarket};\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::Arc;\nuse anyhow::Result;\nuse std::pin::Pin;\nuse std::future::Future;\nuse binance::errors::Result as BinanceResult; // 避免与 anyhow::Result 冲突\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    // USD-M 市场数据流示例\n    let usdm_symbol = \"btcusdt\";\n    let usdm_stream_name = format!(\"{}@kline_1m\", usdm_symbol); // 示例：BTCUSDT 的 1 分钟 K 线\n    println!(\"正在连接到 USD-M 数据流: {}\", usdm_stream_name);\n\n    let keep_running_usdm = Arc::new(AtomicBool::new(true));\n    let kr_usdm_clone = Arc::clone(\u0026keep_running_usdm);\n\n    let mut ws_usdm: FuturesWebSockets\u003c'_,_\u003e = FuturesWebSockets::new(move |event: FuturesWebsocketEvent| -\u003e Pin\u003cBox\u003cdyn Future\u003cOutput = BinanceResult\u003c()\u003e\u003e + Send + 'static\u003e\u003e {\n        let kr_handler_clone = kr_usdm_clone.clone();\n        Box::pin(async move {\n            println!(\"USD-M 事件: {:?}\", event);\n            // kr_handler_clone.store(false, Ordering::Relaxed); // 示例：在第一个事件后停止\n            Ok(())\n        })\n    });\n\n    if let Err(e) = ws_usdm.connect(\u0026FuturesMarket::USDM, \u0026usdm_stream_name).await {\n        eprintln!(\"连接 USD-M 数据流 {} 失败: {:?}\", usdm_stream_name, e);\n    } else {\n        if let Err(e) = ws_usdm.event_loop(keep_running_usdm).await {\n            eprintln!(\"USD-M 数据流 {} 事件循环错误: {:?}\", usdm_stream_name, e);\n        }\n        ws_usdm.disconnect().await.unwrap_or_else(|e| eprintln!(\"断开 USD-M 连接失败: {:?}\", e));\n        println!(\"已从 USD-M 数据流 {} 断开\", usdm_stream_name);\n    }\n    \n    tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; // 短暂暂停\n\n    // COIN-M 市场数据流示例\n    let coinm_symbol = \"btcusd_perp\";\n    let coinm_stream_name = format!(\"{}@aggTrade\", coinm_symbol); // 示例：BTCUSD_PERP 的聚合交易\n    println!(\"\\n正在连接到 COIN-M 数据流: {}\", coinm_stream_name);\n    \n    let keep_running_coinm = Arc::new(AtomicBool::new(true));\n    let kr_coinm_clone = Arc::clone(\u0026keep_running_coinm);\n\n    let mut ws_coinm: FuturesWebSockets\u003c'_,_\u003e = FuturesWebSockets::new(move |event: FuturesWebsocketEvent| -\u003e Pin\u003cBox\u003cdyn Future\u003cOutput = BinanceResult\u003c()\u003e\u003e + Send + 'static\u003e\u003e {\n        let kr_handler_clone = kr_coinm_clone.clone();\n        Box::pin(async move {\n            println!(\"COIN-M 事件: {:?}\", event);\n            // kr_handler_clone.store(false, Ordering::Relaxed); // 示例：在第一个事件后停止\n            Ok(())\n        })\n    });\n\n    if let Err(e) = ws_coinm.connect(\u0026FuturesMarket::COINM, \u0026coinm_stream_name).await {\n        eprintln!(\"连接 COIN-M 数据流 {} 失败: {:?}\", coinm_stream_name, e);\n    } else {\n        if let Err(e) = ws_coinm.event_loop(keep_running_coinm).await {\n             eprintln!(\"COIN-M 数据流 {} 事件循环错误: {:?}\", coinm_stream_name, e);\n        }\n        ws_coinm.disconnect().await.unwrap_or_else(|e| eprintln!(\"断开 COIN-M 连接失败: {:?}\", e));\n        println!(\"已从 COIN-M 数据流 {} 断开\", coinm_stream_name);\n    }\n\n    // 对于合约用户数据流:\n    // 1. 使用 `FuturesUserStream::start()` (USD-M) 或 `FuturesUserStream::start_coin_m()` (COIN-M) 获取 listen_key。\n    // 2. 使用 `FuturesWebSockets::connect()` 和 `FuturesMarket::USDMUserData(\u0026listen_key)` 或 `FuturesMarket::COINMUserData(\u0026listen_key)` 连接。\n    // 示例 (概念性，确保您拥有有效的 listen_key):\n    // let listen_key_example = \"your_futures_listen_key\";\n    // if let Err(e) = ws_usdm.connect(\u0026FuturesMarket::USDMUserData(listen_key_example), \"\").await { ... } \n    // 用户数据流的 stream name 参数通常被忽略或应为空字符串，\n    // 因为 listen_key 本身定义了数据流。如果需要，请查阅币安文档以获取具体信息。\n\n    Ok(())\n}\n```\n\n## 错误处理\n\n提供更详细的错误信息。该库对大多数可能失败的操作使用 `anyhow::Result`，对特定的币安 API 错误使用 `binance::errors::ErrorKind`。\n\n您可以查看 [币安错误代码](https://github.com/binance-exchange/binance-official-api-docs/blob/master/errors.md) 和 [合约错误代码](https://binance-docs.github.io/apidocs/futures/en/#error-codes)。\n\n```rust\nuse binance::errors::{Error as BinanceError, ErrorKind as BinanceLibErrorKind}; // 假设 ErrorKind 是 BinanceError 的一部分\nuse anyhow::Result;\n\nasync fn example_error_handling() -\u003e Result\u003c()\u003e {\n    // ... 一些币安客户端调用 ...\n    // let result = account.get_account().await;\n    // match result {\n    //     Ok(data) =\u003e { /* ... */ }\n    //     Err(e) =\u003e {\n    //         println!(\"发生错误: {}\", e); // 通用的 anyhow 错误\n    //\n    //         // 获取更具体的币安错误详情:\n    //         if let Some(binance_err) = e.downcast_ref::\u003cBinanceError\u003e() {\n    //             match binance_err.kind() { // 假设您的 BinanceError 上有 kind() 方法\n    //                 BinanceLibErrorKind::BinanceError(response) =\u003e {\n    //                     println!(\"币安 API 错误代码: {}, 信息: {}\", response.code, response.msg);\n    //                     match response.code {\n    //                         -1013i32 =\u003e println!(\"过滤器失败: LOT_SIZE!\"), // 注意: 代码可能是 i32 或其他类型\n    //                         -2010i32 =\u003e println!(\"资金不足! {}\", response.msg),\n    //                         _ =\u003e println!(\"未捕获的代码 {}: {}\", response.code, response.msg),\n    //                     }\n    //                 }\n    //                 BinanceLibErrorKind::Msg(msg) =\u003e {\n    //                     println!(\"币安库内部错误信息: {}\", msg);\n    //                 }\n    //                 _ =\u003e println!(\"其他币安库错误: {:?}\", binance_err.kind()),\n    //             }\n    //         }\n    //     }\n    // }\n    Ok(()) // 占位符\n}\n```\n*注意: `BinanceError` 和 `ErrorKind` 的确切结构应参照 `src/errors.rs` 以进行精确处理。*\n\n## 测试网和API集群\n\n如果默认的币安 API URL 存在性能问题，或者您想使用测试网，可以覆盖它们。\n`Config` 结构体可用于为现货、USD-M 合约和 COIN-M 合约指定自定义端点。\n\n[币安现货 API 集群](https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md#general-api-information)\n[币安合约 API 端点](https://binance-docs.github.io/apidocs/futures/en/#endpoint-information) (包含测试网)\n\n```rust\nuse binance::api::*;\nuse binance::config::Config;\nuse binance::market::Market; // 用于现货\nuse binance::futures::general::FuturesGeneral; // 用于合约\n\nfn main() {\n    let use_spot_testnet = true;\n    let use_futures_testnet = true;\n\n    // 现货测试网配置\n    if use_spot_testnet {\n        let config_spot = Config::default()\n            .set_rest_api_endpoint(\"https://testnet.binance.vision\")\n            .set_ws_endpoint(\"wss://testnet.binance.vision/ws\"); // 用于现货 WebSockets\n\n        let market_spot_testnet: Market = Binance::new_with_config(None, None, \u0026config_spot);\n        // 现在使用 market_spot_testnet 进行现货测试网调用\n        println!(\"正在使用现货测试网: {}\", config_spot.rest_api_endpoint);\n    }\n\n    // 合约测试网配置 (USD-M)\n    if use_futures_testnet {\n        let config_futures_usdm = Config::default()\n            .set_futures_rest_api_endpoint(binance::config::FuturesEndpoint::UsdMFuturesTestnet) // 或自定义字符串\n            .set_futures_ws_endpoint(binance::config::FuturesEndpoint::UsdMFuturesTestnet);     // 或用于 WS 的自定义字符串\n\n        let general_futures_usdm_testnet: FuturesGeneral = Binance::new_with_config(None, None, \u0026config_futures_usdm);\n        // 现在使用 general_futures_usdm_testnet 进行 USD-M 合约测试网调用\n        println!(\"正在使用 USD-M 合约测试网 REST: {}\", config_futures_usdm.futures_rest_api_endpoint);\n        println!(\"正在使用 USD-M 合约测试网 WS: {}\", config_futures_usdm.futures_ws_endpoint);\n\n        // 对于 COIN-M 合约测试网\n        let config_futures_coinm = Config::default()\n            .set_futures_coin_m_rest_api_endpoint(binance::config::FuturesEndpoint::CoinMFuturesTestnet)\n            .set_futures_coin_m_ws_endpoint(binance::config::FuturesEndpoint::CoinMFuturesTestnet);\n        \n        let general_futures_coinm_testnet: FuturesGeneral = Binance::new_with_config(None, None, \u0026config_futures_coinm);\n         println!(\"正在使用 COIN-M 合约测试网 REST: {}\", config_futures_coinm.futures_coin_m_rest_api_endpoint);\n         println!(\"正在使用 COIN-M 合约测试网 WS: {}\", config_futures_coinm.futures_coin_m_ws_endpoint);\n    }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpraying%2Fbinance-rs-plus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpraying%2Fbinance-rs-plus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpraying%2Fbinance-rs-plus/lists"}