1use polysqueeze::Result;
2use polysqueeze::client::ClobClient;
3use polysqueeze::errors::PolyError;
4use polysqueeze::types::{GammaListParams, Market};
5use polysqueeze::wss::{WssMarketClient, WssMarketEvent};
6use rust_decimal::Decimal;
7use std::env;
8use std::str::FromStr;
9use std::time::{SystemTime, UNIX_EPOCH};
10
11#[tokio::main]
12async fn main() -> Result<()> {
13 let base_url =
14 env::var("POLY_API_URL").unwrap_or_else(|_| "https://clob.polymarket.com".to_string());
15 let clob = ClobClient::new(&base_url);
16
17 let min_liquidity = env::var("POLY_WSS_MIN_LIQUIDITY")
18 .ok()
19 .and_then(|value| Decimal::from_str(&value).ok())
20 .unwrap_or_else(|| Decimal::from(1_000_000));
21
22 let params = GammaListParams {
23 limit: Some(50),
24 liquidity_num_min: Some(min_liquidity),
25 ..Default::default()
26 };
27
28 let response = clob.get_markets(None, Some(¶ms)).await?;
29 let market = pick_liquid_market(&response.data, min_liquidity)?;
30
31 println!(
32 "Selected market {} (liquidity={:?})",
33 market.condition_id, market.liquidity_num
34 );
35
36 let asset_ids = derive_asset_ids(market).unwrap_or_else(|| Vec::new());
37
38 if asset_ids.is_empty() {
39 return Err(PolyError::validation(
40 "failed to derive asset IDs for the selected market",
41 ));
42 }
43
44 let mut client = WssMarketClient::new();
45 client.subscribe(asset_ids.clone()).await?;
46
47 println!("Subscribed to market channel for assets={:?}", asset_ids);
48
49 for _ in 0..20 {
50 match client.next_event().await {
51 Ok(WssMarketEvent::PriceChange(change)) => {
52 println!(
53 "price_change for {}: {:?}",
54 change.market, change.price_changes
55 );
56 }
57 Ok(WssMarketEvent::Book(book)) => {
58 println!(
59 "book {} bids={} asks={}",
60 book.market,
61 book.bids.len(),
62 book.asks.len()
63 );
64 }
65 Ok(WssMarketEvent::TickSizeChange(change)) => {
66 println!(
67 "tick size change {} from {} to {}",
68 change.market, change.old_tick_size, change.new_tick_size
69 );
70 }
71 Ok(WssMarketEvent::LastTrade(trade)) => {
72 println!(
73 "last_trade {} {:?}@{}",
74 trade.market, trade.side, trade.price
75 );
76 }
77 Err(err) => {
78 eprintln!("stream error: {}", err);
79 break;
80 }
81 }
82 }
83
84 Ok(())
85}
86
87fn pick_liquid_market(markets: &[Market], min_liquidity: Decimal) -> Result<&Market> {
88 let eligible: Vec<&Market> = markets
89 .iter()
90 .filter(|m| m.liquidity_num.unwrap_or_default() >= min_liquidity)
91 .collect();
92
93 if eligible.is_empty() {
94 return Err(PolyError::validation("no liquid markets available"));
95 }
96
97 let seed = SystemTime::now()
98 .duration_since(UNIX_EPOCH)
99 .map(|d| d.as_nanos() as usize)
100 .unwrap_or(0);
101 let idx = seed % eligible.len();
102 Ok(eligible[idx])
103}
104
105fn derive_asset_ids(market: &Market) -> Option<Vec<String>> {
106 if !market.clob_token_ids.is_empty() {
107 return Some(market.clob_token_ids.clone());
108 }
109
110 let ids = market
111 .tokens
112 .iter()
113 .map(|token| token.token_id.clone())
114 .filter(|id| !id.is_empty())
115 .collect::<Vec<_>>();
116
117 if ids.is_empty() { None } else { Some(ids) }
118}