polyte_data/
client.rs

1use std::time::Duration;
2
3use reqwest::Client;
4use url::Url;
5
6use crate::{
7    api::{
8        health::Health,
9        holders::Holders,
10        live_volume::LiveVolumeApi,
11        open_interest::OpenInterestApi,
12        trades::Trades,
13        users::{UserApi, UserTraded},
14    },
15    error::{DataApiError, Result},
16};
17
18const DEFAULT_BASE_URL: &str = "https://data-api.polymarket.com";
19const DEFAULT_TIMEOUT_MS: u64 = 30_000;
20const DEFAULT_POOL_SIZE: usize = 10;
21
22/// Main Data API client
23#[derive(Clone)]
24pub struct DataApi {
25    pub(crate) client: Client,
26    pub(crate) base_url: Url,
27}
28
29impl DataApi {
30    /// Create a new Data API client with default configuration
31    pub fn new() -> Result<Self> {
32        Self::builder().build()
33    }
34
35    /// Create a builder for configuring the client
36    pub fn builder() -> DataApiBuilder {
37        DataApiBuilder::new()
38    }
39
40    /// Get health namespace
41    pub fn health(&self) -> Health {
42        Health {
43            client: self.client.clone(),
44            base_url: self.base_url.clone(),
45        }
46    }
47
48    /// Get user namespace for user-specific operations
49    pub fn user(&self, user_address: impl Into<String>) -> UserApi {
50        UserApi {
51            client: self.client.clone(),
52            base_url: self.base_url.clone(),
53            user_address: user_address.into(),
54        }
55    }
56
57    /// Alias for `user()` - for backwards compatibility
58    pub fn positions(&self, user_address: impl Into<String>) -> UserApi {
59        self.user(user_address)
60    }
61
62    /// Get traded namespace for backwards compatibility
63    pub fn traded(&self, user_address: impl Into<String>) -> Traded {
64        Traded {
65            user_api: self.user(user_address),
66        }
67    }
68
69    /// Get trades namespace
70    pub fn trades(&self) -> Trades {
71        Trades {
72            client: self.client.clone(),
73            base_url: self.base_url.clone(),
74        }
75    }
76
77    /// Get holders namespace
78    pub fn holders(&self) -> Holders {
79        Holders {
80            client: self.client.clone(),
81            base_url: self.base_url.clone(),
82        }
83    }
84
85    /// Get open interest namespace
86    pub fn open_interest(&self) -> OpenInterestApi {
87        OpenInterestApi {
88            client: self.client.clone(),
89            base_url: self.base_url.clone(),
90        }
91    }
92
93    /// Get live volume namespace
94    pub fn live_volume(&self) -> LiveVolumeApi {
95        LiveVolumeApi {
96            client: self.client.clone(),
97            base_url: self.base_url.clone(),
98        }
99    }
100}
101
102/// Builder for configuring Data API client
103pub struct DataApiBuilder {
104    base_url: String,
105    timeout_ms: u64,
106    pool_size: usize,
107}
108
109impl DataApiBuilder {
110    fn new() -> Self {
111        Self {
112            base_url: DEFAULT_BASE_URL.to_string(),
113            timeout_ms: DEFAULT_TIMEOUT_MS,
114            pool_size: DEFAULT_POOL_SIZE,
115        }
116    }
117
118    /// Set base URL for the API
119    pub fn base_url(mut self, url: impl Into<String>) -> Self {
120        self.base_url = url.into();
121        self
122    }
123
124    /// Set request timeout in milliseconds
125    pub fn timeout_ms(mut self, timeout: u64) -> Self {
126        self.timeout_ms = timeout;
127        self
128    }
129
130    /// Set connection pool size
131    pub fn pool_size(mut self, size: usize) -> Self {
132        self.pool_size = size;
133        self
134    }
135
136    /// Build the Data API client
137    pub fn build(self) -> Result<DataApi> {
138        let client = Client::builder()
139            .timeout(Duration::from_millis(self.timeout_ms))
140            .pool_max_idle_per_host(self.pool_size)
141            .build()?;
142
143        let base_url = Url::parse(&self.base_url)?;
144
145        Ok(DataApi { client, base_url })
146    }
147}
148
149impl Default for DataApiBuilder {
150    fn default() -> Self {
151        Self::new()
152    }
153}
154
155/// Wrapper for backwards compatibility with traded() API
156pub struct Traded {
157    user_api: UserApi,
158}
159
160impl Traded {
161    /// Get total markets traded by the user
162    pub async fn get(self) -> std::result::Result<UserTraded, DataApiError> {
163        self.user_api.traded().await
164    }
165}