Skip to content

farhadi/deribit-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Deribit Rust Client

Crates.io docs.rs CI MIT License

Type-safe, async Rust client for the Deribit WebSocket JSON‑RPC v2 API. Request/response types are generated at build time from the official API spec, and a single connection supports both RPC calls and streaming subscriptions.

✨ Features

  • 🏗️ Build-time codegen from Deribit’s spec (production by default, optional Testnet)
  • ⚡ Async WebSocket JSON‑RPC 2.0 over a single multiplexed connection
  • 🦀 Strongly-typed requests, responses, channels and subscription notifications
  • 📡 Simple subscriptions API for public and private channels
  • 🔁 Concurrency-friendly: methods take &self (no mut), and the client is shareable via Arc
  • 💓 Automatic heartbeat handling: responds to Deribit test_request internally (no manual pings needed)

🚀 Quick Start

Add the crate and tokio to your Cargo.toml:

[dependencies]
deribit-api = "0.1.2"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
futures-util = "0.3" # for StreamExt in subscription examples

▶️ Basic usage

Public call example: fetch server time.

use deribit_api::{DeribitClient, Env, PublicGetTimeRequest};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = DeribitClient::connect(Env::Production).await?;
    let time = client.call(PublicGetTimeRequest {}).await?;
    println!("Server time (µs): {:?}", time);
    Ok(())
}

🔐 Authentication + private methods

Authenticate using client credentials and fetch an account summary.

use deribit_api::{
    DeribitClient, Env, PublicAuthRequest, PublicAuthGrantType, PrivateGetAccountSummaryRequest,
    WalletCurrency,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = DeribitClient::connect(Env::Production).await?;

    let client_id = std::env::var("DERIBIT_CLIENT_ID")?;
    let client_secret = std::env::var("DERIBIT_CLIENT_SECRET")?;

    let _auth = client
        .call(PublicAuthRequest {
            grant_type: PublicAuthGrantType::ClientCredentials,
            client_id,
            client_secret,
            ..Default::default()
        })
        .await?;

    let summary = client
        .call(PrivateGetAccountSummaryRequest {
            currency: WalletCurrency::Btc,
            ..Default::default()
        })
        .await?;
    println!("Account summary: {:?}", summary);
    Ok(())
}

📡 Streaming subscriptions

Untyped variant: subscribe by channel string and receive a Stream of serde_json::Value.

use deribit_api::{DeribitClient, Env};
use futures_util::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = DeribitClient::connect(Env::Production).await?;

    let mut stream = client.subscribe_raw("trades.BTC-PERPETUAL.raw").await?;

    while let Some(msg) = stream.next().await {
        println!("{:?}", msg);
    }
    Ok(())
}

Typed variant: use generated channel types and get a Stream of typed messages.

use deribit_api::{DeribitClient, Env, SubscriptionInterval, TradesInstrumentNameChannel};
use futures_util::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = DeribitClient::connect(Env::Production).await?;

    let channel = TradesInstrumentNameChannel {
        instrument_name: "BTC-PERPETUAL".to_string(),
        interval: SubscriptionInterval::Agg2,
    };
    let mut stream = client.subscribe(channel).await?;

    while let Some(msg) = stream.next().await {
        println!("{:?}", msg);
    }
    Ok(())
}

🧪 Testnet

  • Connect with Env::Testnet:
let client = DeribitClient::connect(Env::Testnet).await?;
  • Enable the feature to also generate Testnet types:
[dependencies]
deribit-api = { version = "0.1.2", features = ["testnet"] }

When the testnet feature is enabled, production types live at the crate root (deribit_api::*), and Testnet‑generated types are available under deribit_api::testnet::*.

Note: Enable the testnet feature only if you need endpoints or fields that exist only on Testnet. If you don't need any Testnet‑specific features, you can connect to Env::Testnet while using the default production spec and all overlapping APIs will work as expected.

🧩 API model

  • Each endpoint like public/get_time maps to a request struct named PublicGetTimeRequest.
  • Send requests via client.call(request).await.
  • Responses deserialize into generated structs/enums where possible, or serde_json::Value for generic schemas.
  • Subscriptions expose generated channel structs (e.g., TradesInstrumentNameChannel) implementing the Subscription trait. Use client.subscribe(channel).await? for typed streams, or client.subscribe_raw("...") for untyped.

