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#[derive(Clone)]
25pub struct DataApi {
26 pub(crate) client: Client,
27 pub(crate) base_url: Url,
28}
29
30impl DataApi {
31 pub fn new() -> Result<Self> {
33 Self::builder().build()
34 }
35
36 pub fn builder() -> DataApiBuilder {
38 DataApiBuilder::new()
39 }
40
41 pub fn health(&self) -> Health {
43 Health {
44 client: self.client.clone(),
45 base_url: self.base_url.clone(),
46 }
47 }
48
49 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 pub fn positions(&self, user_address: impl Into<String>) -> UserApi {
60 self.user(user_address)
61 }
62
63 pub fn traded(&self, user_address: impl Into<String>) -> Traded {
65 Traded {
66 user_api: self.user(user_address),
67 }
68 }
69
70 pub fn trades(&self) -> Trades {
72 Trades {
73 client: self.client.clone(),
74 base_url: self.base_url.clone(),
75 }
76 }
77
78 pub fn holders(&self) -> Holders {
80 Holders {
81 client: self.client.clone(),
82 base_url: self.base_url.clone(),
83 }
84 }
85
86 pub fn open_interest(&self) -> OpenInterestApi {
88 OpenInterestApi {
89 client: self.client.clone(),
90 base_url: self.base_url.clone(),
91 }
92 }
93
94 pub fn live_volume(&self) -> LiveVolumeApi {
96 LiveVolumeApi {
97 client: self.client.clone(),
98 base_url: self.base_url.clone(),
99 }
100 }
101
102 pub fn builders(&self) -> BuildersApi {
104 BuildersApi {
105 client: self.client.clone(),
106 base_url: self.base_url.clone(),
107 }
108 }
109}
110
111pub 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 pub fn base_url(mut self, url: impl Into<String>) -> Self {
129 self.base_url = url.into();
130 self
131 }
132
133 pub fn timeout_ms(mut self, timeout: u64) -> Self {
135 self.timeout_ms = timeout;
136 self
137 }
138
139 pub fn pool_size(mut self, size: usize) -> Self {
141 self.pool_size = size;
142 self
143 }
144
145 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
164pub struct Traded {
166 user_api: UserApi,
167}
168
169impl Traded {
170 pub async fn get(self) -> std::result::Result<UserTraded, DataApiError> {
172 self.user_api.traded().await
173 }
174}