use std::time::Duration;
use polynode::{OrderbookEngine, EngineOptions, PolyNodeClient};
const DEFAULT_KEY: &str = "pn_live_test_session_tracking_51eca107e9b347b589f5b0a04f98eb1d";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = std::env::args().nth(1).unwrap_or_else(|| DEFAULT_KEY.to_string());
println!("=== PolyNode SDK — Batch Orderbook API ===\n");
let client = PolyNodeClient::new(&api_key)?;
let markets = client.markets(Some(8)).await?;
let token_ids: Vec<String> = markets
.markets
.iter()
.filter_map(|m| m.token_id.clone())
.take(5)
.collect();
if token_ids.is_empty() {
return Err("no token IDs returned from /v1/markets — cannot exercise orderbook batch API".into());
}
println!("subscribing to {} tokens:", token_ids.len());
for t in &token_ids {
println!(" {}", t);
}
let engine = OrderbookEngine::connect(&api_key, EngineOptions::default()).await?;
engine.subscribe(token_ids.clone()).await?;
println!("\nwaiting 3s for snapshots...");
tokio::time::sleep(Duration::from_secs(3)).await;
println!("\ntracked_tokens: {}", engine.tracked_tokens().await.len());
let mids_all = engine.midpoints_all().await;
println!("\nmidpoints_all ({} entries):", mids_all.len());
for (id, m) in &mids_all {
println!(" {} midpoint={:.4}", short(id), m);
}
let spreads_all = engine.spreads_all().await;
println!("\nspreads_all ({} entries):", spreads_all.len());
for (id, s) in &spreads_all {
println!(" {} spread={:.4}", short(id), s);
}
let bids_for_3 = engine.best_bids(&token_ids[..3.min(token_ids.len())]).await;
println!("\nbest_bids(first 3) -> {} entries", bids_for_3.len());
let books_one = engine.books(&token_ids[..1]).await;
println!("\nbooks(first 1):");
if let Some((bids, asks)) = books_one.values().next() {
println!(" bids: {} levels (top: {:?})", bids.len(), bids.first());
println!(" asks: {} levels (top: {:?})", asks.len(), asks.first());
} else {
println!(" (no book yet — snapshot still in flight)");
}
let stale_short = engine.inactive_since(Duration::from_secs(10)).await;
println!("\ninactive_since(10s): {} (expected 0 right after fresh snapshots)", stale_short.len());
let stale_zero = engine.inactive_since(Duration::from_millis(1)).await;
println!("inactive_since(1ms): {} (expected ~all)", stale_zero.len());
println!("\nstate() handle — direct read lock:");
let state = engine.state();
let guard = state.read().await;
println!(" tracked: {}", guard.len());
for token in guard.tracked_tokens().iter().take(3) {
if let Some(ts) = guard.last_change(token) {
println!(" {} last_change={:?} ago", short(token), ts.elapsed());
}
}
drop(guard);
engine.close().await?;
println!("\ndone.");
Ok(())
}
fn short(id: &str) -> String {
if id.len() > 16 {
format!("{}…{}", &id[..8], &id[id.len() - 8..])
} else {
id.to_string()
}
}