Expand description
§Bybit Async
Unofficial Rust Library for the Bybit API with Async/Await and ergonomic design.
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. PRs are very welcomed!
§Design Goal
Besides the async/await support, this library aims for being ergonomic by leveraging types. The struct
for REST and Websocket only provides limited functions for you to call: for example, Bybit is
the struct for REST requests and it only exposes one function: fn request. Additionally,
which API endpoint to call and what parameter to carry are all stored in the type information.
for example, creating a new order is
let bybit = Bybit::new();
bybit.request(usdm::NewOrderRequest {
    symbol: "ethusdt".into(),
    r#type: OrderType::Limit,
    side: Side::Buy,
    price: Decimal::from_f64(1500.),
    quantity: Decimal::from_f64(0.004),
    time_in_force: Some(TimeInForce::GTC),
    ..Default::default()
})As you can see, usdm::NewOrderRequest itself knows which endpoint (“/fapi/v1/order”) to send this request to. Moreover,
all the request structs have Default implemented, which allows you to express different parameter
combinations without making the code verbose.
§Examples
§Send a New Order and Cancel it
async fn main() {
   let bybit = Bybit::with_key_and_secret(&var("BYBIT_KEY")?, &var("BYBIT_SECRET")?);
   let resp = bybit
       .request(usdm::NewOrderRequest {
           symbol: "ethusdt".into(),
           r#type: OrderType::Limit,
           side: Side::Buy,
           price: Decimal::from_f64(1500.),
           quantity: Decimal::from_f64(0.004),
           time_in_force: Some(TimeInForce::GTC),
           ..Default::default()
       })
       .await?;
   println!("{resp:?}");
   let resp = bybit
       .request(usdm::CancelOrderRequest {
           symbol: "ethusdt".into(),
           order_id: Some(resp.order_id),
           ..Default::default()
       })
       .await?;
   println!("{resp:?}");
}§Listening to WS
async fn main() {
    let bybit = Bybit::with_key(&var("BYBIT_KEY")?);
    let listen_key = bybit.request(StartUserDataStreamRequest {}).await?;
    let mut ws: BybitWebsocket<UsdMWebsocketMessage> = BybitWebsocket::new(&[
        listen_key.listen_key.as_str(),
        "ethusdt@aggTrade",
        "solusdt@bookTicker",
    ])
    .await?;
    for _ in 0..10000 {
        let msg = ws.next().await.expect("ws exited")?;
        println!("{msg:?}");
    }
}§Module Structure
Since this library heavily uses type, there are a plenty of structs defined in each module. The organization of the structs follow the principle:
- REST related types are defined in the restmodule (mainly request and responses).
- Websocket related types are defined in the websocketmodule (mainly websocket events).
- Common types like OrderTypeare defined in themodelsmodule.
- Bybit distinguishes products like Spot,USDM Futures, so as our types. Types are further stored under theusdm,coinmandspotmodule under therestandwebsocketmodule.
Re-exports§
- pub use rest::Bybit;
- pub use rest::RestResponse;
- pub use websocket::BybitWebsocket;