ndaxrs
======
Unofficial Rust bindings for the NDAX exchange WebSocket API.
This library provides a Rust client for NDAX market data and trading over WebSockets, with a synchronous API surface that is easy to integrate into CLI apps, bots, and services.
- Strongly typed requests and responses via [`serde`](https://docs.rs/serde/latest/serde/)
- WebSocket transport via [`tokio-tungstenite`](https://docs.rs/tokio-tungstenite/latest/tokio_tungstenite/)
- NDAX HMAC authentication support for private endpoints
- Decimal-safe price/quantity handling via [`rust_decimal`](https://docs.rs/rust_decimal/latest/rust_decimal/)
- Builder-based config for feeds, auth, depth, and gateway URL
- Logging support via [`log`](https://docs.rs/log/latest/log/)
- `.env` loading support via [`dotenvy`](https://docs.rs/dotenvy/latest/dotenvy/)
Both public and private APIs are supported. Current coverage focuses on the endpoints needed for market data, account balances, open orders, placing orders, and canceling orders.
If something you need is missing, patches are welcome.
Capabilities
------------
`ndaxrs` currently includes:
- Public market data subscriptions:
- Level1 (ticker)
- Level2 (order book)
- Trades
- Private/authenticated workflows:
- Authenticate user
- Subscribe account events
- Get account positions
- Get open orders
- Send order
- Cancel order
Threading
---------
`NdaxWsAPI` is a blocking/synchronous interface that spawns an internal worker thread and drives an async WebSocket client behind the scenes.
Architecture:
```text
User Code
|
v
NdaxWsAPI (sync)
|
v mpsc channel
Worker Thread (tokio runtime)
|
v
NdaxWsClient (async)
|
v
NDAX WebSocket Gateway
```
This keeps application code simple for most use-cases while still using async I/O internally.
Quick Start
-----------
Add dependency:
```toml
[dependencies]
ndaxrs = "0.1.0" # or: { path = "../ndaxrs" }
```
### Public market data
```rust,no_run
use ndaxrs::ws::{NdaxWsAPI, NdaxWsConfig};
use std::{thread, time::Duration};
fn main() -> ndaxrs::Result<()> {
let instrument_id = 1; // BTC/CAD on NDAX
let config = NdaxWsConfig::builder()
.subscribe_level1(vec![instrument_id])
.subscribe_level2(vec![instrument_id])
.subscribe_trades(vec![instrument_id])
.book_depth(20)
.build();
let api = NdaxWsAPI::new(config)?;
thread::sleep(Duration::from_secs(2));
if let Some(level1) = api.get_level1(instrument_id) {
println!(
"last={} bid={} ask={} vol={}",
level1.last_price, level1.best_bid, level1.best_ask, level1.volume
);
}
if let Some(book) = api.get_book(instrument_id) {
println!("best bid: {:?}", book.best_bid());
println!("best ask: {:?}", book.best_ask());
}
if let Some(trades) = api.get_trades(instrument_id) {
println!("recent trades: {}", trades.len());
}
api.close();
Ok(())
}
```
### Authenticated trading
```rust,no_run
use ndaxrs::messages::orders::create_limit_order;
use ndaxrs::ws::{NdaxWsAPI, NdaxWsConfig, PrivateConfig};
use ndaxrs::{NdaxCredentials, Side};
use rust_decimal::Decimal;
use std::str::FromStr;
fn main() -> ndaxrs::Result<()> {
let creds = NdaxCredentials::from_env()?;
let account_id: u64 = std::env::var("NDAX_ACCOUNT_ID")
.expect("NDAX_ACCOUNT_ID must be set")
.parse()
.expect("NDAX_ACCOUNT_ID must be a u64");
let config = NdaxWsConfig::builder()
.credentials(creds)
.private(PrivateConfig::new(account_id).with_account_events())
.build();
let api = NdaxWsAPI::new(config)?;
assert!(api.is_authenticated(), "authentication failed");
let order = create_limit_order(
1, // instrument_id
account_id,
Side::Buy,
Decimal::from_str("0.0001").unwrap(),
Decimal::from_str("1.00").unwrap(), // intentionally far from market
);
let resp = api.send_order(&order)?;
println!("order response: status={}, order_id={:?}", resp.status, resp.order_id);
api.close();
Ok(())
}
```
Environment Variables
---------------------
For authenticated APIs, `NdaxCredentials::from_env()` reads:
- `NDAX_API_KEY`
- `NDAX_API_SECRET`
- `NDAX_USER_ID`
For private account operations and the trading example:
- `NDAX_ACCOUNT_ID`
Examples
--------
Library examples:
- `cargo run --example public_data`
- `cargo run --example trading`
The `trading` example performs real authenticated operations and submits a test order. Use a funded account with caution.
TUI example app:
```bash
cd examples/ndax-tui
cp .env.example .env
cargo run
```
`ndax-tui` shows:
- Live Level2 order book
- Price chart driven by Level1 updates
- Latest market trades
- Latest user trades (when authenticated)
Disclaimer
----------
Use at your own risk. If you build trading software with this library and incur losses due to bugs, connectivity issues, or exchange behavior, you are responsible for validating and monitoring your system.
Reference
---------
- [NDAX API Documentation](https://apidoc.ndax.io/)