use nautilus_bybit::{
common::enums::{BybitKlineInterval, BybitProductType},
http::{
client::BybitHttpClient,
query::{
BybitInstrumentsInfoParamsBuilder, BybitKlinesParamsBuilder, BybitTradesParamsBuilder,
},
},
};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
nautilus_common::logging::ensure_logging_initialized();
println!("=== Bybit HTTP Client Demo ===\n");
test_public_endpoints().await?;
let api_key = std::env::var("BYBIT_API_KEY").ok();
let api_secret = std::env::var("BYBIT_API_SECRET").ok();
if let (Some(key), Some(secret)) = (api_key, api_secret) {
println!("\n=== Testing Authenticated Endpoints ===");
test_authenticated_endpoints(&key, &secret).await?;
} else {
println!(
"\n[SKIP] Skipping authenticated endpoints (set BYBIT_API_KEY and BYBIT_API_SECRET to test)"
);
}
Ok(())
}
async fn test_public_endpoints() -> anyhow::Result<()> {
let client = BybitHttpClient::new(None, Some(60), None, None, None, None, None)?;
println!("1. Testing GET /v5/market/time");
match client.get_server_time().await {
Ok(response) => {
println!(
" [OK] Server time: {} (seconds)",
response.result.time_second
);
println!(" [OK] Server time: {} (nanos)", response.result.time_nano);
}
Err(e) => {
println!(" [ERROR] {e}");
return Err(e.into());
}
}
println!("\n2. Testing GET /v5/market/instruments-info (linear)");
let params = BybitInstrumentsInfoParamsBuilder::default()
.category(BybitProductType::Linear)
.symbol("BTCUSDT")
.build()?;
match client.get_instruments_linear(¶ms).await {
Ok(response) => {
println!(" [OK] Found {} instruments", response.result.list.len());
if let Some(first) = response.result.list.first() {
println!(" [OK] First instrument: {}", first.symbol);
println!(" [OK] Status: {:?}", first.status);
}
}
Err(e) => {
println!(" [ERROR] {e}");
return Err(e.into());
}
}
println!("\n3. Testing GET /v5/market/instruments-info (spot)");
let params = BybitInstrumentsInfoParamsBuilder::default()
.category(BybitProductType::Spot)
.limit(5u32)
.build()?;
match client.get_instruments_spot(¶ms).await {
Ok(response) => {
println!(" [OK] Found {} instruments", response.result.list.len());
for instrument in response.result.list.iter().take(3) {
println!(" - {}: {:?}", instrument.symbol, instrument.status);
}
}
Err(e) => {
println!(" [ERROR] {e}");
return Err(e.into());
}
}
println!("\n4. Testing GET /v5/market/kline");
let params = BybitKlinesParamsBuilder::default()
.category(BybitProductType::Linear)
.symbol("BTCUSDT")
.interval(BybitKlineInterval::Minute1)
.limit(5u32)
.build()?;
match client.get_klines(¶ms).await {
Ok(response) => {
println!(" [OK] Found {} klines", response.result.list.len());
if let Some(first) = response.result.list.first() {
println!(
" [OK] First kline: O={}, H={}, L={}, C={}",
first.open, first.high, first.low, first.close
);
}
}
Err(e) => {
println!(" [ERROR] {e}");
return Err(e.into());
}
}
println!("\n5. Testing GET /v5/market/recent-trade");
let params = BybitTradesParamsBuilder::default()
.category(BybitProductType::Linear)
.symbol("BTCUSDT")
.limit(5u32)
.build()?;
match client.get_recent_trades(¶ms).await {
Ok(response) => {
println!(" [OK] Found {} recent trades", response.result.list.len());
for trade in response.result.list.iter().take(3) {
println!(
" - Price: {}, Size: {}, Side: {:?}",
trade.price, trade.size, trade.side
);
}
}
Err(e) => {
println!(" [ERROR] {e}");
return Err(e.into());
}
}
println!("\n[SUCCESS] All public endpoint tests passed!");
Ok(())
}
async fn test_authenticated_endpoints(api_key: &str, api_secret: &str) -> anyhow::Result<()> {
let base_url = std::env::var("BYBIT_BASE_URL")
.unwrap_or_else(|_| "https://api-testnet.bybit.com".to_string());
let client = BybitHttpClient::with_credentials(
api_key.to_string(),
api_secret.to_string(),
Some(base_url),
Some(60),
None,
None,
None,
None,
None,
)?;
println!("\n1. Testing GET /v5/order/realtime (open orders)");
match client
.get_open_orders(
BybitProductType::Linear,
Some("BTCUSDT".to_owned()),
None,
None,
None,
None,
None,
None,
None,
None,
)
.await
{
Ok(response) => {
println!(" [OK] Found {} open orders", response.result.list.len());
for order in response.result.list.iter().take(3) {
println!(
" - Order: {} | {:?} | {} @ {}",
order.order_id, order.side, order.qty, order.price
);
}
}
Err(e) => {
println!(" [WARN] Error (may be expected if no orders): {e}");
}
}
println!("\n2. Testing POST /v5/order/create (order placement)");
println!(" [SKIP] Skipping actual order placement to avoid unintended trades");
println!(" [INFO] Uncomment in code to test order placement");
println!("\n[SUCCESS] Authenticated endpoint tests completed!");
Ok(())
}