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
| Type | Description |
|---|---|
GodarkClient | WebSocket trading + order/position streams on /ws/v1 |
GodarkRestClient | Bearer-authenticated REST trading, order lookup, leverage, account/position snapshots, and public-market queries; trading bodies use one-shot HPKE |
MarketDataClient | Public 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
| Method | Docs 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.