Rust SDK

Encrypted Rust client for the GoDark API. Crate name: godark.

Requirements: Rust 2021, tokio
Status: Beta — clone the public examples repo to get started.

Get the SDK

Clone gdx-rust-sdk-examples. The repo vendors the godark crate under sdk/ so no private crates registry is required:

git clone https://github.com/gq-godark/gdx-rust-sdk-examples.git
cd gdx-rust-sdk-examples
cp .env.example .env
# set GODARK_API_KEY_ID, GODARK_API_SECRET, GODARK_PASSPHRASE

cargo build --release --examples
cargo run --release --example quickstart
cargo run --release --example full_trader_example

You can also point an LLM / coding agent at the cloned repo and ask it to build a strategy using your credentials in .env. See the repo README for full setup, examples, and packaging details.

Public crates.io release is not yet available; until then this repo is the supported distribution.

Quickstart

Set credentials, then place a limit order over encrypted WebSocket (GodarkClient). Subscribe to orders before placing so book confirmation can wait on private updates. Limit prices must stay near the oracle or the venue rejects — see Error Codes.

use godark::{Environment, GodarkClient, OrderType, Side, TimeInForce};

const SYMBOL: &str = "BTC-USDC-PERP";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut builder = GodarkClient::builder()
        .environment(Environment::the configured host)
        .api_key_id(std::env::var("GODARK_API_KEY_ID")?)
        .api_secret(std::env::var("GODARK_API_SECRET")?)
        .passphrase(std::env::var("GODARK_PASSPHRASE")?);
    if let Ok(base_url) = std::env::var("GODARK_EDGE_URL") {
        if !base_url.trim().is_empty() {
            builder = builder.base_url(base_url.trim());
        }
    }

    let mut client = GodarkClient::new(builder.build()?);
    client.connect().await?;
    client.subscribe(&["orders"]).await?;

    let ack = client
        .place_order(
            SYMBOL,
            Side::Sell,
            OrderType::Limit,
            "0.01",
            Some("68000"), // within ~10% of oracle
            TimeInForce::Gtc,
            false,
            None,
            None,
        )
        .await?;
    println!("placed {}", ack.order_id);

    tokio::time::sleep(std::time::Duration::from_millis(500)).await;
    let cancel = client.cancel_order(&ack.order_id, SYMBOL).await?;
    println!("cancelled {}", cancel.order_id);

    client.disconnect().await;
    Ok(())
}

See WebSocket Trading and Place Order for request fields.

Clients

TypeDescription
GodarkClientWebSocket trading + order/position streams on /ws/v1
GodarkRestClientBearer-authenticated REST trading, order lookup, leverage, account/position snapshots, and public-market queries; trading bodies use one-shot HPKE
MarketDataClientPublic market snapshots on /ws/v1 by default; set GODARK_MARKET_DATA_USE_GOMARKET=1 or GODARK_MARKET_DATA_WS_URL to opt in to /ws/gomarket order-book feeds

Build GodarkClient with the builder pattern: .api_key_id(), .api_secret(), .passphrase(), .environment(). With that key triple, both clients mint POST /api/v1/auth/token (client_credentials) first. WebSocket login uses the returned access_token — the secret is never sent on the socket. A legacy opaque api_key (for example a custom host test-key-*) is still sent as-is for login. GodarkRestClient places / cancels / modifies with bearer + one-shot HPKE. GodarkClient uses a sealed HPKE WebSocket session for the same ops. A WebSocket place that sets PlaceOrderOptions::client_order_id registers that id immediately after the place ack: POST /api/v1/orders/_register_coid with the header correlation id as a decimal u128, the client order id, and the decimal order id. The SDK writes its process-local map only after HTTP 200 and returns the 400 when the edge rejects the register. REST place leaves the id unregistered — the edge arms place correlation only for WebSocket Place, so the same POST returns 400 unknown place correlation. get_order_by_client_id / cancel_order_by_client_id query GET /api/v1/orders?client_order_id= when that local map is empty. Public place / modify / mass-quote / batch-modify / TP-SL APIs take decimal strings only for prices and sizes (&str / String / Option<String> — for example "0.01", Some("68000")). There is no public f64 / f32 / integer price or size input and no format_decimal / parse_decimal helper; invalid strings (empty, negative, exponent form, non-numeric, over instrument precision) are rejected by normalize_decimal against price_decimals / quantity_decimals. The same string form is sealed on the wire (PlaceOrderInput.price field 23, quantity field 24, and the same for modify / mass-quote / triggers / TP-SL / quote_notional / min_fill_size).

Environment::the configured host is the hosted default; Environment::the configured host selects the configured host and Environment::a custom host uses the configured local edge. Rust expects a ws:// or wss:// edge URL, upgrades a trailing /ws, and otherwise appends /ws/v1. A trailing /ws or /ws/v1 is stripped when that same URL is used to mint the REST access token, so login hits the HTTP origin. Non-2xx REST responses (including an empty 405 on GET /api/v1/leverage) surface as HTTP <status> instead of a JSON parse error. get_order / await_terminal_status fill status from the decrypted open-orders snapshot, a local terminal ack, or GET /api/v1/orders/history when the edge returns an encrypted pointer or HTTP 403. An unknown trading-channel name fails the subscribe call immediately. See Base URLs.