Error type: all calls return Result<T, deribit_api::Error> (covers RPC, WebSocket, and JSON decode errors).

🧵 Low-level: call_raw

If you want to call a method by name with ad‑hoc JSON parameters, use call_raw. It returns a serde_json::Value.

Requires adding serde_json to your Cargo.toml:

[dependencies]
serde_json = "1"
use deribit_api::{DeribitClient, Env};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = DeribitClient::connect(Env::Production).await?;

    // Public call
    let time = client.call_raw("public/get_time", json!({})).await?;
    println!("Server time (µs): {}", time);

    // Authenticate (enables private methods on this connection)
    let _auth = client
        .call_raw(
            "public/auth",
            json!({
                "grant_type": "client_credentials",
                "client_id": std::env::var("DERIBIT_CLIENT_ID")?,
                "client_secret": std::env::var("DERIBIT_CLIENT_SECRET")?,
            }),
        )
        .await?;

    // Private call
    let account = client
        .call_raw(
            "private/get_account_summary",
            json!({ "currency": "BTC" }),
        )
        .await?;
    println!("Account summary: {}", account);

    Ok(())
}

🤝 Concurrency and sharing

The client is safe to share across tasks using std::sync::Arc and does not require mut. All methods take &self and internally multiplex over a single WebSocket connection.

use std::sync::Arc;
use deribit_api::{DeribitClient, Env, PublicGetTimeRequest, SubscriptionInterval, TradesInstrumentNameChannel};
use futures_util::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Arc::new(DeribitClient::connect(Env::Production).await?);

    // Task 1: make RPC calls
    let c1 = client.clone();
    let h1 = tokio::spawn(async move {
        let _ = c1.call(PublicGetTimeRequest {}).await;
    });

    // Task 2: subscribe to a channel
    let c2 = client.clone();
    let h2 = tokio::spawn(async move {
        let mut stream = c2.subscribe(TradesInstrumentNameChannel {
            instrument_name: "BTC-PERPETUAL".to_string(),
            interval: SubscriptionInterval::Agg2,
        }).await.unwrap();
        while let Some(_data) = stream.next().await {}
    });

    let _ = tokio::join!(h1, h2);
    Ok(())
}

🔧 Configuration

  • Default spec source: production https://www.deribit.com/static/deribit_api_v2.json.

  • Override the API spec used for codegen at build time in one of these ways:

    • Enable the bundled-spec feature to force using bundled deribit_api_v2.json file:
      • Enabling bundled-spec feature in Cargo.toml:
        [dependencies]
        deribit-api = { version = "0.1.2", features = ["bundled-spec"] }
      • Running tests using bundled spec: cargo test --features bundled-spec
    • Environment variable DERIBIT_API_SPEC pointing to a local file path or a URL.
      • Examples:
        • DERIBIT_API_SPEC=./deribit_api_v2.json cargo build
        • DERIBIT_API_SPEC=https://example.com/deribit_api_v2.json cargo build
  • Testnet codegen: enable testnet to also generate Testnet types alongside production:

    • Enabling testnet feature in Cargo.toml:
      [dependencies]
      deribit-api = { version = "0.1.2", features = ["testnet"] }
    • Production types are at the crate root (deribit_api::*); Testnet types live under deribit_api::testnet::*.
    • Only enable this if you need new Testnet endpoints/fields that are not available on production; otherwise you can use Env::Testnet with the default production spec.
  • The build script also sets GENERATED_DERIBIT_CLIENT_PATH (env var) to the formatted, generated production client file path in target/, which can help with debugging.

📚 Examples

This repo ships several runnable examples:

# Public calls
cargo run --example basic_usage

# Subscriptions
cargo run --example subscription

# Authentication + private endpoints
cargo run --example authentication

# Setting heartbeats
cargo run --example heartbeat

# Testnet (enables the feature and uses the Testnet endpoint)
cargo run --features testnet --example testnet

# Low-level + untyped stream
cargo run --example untyped

# Concurrent RPC + subscription on one connection
cargo run --example concurrent

🛠️ Development

cargo build
cargo check --examples
cargo test

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

⚠️ Disclaimer

This software is for educational and development purposes. Use at your own risk when trading with real funds.

About

Deribit Rust Client

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages