use std::time::Duration;
use crate::cli::common::write_json_output;
use clap::{Args, Subcommand};
use polymarket_hft::client::polymarket::rtds::{ClobAuth, RtdsClient, Subscription};
#[derive(Subcommand)]
pub enum RtdsCommands {
Subscribe {
#[command(flatten)]
params: SubscribeArgs,
},
}
#[derive(Args, Debug, Clone)]
pub struct SubscribeArgs {
#[arg(short, long, required = true)]
pub topic: String,
#[arg(short = 'T', long, default_value = "*")]
pub message_type: String,
#[arg(short, long)]
pub filter: Option<String>,
#[arg(long, env = "POLY_API_KEY")]
pub clob_key: Option<String>,
#[arg(long, env = "POLY_API_SECRET")]
pub clob_secret: Option<String>,
#[arg(long, env = "POLY_PASSPHRASE")]
pub clob_passphrase: Option<String>,
#[arg(short = 'n', long, default_value = "10")]
pub max_messages: usize,
#[arg(long, default_value = "60")]
pub timeout: u64,
#[arg(short, long, default_value = "json")]
pub output: String,
}
pub async fn handle(command: &RtdsCommands) -> anyhow::Result<()> {
match command {
RtdsCommands::Subscribe { params } => {
subscribe(params).await?;
}
}
Ok(())
}
async fn subscribe(params: &SubscribeArgs) -> anyhow::Result<()> {
let mut client = RtdsClient::builder().auto_reconnect(true).build();
eprintln!("Connecting to RTDS...");
client.connect().await?;
eprintln!("Connected!");
let mut subscription = Subscription::new(¶ms.topic, ¶ms.message_type);
if let Some(filter) = ¶ms.filter {
subscription = subscription.with_filter(filter);
}
if let (Some(key), Some(secret), Some(passphrase)) = (
¶ms.clob_key,
¶ms.clob_secret,
¶ms.clob_passphrase,
) {
subscription = subscription.with_clob_auth(ClobAuth::new(key, secret, passphrase));
}
eprintln!(
"Subscribing to topic={}, type={}...",
params.topic, params.message_type
);
client.subscribe(vec![subscription]).await?;
eprintln!("Subscribed! Waiting for messages...\n");
let timeout = if params.timeout > 0 {
Some(Duration::from_secs(params.timeout))
} else {
None
};
let start = std::time::Instant::now();
let mut count = 0;
loop {
#[allow(clippy::collapsible_if)]
if let Some(t) = timeout {
if start.elapsed() > t {
eprintln!("\nTimeout reached after {} seconds", params.timeout);
break;
}
}
if params.max_messages > 0 && count >= params.max_messages {
eprintln!("\nReached {} messages limit", params.max_messages);
break;
}
let msg_future = client.next_message();
let result = tokio::time::timeout(Duration::from_secs(5), msg_future).await;
match result {
Ok(Some(msg)) => {
count += 1;
if params.output == "compact" {
println!(
"[{}] {}/{}: {}",
msg.timestamp,
msg.topic,
msg.message_type,
serde_json::to_string(&msg.payload)?
);
} else {
write_json_output(&msg)?;
}
}
Ok(None) => {
eprintln!("Connection closed");
break;
}
Err(_) => {
continue;
}
}
}
eprintln!("\nReceived {} messages total", count);
client.disconnect().await;
Ok(())
}