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#[derive(Clone)]
24pub struct DataApi {
25 pub(crate) client: Client,
26 pub(crate) base_url: Url,
27}
28
29impl DataApi {
30 pub fn new() -> Result<Self> {
32 Self::builder().build()
33 }
34
35 pub fn builder() -> DataApiBuilder {
37 DataApiBuilder::new()
38 }
39
40 pub fn health(&self) -> Health {
42 Health {
43 client: self.client.clone(),
44 base_url: self.base_url.clone(),
45 }
46 }
47
48 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 pub fn positions(&self, user_address: impl Into<String>) -> UserApi {
59 self.user(user_address)
60 }
61
62 pub fn traded(&self, user_address: impl Into<String>) -> Traded {
64 Traded {
65 user_api: self.user(user_address),
66 }
67 }
68
69 pub fn trades(&self) -> Trades {
71 Trades {
72 client: self.client.clone(),
73 base_url: self.base_url.clone(),
74 }
75 }
76
77 pub fn holders(&self) -> Holders {
79 Holders {
80 client: self.client.clone(),
81 base_url: self.base_url.clone(),
82 }
83 }
84
85 pub fn open_interest(&self) -> OpenInterestApi {
87 OpenInterestApi {
88 client: self.client.clone(),
89 base_url: self.base_url.clone(),
90 }
91 }
92
93 pub fn live_volume(&self) -> LiveVolumeApi {
95 LiveVolumeApi {
96 client: self.client.clone(),
97 base_url: self.base_url.clone(),
98 }
99 }
100}
101
102pub 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 pub fn base_url(mut self, url: impl Into<String>) -> Self {
120 self.base_url = url.into();
121 self
122 }
123
124 pub fn timeout_ms(mut self, timeout: u64) -> Self {
126 self.timeout_ms = timeout;
127 self
128 }
129
130 pub fn pool_size(mut self, size: usize) -> Self {
132 self.pool_size = size;
133 self
134 }
135
136 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
155pub struct Traded {
157 user_api: UserApi,
158}
159
160impl Traded {
161 pub async fn get(self) -> std::result::Result<UserTraded, DataApiError> {
163 self.user_api.traded().await
164 }
165}