use nautilus_bybit::{
common::{
credential::Credential,
enums::{BybitEnvironment, 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?;
if Credential::resolve(None, None, BybitEnvironment::Testnet).is_some() {
println!("\n=== Testing Authenticated Endpoints ===");
test_authenticated_endpoints().await?;
} else {
println!(
"\n[SKIP] Skipping authenticated endpoints (set BYBIT_TESTNET_API_KEY and BYBIT_TESTNET_API_SECRET to test)"
);
}
Ok(())
}
async fn test_public_endpoints() -> anyhow::Result<()> {
let client = BybitHttpClient::new(None, 60, 3, 1000, 10_000, 5_000, 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() -> anyhow::Result<()> {
let client = BybitHttpClient::new_with_env(
None, None, None, false, true, 60, 3, 1000, 10_000, 5_000, 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(())
}