GodarkClient methods

MethodDocs reference
connect() / disconnect()Authentication, Encryption
subscribe(...)WebSocket Trading
place_order(...)Place Order, WebSocket Trading
cancel_order(...)Cancel Order
modify_order(...)Modify Order
mass_quote(...)Mass Quote
batch_cancel(...)Cancel Order
take_order_receiver()Orders Channel
take_open_orders_snapshot_receiver()Orders Channel — full open_orders_snapshot on orders subscribe and later encrypted pushes
take_positions_snapshot_receiver()Positions Channel
take_balance_receiver() / take_account_margin_receiver()Plaintext account_update (quote risk)
take_funding_rate_receiver()funding_rate subscribe snapshot
take_system_health_receiver()Cleartext system_health / health_report when the edge emits one
take_leverage_settings_receiver()Encrypted leverage settings after update_leverage
take_error_receiver() / take_reconnect_receiver()Asynchronous error and reconnect lifecycle streams

Types and errors

Exported types include Environment, Side, OrderType, TimeInForce, OrderStatus, OrderUpdateType, PositionUpdateType, CancelReason, OrderAck, OrderUpdate, and PositionUpdate. The HPKE login conn_id is u64.

Methods return Result<T, GodarkError>. The enum variants are Authentication(String), Session(String), Order { message, error_code: Option<String>, user_message: Option<String> }, Connection(String), Encryption(String), Timeout(String), Config(String), InvalidInput(String), WebSocket(tungstenite::Error), and Proto(prost::DecodeError). Rust delivers asynchronous errors and updates through Tokio receivers; it does not expose callback registration for these streams.

Environment variables: OS GODARK_*, then OS GDX_*, then .env GODARK_*, then .env GDX_*. The process environment always wins over .env. Quickstart snippets use the canonical GODARK_* names.

Bundled examples

Runnable samples in the examples repo: quickstart (connect → subscribe → place → cancel) and full_trader_example (modify, mass quote, batch cancel) — cargo run --release --example <name>.

See also


Shared trading fields

Prices, sizes, quote notional, trigger, take-profit, and stop-loss are decimal strings.

Place options (names follow each language): reduce_only, post_only, stp_mode (UNSPECIFIED, CANCEL_RESTING, CANCEL_AGGRESSOR, CANCEL_BOTH), quote_notional, peg_offset_bps, trigger_price, take_profit_price, stop_loss_price, slippage_bps, client_order_id.

confirmation: ack returns on the sequencer acknowledgement. book waits for a terminal private order update until the place timeout.

Time in force: GTC, IOC, FOK, GTD. Order types: MARKET, LIMIT, PEG, STOP_MARKET, STOP_LIMIT. Side: BUY, SELL.

Mass quote: 1 to 20 legs. Each leg has side, price, quantity, optional cancel_order_id, time_in_force, expiry_time. post_only omitted uses the venue default.

Batch modify legs: order_id plus at least one of new_price, new_quantity.

WebSocket implements cancel-all, close-all, reverse, and TP/SL amend or cancel. REST implements one-shot encrypted place, cancel, modify, mass quote, batch cancel, batch modify, plus snapshots. REST does not implement cancel-all, close-all, reverse, or TP/SL amend.

A WebSocket place that sets client_order_id registers it after the ack. REST leaves that id unregistered.

Errors: authentication, session, connection, encryption, timeout, and order rejection with a numeric code and symbolic name. See Error Codes.

Rust reference

GodarkClient::builder() and GodarkRestClient::builder() then build(). Builder methods: environment, api_key, api_key_id, api_secret, passphrase, base_url or rest_base_url, account, hpke_static_public_key_hex, symbol, and for the socket transport, auto_reconnect, place_order_terminal_timeout.

GodarkConfig fields: auth_token, base_url, auto_reconnect, symbol_map, transport, account, hpke_static_public_key_hex.

TransportConfig: tls_skip_verify, extra_headers, connect_timeout, command_timeout, stale_timeout, heartbeat_interval, missed_heartbeat_limit.

Socket methods return Result<_, GodarkError>: connect, disconnect, logout, place_order, place_order_with_options, cancel_order, modify_order, update_leverage, cancel_all_orders, close_all, reverse_position, amend_tpsl, cancel_tpsl, mass_quote, batch_cancel, batch_modify, subscribe, unsubscribe.

take_*_receiver yields a one-shot channel for orders, positions, open orders, health, balance, funding, account margin, leverage, errors, and reconnect.

REST adds get_order, get_order_by_client_id, cancel_order_by_client_id, get_leverage, get_open_orders, get_positions, get_account, get_funding_rates, get_open_interest, get_volume, get_me (session token), await_terminal_status.

GodarkError variants: Authentication, Session, Order, Connection, Encryption, Timeout, Config, InvalidInput, WebSocket, Proto.

MarketDataClient::new(base_url) subscribes to the order book, trades, or a public channel and emits JSON values.