Rust
Async signed-request helper plus a public WebSocket subscription.
Cargo dependencies
[dependencies]
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
hmac = "0.12"
sha2 = "0.10"
hex = "0.4"
serde_json = "1"
tokio = { version = "1", features = ["full"] }
urlencoding = "2"
uuid = { version = "1", features = ["v4"] }
tokio-tungstenite = { version = "0.23", features = ["rustls-tls-webpki-roots"] }
futures-util = "0.3"REST
// src/zdex.rs
use hmac::{Hmac, Mac};
use sha2::Sha256;
use serde_json::Value;
use std::time::{SystemTime, UNIX_EPOCH};
type HmacSha256 = Hmac<Sha256>;
const API_KEY: &str = "zd_84444a6e...";
const SECRET: &str = "073CuVWk...";
const BASE_URL: &str = "https://api.zetariumdex.com";
pub async fn signed_request(
method: reqwest::Method,
path: &str,
params: &[(&str, &str)],
body: Option<&Value>,
) -> reqwest::Result<Value> {
let ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis()
.to_string();
let mut all: Vec<(&str, String)> =
params.iter().map(|(k, v)| (*k, v.to_string())).collect();
all.push(("timestamp", ts));
all.sort_by(|a, b| a.0.cmp(b.0));
let qs: String = all
.iter()
.map(|(k, v)| format!("{}={}", urlencoding::encode(k), urlencoding::encode(v)))
.collect::<Vec<_>>()
.join("&");
let mut mac = HmacSha256::new_from_slice(SECRET.as_bytes()).unwrap();
mac.update(qs.as_bytes());
let sig = hex::encode(mac.finalize().into_bytes());
let url = format!("{BASE_URL}{path}?{qs}&signature={sig}");
let mut req = reqwest::Client::new()
.request(method, &url)
.header("X-API-KEY", API_KEY);
if let Some(b) = body {
req = req.json(b);
}
req.send().await?.json().await
}Usage
// src/main.rs
use serde_json::json;
use uuid::Uuid;
#[tokio::main]
async fn main() -> reqwest::Result<()> {
// 1. Read futures balance
let balance = signed_request(reqwest::Method::GET, "/v2/futures/balance", &[], None).await?;
println!("{balance}");
// 2. Idempotent LIMIT BUY
let body = json!({
"symbol": "BTCUSDT",
"side": "BUY",
"type": "LIMIT",
"quantity": "0.001",
"price": "30000",
"clientOrderId": Uuid::new_v4().to_string(),
});
let order = signed_request(reqwest::Method::POST, "/v2/orders", &[], Some(&body)).await?;
println!("{order}");
Ok(())
}WebSocket — public ticker
use futures_util::{SinkExt, StreamExt};
use tokio_tungstenite::tungstenite::Message;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (mut ws, _) =
tokio_tungstenite::connect_async("wss://api.zetariumdex.com/ws").await?;
ws.send(Message::Text(
serde_json::json!({
"action": "subscribe",
"channel": "ticker",
"symbol": "BTCUSDT",
})
.to_string(),
))
.await?;
while let Some(Ok(msg)) = ws.next().await {
if let Message::Text(txt) = msg {
println!("{txt}");
}
}
Ok(())
}