A pure Rust SDK for Lighter DEX - a zk-powered perpetual futures exchange on Hyperliquid.
- Pure Rust - No external
.sofiles or FFI dependencies required - Complete API Coverage - HTTP REST API and WebSocket streaming
- Transaction Signing - Built-in ECgFp5/Poseidon2 cryptographic signing
- Thread-safe - Concurrent nonce management with atomic operations
- Async/Await - Built on tokio for high-performance async operations
Add this to your Cargo.toml:
[dependencies]
lighter-sdk = "0.1"use lighter_sdk::{LighterClient, LighterSigner};
use rust_decimal_macros::dec;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create a signer with your API key
let signer = LighterSigner::new(
"your_private_key_hex", // 40-byte hex string
0, // api_key_index
12345, // account_index
true, // is_mainnet
)?;
// Create a client
let client = LighterClient::mainnet(signer);
// Sync nonce from API (required before placing orders)
client.sync_nonce().await?;
// Get account info
let account = client.get_account_info().await?;
println!("Balance: {}", account.available_balance);
// Place a limit order
let response = client.place_limit_order(
"HYPE", // symbol
dec!(25.50), // price
dec!(100.0), // quantity
true, // is_buy (true = buy, false = sell)
false, // reduce_only
).await?;
println!("Order placed: {:?}", response);
Ok(())
}use lighter_sdk::LighterWebSocket;
use tokio::sync::mpsc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let ws = LighterWebSocket::mainnet();
// Create channel for orderbook updates
let (tx, mut rx) = mpsc::unbounded_channel();
// Subscribe to orderbook updates (symbol, market_id, sender)
// Note: Get market_id from client.get_market_info() or API
ws.subscribe_orderbook("HYPE".to_string(), 24, tx).await?;
// Receive updates
while let Some(update) = rx.recv().await {
println!("Best bid: {}, Best ask: {}",
update.best_bid, update.best_ask);
}
Ok(())
}Transaction signing with ECgFp5 elliptic curve and Poseidon2 hash.
let signer = LighterSigner::new(
api_key_private, // 40-byte hex private key
api_key_index, // API key index (u8)
account_index, // Account index (i64)
is_mainnet, // true for mainnet, false for testnet
)?;
// Get public key
println!("Public key: {}", signer.public_key_hex());
// Create auth token for private APIs
let token = signer.create_auth_token(3600)?; // 1 hour validityHTTP client for Lighter API.
// Create client
let client = LighterClient::mainnet(signer);
// or
let client = LighterClient::testnet(signer);
// Sync nonce (required before placing orders)
client.sync_nonce().await?;
// Account operations
let account = client.get_account_info().await?;
let position = client.get_position("HYPE").await?;
// Market data
let market = client.get_market_info("HYPE").await?;
let (bid, ask) = client.get_best_prices("HYPE").await?;
// Order operations
client.place_limit_order(symbol, price, quantity, is_buy, reduce_only).await?;
client.place_market_order(symbol, quantity, is_buy, reduce_only, slippage_price).await?;
client.cancel_order(symbol, order_index).await?;
// Position operations
client.set_leverage(symbol, leverage, is_cross).await?;
client.close_position(symbol).await?;Real-time data streaming with automatic reconnection.
use tokio::sync::mpsc;
let ws = LighterWebSocket::mainnet();
// Public: Orderbook updates
let (tx, mut rx) = mpsc::unbounded_channel();
ws.subscribe_orderbook("HYPE".to_string(), market_id, tx).await?;
while let Some(update) = rx.recv().await {
println!("{}: {} / {}", update.symbol, update.best_bid, update.best_ask);
}
// Private: Fill notifications (requires auth)
let (fill_tx, mut fill_rx) = mpsc::unbounded_channel();
ws.subscribe_fills(account_index, auth_token, market_symbols, fill_tx).await?;
while let Some(fill) = fill_rx.recv().await {
println!("Filled: {} {} @ {}", fill.quantity, fill.symbol, fill.price);
}use lighter_sdk::OrderType;
OrderType::Limit // 0 - Limit order
OrderType::Market // 1 - Market order
OrderType::StopLoss // 2 - Stop loss
OrderType::StopLossLimit // 3 - Stop loss limit
OrderType::TakeProfit // 4 - Take profit
OrderType::TakeProfitLimit // 5 - Take profit limit
OrderType::TWAP // 6 - Time-weighted average priceuse lighter_sdk::TimeInForce;
TimeInForce::ImmediateOrCancel // 0 - IOC
TimeInForce::GoodTillTime // 1 - GTT
TimeInForce::PostOnly // 2 - Post onlyThe examples use these environment variables:
| Variable | Description | Required |
|---|---|---|
LIGHTER_API_KEY_PRIVATE |
40-byte hex private key | Yes |
LIGHTER_API_KEY_INDEX |
API key index (default: 0) | No |
LIGHTER_ACCOUNT_INDEX |
Account index | Yes |
LIGHTER_MAINNET |
"true" for mainnet, "false" for testnet | No |
Run the examples:
# Place orders - limit, market, close, cancel, set leverage, etc.
cargo run --example place_order -- --help
cargo run --example place_order -- limit buy HYPE 0.5 25.0
cargo run --example place_order -- market sell HYPE 0.5
cargo run --example place_order -- position
cargo run --example place_order -- account
# WebSocket orderbook streaming
cargo run --example websocket_orderbook
# Account fills/trades monitoring (requires authentication)
cargo run --example account_fills
# Basic usage - account info and market data
cargo run --example basic_usagelighter-sdk/
├── src/
│ ├── lib.rs # Public API exports
│ ├── client.rs # HTTP REST client
│ ├── signer.rs # Transaction signing
│ ├── websocket.rs # WebSocket streaming
│ ├── types.rs # Data types
│ ├── nonce.rs # Nonce management
│ └── crypto/ # Cryptographic primitives
│ ├── mod.rs
│ ├── goldilocks.rs # Goldilocks field
│ ├── gfp5.rs # Quintic extension
│ ├── poseidon2.rs # Poseidon2 hash
│ ├── ecgfp5.rs # Elliptic curve
│ └── schnorr.rs # Schnorr signatures
└── examples/
├── basic_usage.rs
├── place_order.rs
├── websocket_orderbook.rs
└── account_fills.rs
This SDK implements Lighter's transaction signing using:
- Goldilocks Field - 64-bit prime field (p = 2^64 - 2^32 + 1)
- GFp5 - Quintic extension field
- ECgFp5 - Elliptic curve for digital signatures
- Poseidon2 - Hash function for transaction hashing
- Schnorr Signatures - Digital signature scheme
All cryptographic operations are implemented in pure Rust without external dependencies.
MIT OR Apache-2.0