Skip to main content

limitless/
markets.rs

1use crate::prelude::*;
2
3/// Provides access to public market data on the Limitless Exchange.
4///
5/// No authentication is required for these endpoints. Use this manager
6/// to browse active markets, fetch details, search, get oracle data,
7/// and retrieve feed events.
8#[derive(Clone)]
9pub struct Markets {
10    pub client: Client,
11}
12
13impl Markets {
14    /// Browse all active (unresolved) markets.
15    ///
16    /// Supports optional filtering by category, trade type, and automation type
17    /// with pagination via `page` and `limit`.
18    pub async fn browse_active(
19        &self,
20        category_id: Option<u64>,
21        page: Option<u64>,
22        limit: Option<u64>,
23        sort_by: Option<String>,
24        trade_type: Option<String>,
25        automation_type: Option<String>,
26    ) -> Result<ActiveMarketsResponse, LimitlessError> {
27        let mut params = BTreeMap::new();
28        if let Some(v) = page {
29            params.insert("page".into(), v.to_string());
30        }
31        if let Some(v) = limit {
32            params.insert("limit".into(), v.to_string());
33        }
34        if let Some(ref v) = sort_by {
35            params.insert("sortBy".into(), v.clone());
36        }
37        if let Some(ref v) = trade_type {
38            params.insert("tradeType".into(), v.clone());
39        }
40        if let Some(ref v) = automation_type {
41            params.insert("automationType".into(), v.clone());
42        }
43        let request = build_request(&params);
44
45        let path = if let Some(cat_id) = category_id {
46            format!("markets/active/{}", cat_id)
47        } else {
48            "markets/active".to_string()
49        };
50
51        self.client.get(&path, Some(request)).await
52    }
53
54    /// Get the count of active markets per category.
55    pub async fn get_category_counts(&self) -> Result<CategoryCountResponse, LimitlessError> {
56        self.client.get("markets/categories/count", None).await
57    }
58
59    /// Get all active market slugs with metadata (strike price, ticker, deadline).
60    pub async fn get_active_slugs(&self) -> Result<Vec<ActiveSlug>, LimitlessError> {
61        self.client.get("markets/active/slugs", None).await
62    }
63
64    /// Get detailed market information by address or slug.
65    ///
66    /// Returns venue data (`exchange` and `adapter` addresses) needed for
67    /// EIP-712 order signing on CLOB markets.
68    pub async fn get_market(&self, address_or_slug: &str) -> Result<MarketDetail, LimitlessError> {
69        let path = format!("markets/{}", address_or_slug);
70        self.client.get(&path, None).await
71    }
72
73    /// Get Chainlink oracle candlestick data for markets with Data Streams.
74    pub async fn get_oracle_candles(
75        &self,
76        address_or_slug: &str,
77        interval: Option<&str>,
78        from: Option<u64>,
79        to: Option<u64>,
80    ) -> Result<OracleCandlesResponse, LimitlessError> {
81        let mut params = BTreeMap::new();
82        if let Some(ref v) = interval {
83            params.insert("interval".into(), v.to_string());
84        }
85        if let Some(v) = from {
86            params.insert("from".into(), v.to_string());
87        }
88        if let Some(v) = to {
89            params.insert("to".into(), v.to_string());
90        }
91        let request = build_request(&params);
92        let path = format!("markets/{}/oracle-candles", address_or_slug);
93        self.client.get(&path, Some(request)).await
94    }
95
96    /// Get feed events (trades, orders, liquidity changes) for a specific market.
97    pub async fn get_feed_events(
98        &self,
99        slug: &str,
100        page: Option<u64>,
101        limit: Option<u64>,
102    ) -> Result<FeedEventsResponse, LimitlessError> {
103        let mut params = BTreeMap::new();
104        if let Some(v) = page {
105            params.insert("page".into(), v.to_string());
106        }
107        if let Some(v) = limit {
108            params.insert("limit".into(), v.to_string());
109        }
110        let request = build_request(&params);
111        let path = format!("markets/{}/get-feed-events", slug);
112        self.client.get(&path, Some(request)).await
113    }
114
115    /// Semantic search for markets using natural language queries.
116    ///
117    /// Supports configurable similarity threshold and pagination.
118    pub async fn search(
119        &self,
120        query: &str,
121        limit: Option<u64>,
122        page: Option<u64>,
123        similarity_threshold: Option<f64>,
124    ) -> Result<SearchResponse, LimitlessError> {
125        let mut params = BTreeMap::new();
126        params.insert("query".into(), query.to_string());
127        if let Some(v) = limit {
128            params.insert("limit".into(), v.to_string());
129        }
130        if let Some(v) = page {
131            params.insert("page".into(), v.to_string());
132        }
133        if let Some(v) = similarity_threshold {
134            params.insert("similarityThreshold".into(), v.to_string());
135        }
136        let request = build_request(&params);
137        self.client.get("markets/search", Some(request)).await
138    }
139}
140
141impl Limitless for Markets {
142    fn new(api_key: Option<String>, secret: Option<String>) -> Self {
143        Self::new_with_config(&Config::default(), api_key, secret)
144    }
145
146    fn new_with_config(config: &Config, api_key: Option<String>, secret: Option<String>) -> Self {
147        Self {
148            client: Client::new(api_key, secret, config.rest_api_endpoint.to_string()),
149        }
150    }
151}