Skip to content

8ball030/thalex_rust_sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

322 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Thalex Rust SDK

This is a community-driven Rust SDK for interacting with the Thalex API, providing tools for real-time data streaming and market analysis.

Features

  • WebSocket client for real-time data streaming
  • Support for various market data types (OHLC, trades, quotes)
  • Easy integration with Rust applications
  • Callback based event handling

Note, this SDK is not officially maintained by Thalex but is developed and supported by the community. It is a work in progress, and contributions are welcome!

Getting Started

To get started with the Thalex Rust SDK, install the crate via Cargo:

cargo add thalex_rust_sdk

A client can be either public or private, depending on whether you need to access authenticated endpoints. For public access, you can create a WsClient without any authentication parameters.

For private access, you will need to get an API key and secret from your Thalex account and create a WsClient with those credentials.

A helpful instantiation method is provided to create a private client using the following environment variables:

THALEX_PRIVATE_KEY_PATH THALEX_KEY_ID THALEX_ACCOUNT_ID THALEX_ENVIRONMENT (must be set to either Mainnet or Testnet)

Additionally you can create a client with a Custom environment by providing a WebSocket URL directly.

// examples/create_client.rs
use thalex_rust_sdk::{types::Environment, ws_client::WsClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let env = Environment::Mainnet;
    // public client
    let client = WsClient::new_public(env).await.unwrap();
    // shutting down the client
    client.wait_for_connection().await;
    println!("Client connected, shutting down...");
    client.shutdown("Done!").await.unwrap();

    let private_client = WsClient::from_env().await.unwrap();
    println!("Private client created from environment variables, shutting down...");
    private_client
        .shutdown("Done with private client!")
        .await
        .unwrap();

    // custom environment
    let custom_env = Environment::Custom("wss://testnet.thalex.com/ws/api/v2".to_string());
    let custom_client = WsClient::new_public(custom_env).await.unwrap();
    println!("Custom client connected, shutting down...");
    custom_client
        .shutdown("Done with custom client!")
        .await
        .unwrap();

    Ok(())
}

Subscribing to Data Streams

Once you have a WsClient instance, you can subscribe to various data streams.

A callback based approach is used to handle incoming messages.

For example, to subscribe to ticker OHLC data:

// examples/subscribe_ticker.rs
use log::{Level::Info, info};
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use simple_logger::init_with_level;
use thalex_rust_sdk::{
    models::Delay,
    types::{Environment, ExternalEvent},
    ws_client::WsClient,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    init_with_level(Info).unwrap();

    let client = WsClient::new_public(Environment::Mainnet).await.unwrap();

    let instruments = client.rpc().market_data().instruments().await.unwrap();
    info!("Total Instruments: {}", instruments.len());

    let _ = client
        .subscriptions()
        .market_data()
        .ticker("BTC-PERPETUAL", Delay::Variant1000ms, |msg| {
            // Parses into a json value initally
            async move {
            let best_bid_price: Decimal = msg.best_bid_price.unwrap();
            let best_ask_price: Decimal = msg.best_ask_price.unwrap();
            let index_price = msg.index.unwrap();

            // Check if all non-optional fields are present
            let spread = best_ask_price - best_bid_price;

            let index_delta = msg.mark_price.unwrap() - index_price;
            let index_delta_bps = if index_price != dec!(0.0) {
                (index_delta / index_price) * dec!(10000.0)
            } else {
                dec!(0.0)
            };
            info!(
                "Ticker update - Bid: {best_bid_price}, Ask: {best_ask_price} spread: {spread} index: {index_price} index_delta_bps: {index_delta_bps}"
            );
        }
    })
        .await;

    client.wait_for_connection().await;
    info!("Starting receive loop!");
    loop {
        match client.run_till_event().await {
            ExternalEvent::Connected => {
                client.resubscribe_all().await.ok();
            }
            ExternalEvent::Disconnected => continue,
            ExternalEvent::Exited => break,
        }
    }
    client.shutdown("Time to go!").await.unwrap();
    Ok(())
}

Creating Orders

The SDK also provides support for authenticated endpoints, allowing you to manage your account and place orders.

// examples/create_order.rs
use thalex_rust_sdk::{
    models::{CancelParams, DirectionEnum, InsertParams, OrderTypeEnum},
    ws_client::WsClient,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    // Optionally set environment via env vars or modify WsClient::from_env for custom env
    let client = WsClient::from_env().await.unwrap();

    let order = client
        .rpc()
        .trading()
        .insert(InsertParams {
            direction: DirectionEnum::Buy,
            amount: rust_decimal_macros::dec!(0.0001),
            price: Some(rust_decimal_macros::dec!(50000.0)),
            instrument_name: Some("BTC-PERPETUAL".to_string()),
            order_type: Some(OrderTypeEnum::Limit),
            post_only: Some(true),
            reject_post_only: Some(true),
            ..Default::default()
        })
        .await
        .unwrap();

    println!("Order placed: {:?}", order);

    // cancel the order
    client
        .rpc()
        .trading()
        .cancel(CancelParams {
            order_id: Some(order.order_id.clone()),
            ..Default::default()
        })
        .await
        .unwrap();

    Ok(())
}

Examples

The SDK includes several example applications demonstrating its capabilities. You can find them in the examples directory. To run an example, use the following command:

bashcargo run --example <example_name> Replace <example_name> with the name of the example file (without the .rs extension).

Documentation

The client is generated automatically from the Thalex OpenAPI specification using openapi-generator-cli.

The api is fully documented and available here.

Roadmap

  • Initial release with WebSocket support for public data streams.
  • Add support for private data streams and authenticated endpoints.
  • Implement callback based event handling.
  • Improve error handling and reconnection logic.
  • Expand support for additional rpc endpoints.
    • market data
    • account management
    • trading
    • historical data
    • market maker protection
    • notifications
    • bot management
    • wallet operations
    • rfq management
  • Add more examples and documentation.

Contributing

Contributions are welcome! Please feel free to submit issues and pull requests on the GitHub repository.

License

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

Development

To build and test the SDK locally, clone the repository and run:

make test

This will run the test suite to ensure everything is working correctly.

For formatting and linting, use:

make fmt
make lint

Codegen is used to regenerate the API client from the OpenAPI specification. To do this, ensure you have openapi-generator-cli installed and run:

make all

This will update the generated code in the src/ directory.

Acknowledgements

This SDK is inspired by and builds upon the work of various open-source projects in the Rust ecosystem and the Thalex community. Special thanks to the team at Thalex for their support and for providing a robust API.

About

Rust client for the Thalex exchange.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages