Skip to main content

limitless/
navigation.rs

1use crate::prelude::*;
2
3/// Provides access to the Limitless Exchange market navigation system.
4///
5/// Includes the hierarchical navigation tree, market page resolution,
6/// property keys/options, and page-specific market listings.
7/// All endpoints are public (no authentication required).
8#[derive(Clone)]
9pub struct Navigation {
10    pub client: Client,
11}
12
13impl Navigation {
14    /// Get the full hierarchical navigation tree for market pages.
15    pub async fn get_navigation_tree(&self) -> Result<Vec<NavigationNode>, LimitlessError> {
16        self.client.get("navigation", None).await
17    }
18
19    /// Resolve a URL path to a market page configuration.
20    ///
21    /// Returns the page's filter groups, breadcrumb, and metadata.
22    /// Supports home page resolution via `path=/`.
23    pub async fn get_page_by_path(&self, path: &str) -> Result<MarketPage, LimitlessError> {
24        let mut params = BTreeMap::new();
25        params.insert("path".into(), path.to_string());
26        let request = build_request(&params);
27        self.client.get("market-pages/by-path", Some(request)).await
28    }
29
30    /// List markets belonging to a specific market page.
31    ///
32    /// Supports both offset and cursor pagination. Use `__home__` as the
33    /// page ID for the home page when not explicitly configured.
34    pub async fn list_page_markets(
35        &self,
36        page_id: &str,
37        cursor: Option<&str>,
38        page: Option<u64>,
39        limit: Option<u64>,
40        sort_by: Option<&str>,
41        filters: Option<&BTreeMap<String, String>>,
42    ) -> Result<PageMarketsResponse, LimitlessError> {
43        let mut params = BTreeMap::new();
44        if let Some(ref v) = cursor {
45            params.insert("cursor".into(), v.to_string());
46        }
47        if let Some(v) = page {
48            params.insert("page".into(), v.to_string());
49        }
50        if let Some(v) = limit {
51            params.insert("limit".into(), v.to_string());
52        }
53        if let Some(ref v) = sort_by {
54            params.insert("sortBy".into(), v.to_string());
55        }
56        if let Some(f) = filters {
57            for (k, v) in f {
58                params.insert(k.clone(), v.clone());
59            }
60        }
61        let request = build_request(&params);
62        let path = format!("market-pages/{}/markets", page_id);
63        self.client.get(&path, Some(request)).await
64    }
65
66    /// List all property keys with their options (sorted by slug).
67    pub async fn list_property_keys(&self) -> Result<Vec<PropertyKey>, LimitlessError> {
68        self.client.get("property-keys", None).await
69    }
70
71    /// Get a specific property key by ID, including its options.
72    pub async fn get_property_key(&self, key_id: &str) -> Result<PropertyKey, LimitlessError> {
73        let path = format!("property-keys/{}", key_id);
74        self.client.get(&path, None).await
75    }
76
77    /// List options for a specific property key, optionally filtered by parent.
78    pub async fn list_property_options(
79        &self,
80        key_id: &str,
81        parent_id: Option<&str>,
82    ) -> Result<Vec<PropertyOption>, LimitlessError> {
83        let mut params = BTreeMap::new();
84        if let Some(ref v) = parent_id {
85            params.insert("parentId".into(), v.to_string());
86        }
87        let request = build_request(&params);
88        let path = format!("property-keys/{}/options", key_id);
89        self.client.get(&path, Some(request)).await
90    }
91}
92
93impl Limitless for Navigation {
94    fn new(api_key: Option<String>, secret: Option<String>) -> Self {
95        Self::new_with_config(&Config::default(), api_key, secret)
96    }
97
98    fn new_with_config(config: &Config, api_key: Option<String>, secret: Option<String>) -> Self {
99        Self {
100            client: Client::new(api_key, secret, config.rest_api_endpoint.to_string()),
101        }
102    }
103}