polyte_data/
client.rs

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