# binance-async
Unofficial Rust Library for the [Binance API](https://github.com/binance-exchange/binance-official-api-docs) with Async/Await and ergonomic design.
[](https://crates.io/crates/binance-async)
[](https://github.com/dovahcrow/binance-async-rs/actions/workflows/ci.yml)
[](./LICENSE-MIT)
[](./LICENSE-APACHE)
[Documentation](https://docs.rs/crate/binance-async)
This library borrows code from Flavio Oliveira (wisespace-io)'s [work](https://github.com/wisespace-io/binance-rs). Thanks for his excellent library!
This repo is at its early stage, not all requests/websockets are implemented.
However, the related mechanism is already there: adding support for new requests/websocket events
should only require [several lines of code](#missing-endpoints-you-can-add-it-easily). PRs are very welcomed!
## Risk Warning
It is a personal project, use at your own risk. I will not be responsible for your investment losses.
Cryptocurrency investment is subject to high market risk.
## MSRV
Rust 1.60
## Usage
This library is just revived. Please use the git version for now.
~~Add this to your Cargo.toml~~
```toml
[dependencies]
binance-async = 0.2
```
Examples located in the examples folder.
* `examples/websocket.rs`: websocket subscribing market data and user data.
* `examples/new_order_and_cancel.rs`: create a new order than then cancel it.
## Ergonomic Design
The design of this library follows the `struct-based Request/Response` pattern.
This makes the API requests easy to use and understand.
For example, to make a new order, you need to fill the `OrderRequest` struct, which
is defined as:
```rust
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct OrderRequest {
pub symbol: String,
pub qty: Decimal,
pub price: Decimal,
pub stop_price: Option<Decimal>,
pub order_side: OrderSide,
pub order_type: OrderType,
pub time_in_force: TimeInForce,
pub new_client_order_id: Option<String>,
}
```
You can just fill in the fields you want to fill, and leave the rest to `Default`. e.g.
```rust
let req = OrderRequest {
symbol: "btcusd".into(),
qty: 3.try_into().unwrap(),
price: 20000.try_into().unwrap(),
..Default::default()
};
let client = Binance::new();
client.request(req).await?;
```
This avoids the library to have a plethora of methods for different parameter
combinations.
The magic behind the convenience is the `Request` trait. For example, `OrderRequest`
has the `Request` implemented as:
```rust
impl Request for OrderRequest {
const API: APIUrl = APIUrl::Spot;
const ENDPOINT: &'static str = "/api/v3/order";
const METHOD: Method = Method::POST;
const SIGNED: bool = true;
type Response = OrderInfo;
}
```
This associates necessary information to each request struct.
## Missing Endpoints? You Can Add it Easily!
Due to the amount of APIs Binance provides, it is hard to cover everything for this
library.
However, since this library uses the `struct-based Request/Response` pattern, adding a new
request is easy. You only need to add a new `Request` struct and a new `Response` struct
into the source code and implement the `Request` trait to the newly added `Request`
struct.
For example, adding `GET /fapi/v1/positionSide/dual` is just
```rust
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub struct GetCurrentPositionModeRequest {}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GetCurrentPositionModeResponse {
dual_side_position: bool,
}
impl Request for GetCurrentPositionModeRequest {
const API: APIUrl = APIUrl::UsdMFutures;
const ENDPOINT: &'static str = "/fapi/v1/positionSide/dual";
const METHOD: Method = Method::GET;
const SIGNED: bool = true;
type Response = GetCurrentPositionModeResponse;
}
```
Or, to make it simpler, use the macro ([see in action](https://github.com/dovahcrow/binance-async-rs/blob/master/src/rest/usdm/account.rs)):
```rust
crate::define_request! {
Name => GetCurrentPositionMode;
Product => Product::UsdMFutures;
Endpoint => "/fapi/v1/positionSide/dual";
Method => Method::GET;
Signed => true;
Request => {};
Response => {
pub dual_side_position: bool,
};
}
```