Files
zeekay fae0efeb1b chore: normalize naming to LX across codebase
Apply consistent naming conventions throughout:
- Standardize product name to "LX" in documentation
- Update README files and API documentation
- Apply linter fixes to all source files
- Update Hummingbot connector documentation
2025-12-11 21:04:37 -08:00

173 lines
5.5 KiB
Rust

//! Basic trading example for LX.
//!
//! Demonstrates:
//! - Connecting to WebSocket
//! - Authentication
//! - Subscribing to market data
//! - Placing and canceling orders
//! - Handling events
use lux_dex::{Client, ClientConfig, Order, Side, WsEvent};
use std::env;
use tracing::{info, warn};
#[tokio::main]
async fn main() -> lux_dex::Result<()> {
// Initialize logging
tracing_subscriber::fmt::init();
// Configuration from environment or defaults
let ws_url = env::var("LX_WS_URL").unwrap_or_else(|_| "ws://localhost:8081".into());
let http_url = env::var("LX_HTTP_URL").unwrap_or_else(|_| "http://localhost:8080".into());
let api_key = env::var("LX_API_KEY").ok();
let api_secret = env::var("LX_API_SECRET").ok();
let mut config = ClientConfig::default()
.with_ws_url(&ws_url)
.with_http_url(&http_url);
if let (Some(key), Some(secret)) = (api_key, api_secret) {
config = config.with_credentials(key, secret);
}
// Create client
let client = Client::with_config(config);
// Take event receiver before connecting
let mut events = client.take_event_receiver().await.unwrap();
// Connect to WebSocket
info!("Connecting to {}", ws_url);
client.connect().await?;
// Spawn event handler
let event_handle = tokio::spawn(async move {
while let Some(event) = events.recv().await {
match event {
WsEvent::Connected { client_id } => {
info!("Connected with client_id: {}", client_id);
}
WsEvent::Authenticated { user_id } => {
info!("Authenticated as user: {}", user_id);
}
WsEvent::OrderBook(book) => {
info!(
"Order book {}: bid={:?} ask={:?} spread={:?}",
book.symbol,
book.best_bid(),
book.best_ask(),
book.spread()
);
}
WsEvent::Trade(trade) => {
info!(
"Trade: {} {} @ {} (value: {})",
trade.symbol,
trade.size,
trade.price,
trade.value()
);
}
WsEvent::OrderUpdate { order, status } => {
info!(
"Order update: {} {} {} @ {} - {}",
order.order_id.unwrap_or(0),
order.side,
order.size,
order.price,
status
);
}
WsEvent::Position(pos) => {
info!(
"Position: {} {} size={} entry={} pnl={}",
pos.symbol, pos.side, pos.size, pos.entry_price, pos.unrealized_pnl
);
}
WsEvent::Price { symbol, price } => {
info!("Price update: {} = {}", symbol, price);
}
WsEvent::Error { message, request_id } => {
warn!("Error: {} (request: {:?})", message, request_id);
}
WsEvent::Pong => {
info!("Pong received");
}
_ => {}
}
}
});
// Wait for connection
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
// Authenticate if credentials are configured
if client.is_connected() {
info!("Attempting authentication...");
client.authenticate_configured().await.ok();
}
// Subscribe to market data
info!("Subscribing to BTC-USDT order book");
client.subscribe_orderbook("BTC-USDT").await?;
info!("Subscribing to ETH-USDT trades");
client.subscribe_trades("ETH-USDT").await?;
// Get order book via HTTP
info!("Fetching order book via HTTP...");
match client.get_orderbook("BTC-USDT", 10).await {
Ok(book) => {
info!(
"HTTP Order book: {} levels, mid={:?}",
book.bids.len() + book.asks.len(),
book.mid_price()
);
// Demonstrate slippage estimation
if let Some(avg_price) = book.estimate_buy_slippage(1.0) {
info!("Estimated buy price for 1 BTC: {}", avg_price);
}
}
Err(e) => {
warn!("Failed to fetch order book: {}", e);
}
}
// Place a test order (only if authenticated)
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
if client.is_authenticated() {
info!("Placing test limit order...");
let order = Order::limit("BTC-USDT", Side::Buy, 45000.0, 0.001)
.with_client_id("rust-sdk-test-001")
.post_only();
client.place_order(&order).await?;
info!("Order placed");
// Wait for confirmation
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
}
// Ping to keep connection alive
client.ping().await?;
// Run for a while to receive events
info!("Listening for events... (press Ctrl+C to exit)");
tokio::select! {
_ = tokio::signal::ctrl_c() => {
info!("Shutting down...");
}
_ = event_handle => {
info!("Event handler finished");
}
}
// Disconnect
client.disconnect().await?;
info!("Disconnected");
Ok(())
}