polynode 0.13.8

Rust SDK for the PolyNode API — real-time Polymarket data
Documentation
//! Subscription builder and types.

use serde::Serialize;

/// WebSocket subscription type presets.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum SubscriptionType {
    Settlements,
    Trades,
    Prices,
    Blocks,
    Wallets,
    Markets,
    LargeTrades,
    Global,
    Oracle,
    Chainlink,
}

/// Builder for creating a subscription with filters.
#[derive(Debug, Clone)]
pub struct Subscription {
    pub(crate) sub_type: SubscriptionType,
    pub(crate) filters: SubscriptionFilters,
}

#[derive(Debug, Clone, Default, Serialize)]
pub struct SubscriptionFilters {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub wallets: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tokens: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub slugs: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub condition_ids: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub side: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub min_size: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub max_size: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub event_types: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub snapshot_count: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub feeds: Option<Vec<String>>,
}

impl Subscription {
    pub fn new(sub_type: SubscriptionType) -> Self {
        Self {
            sub_type,
            filters: SubscriptionFilters::default(),
        }
    }

    pub fn wallets(mut self, wallets: Vec<String>) -> Self {
        self.filters.wallets = Some(wallets);
        self
    }

    pub fn tokens(mut self, tokens: Vec<String>) -> Self {
        self.filters.tokens = Some(tokens);
        self
    }

    pub fn slugs(mut self, slugs: Vec<String>) -> Self {
        self.filters.slugs = Some(slugs);
        self
    }

    pub fn condition_ids(mut self, ids: Vec<String>) -> Self {
        self.filters.condition_ids = Some(ids);
        self
    }

    pub fn side(mut self, side: &str) -> Self {
        self.filters.side = Some(side.to_string());
        self
    }

    pub fn status(mut self, status: &str) -> Self {
        self.filters.status = Some(status.to_string());
        self
    }

    pub fn min_size(mut self, size: f64) -> Self {
        self.filters.min_size = Some(size);
        self
    }

    pub fn max_size(mut self, size: f64) -> Self {
        self.filters.max_size = Some(size);
        self
    }

    pub fn event_types(mut self, types: Vec<String>) -> Self {
        self.filters.event_types = Some(types);
        self
    }

    pub fn snapshot_count(mut self, count: u64) -> Self {
        self.filters.snapshot_count = Some(count);
        self
    }

    pub fn feeds(mut self, feeds: Vec<String>) -> Self {
        self.filters.feeds = Some(feeds);
        self
    }

    /// Serialize to the JSON message format expected by the server.
    pub(crate) fn to_message(&self) -> serde_json::Value {
        let mut msg = serde_json::json!({
            "action": "subscribe",
            "type": self.sub_type,
        });
        let filters = serde_json::to_value(&self.filters).unwrap_or_default();
        if let serde_json::Value::Object(ref m) = filters {
            if !m.is_empty() {
                msg["filters"] = filters;
            }
        }
        msg
    }
}