polyoxide_gamma/
client.rs1use polyoxide_core::{
2 HttpClient, HttpClientBuilder, RateLimiter, RetryConfig, DEFAULT_POOL_SIZE, DEFAULT_TIMEOUT_MS,
3};
4
5use crate::{
6 api::{
7 comments::Comments, events::Events, health::Health, markets::Markets, series::Series,
8 sports::Sports, tags::Tags, user::User,
9 },
10 error::GammaError,
11};
12
13const DEFAULT_BASE_URL: &str = "https://gamma-api.polymarket.com";
14
15#[derive(Clone)]
17pub struct Gamma {
18 pub(crate) http_client: HttpClient,
19}
20
21impl Gamma {
22 pub fn new() -> Result<Self, GammaError> {
24 Self::builder().build()
25 }
26
27 pub fn builder() -> GammaBuilder {
29 GammaBuilder::new()
30 }
31
32 pub fn markets(&self) -> Markets {
34 Markets {
35 http_client: self.http_client.clone(),
36 }
37 }
38
39 pub fn events(&self) -> Events {
41 Events {
42 http_client: self.http_client.clone(),
43 }
44 }
45
46 pub fn series(&self) -> Series {
48 Series {
49 http_client: self.http_client.clone(),
50 }
51 }
52
53 pub fn tags(&self) -> Tags {
55 Tags {
56 http_client: self.http_client.clone(),
57 }
58 }
59
60 pub fn sports(&self) -> Sports {
62 Sports {
63 http_client: self.http_client.clone(),
64 }
65 }
66
67 pub fn comments(&self) -> Comments {
69 Comments {
70 http_client: self.http_client.clone(),
71 }
72 }
73
74 pub fn user(&self) -> User {
76 User {
77 http_client: self.http_client.clone(),
78 }
79 }
80
81 pub fn health(&self) -> Health {
83 Health {
84 http_client: self.http_client.clone(),
85 }
86 }
87}
88
89pub struct GammaBuilder {
91 base_url: String,
92 timeout_ms: u64,
93 pool_size: usize,
94 retry_config: Option<RetryConfig>,
95}
96
97impl GammaBuilder {
98 fn new() -> Self {
99 Self {
100 base_url: DEFAULT_BASE_URL.to_string(),
101 timeout_ms: DEFAULT_TIMEOUT_MS,
102 pool_size: DEFAULT_POOL_SIZE,
103 retry_config: None,
104 }
105 }
106
107 pub fn base_url(mut self, url: impl Into<String>) -> Self {
109 self.base_url = url.into();
110 self
111 }
112
113 pub fn timeout_ms(mut self, timeout: u64) -> Self {
115 self.timeout_ms = timeout;
116 self
117 }
118
119 pub fn pool_size(mut self, size: usize) -> Self {
121 self.pool_size = size;
122 self
123 }
124
125 pub fn with_retry_config(mut self, config: RetryConfig) -> Self {
127 self.retry_config = Some(config);
128 self
129 }
130
131 pub fn build(self) -> Result<Gamma, GammaError> {
133 let mut builder = HttpClientBuilder::new(&self.base_url)
134 .timeout_ms(self.timeout_ms)
135 .pool_size(self.pool_size)
136 .with_rate_limiter(RateLimiter::gamma_default());
137 if let Some(config) = self.retry_config {
138 builder = builder.with_retry_config(config);
139 }
140 let http_client = builder.build()?;
141
142 Ok(Gamma { http_client })
143 }
144}
145
146impl Default for GammaBuilder {
147 fn default() -> Self {
148 Self::new()
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155
156 #[test]
157 fn test_builder_default() {
158 let builder = GammaBuilder::default();
159 assert_eq!(builder.base_url, DEFAULT_BASE_URL);
160 assert_eq!(builder.timeout_ms, DEFAULT_TIMEOUT_MS);
161 assert_eq!(builder.pool_size, DEFAULT_POOL_SIZE);
162 }
163
164 #[test]
165 fn test_builder_custom_url() {
166 let builder = GammaBuilder::new().base_url("https://custom.api.com");
167 assert_eq!(builder.base_url, "https://custom.api.com");
168 }
169
170 #[test]
171 fn test_builder_custom_timeout() {
172 let builder = GammaBuilder::new().timeout_ms(60_000);
173 assert_eq!(builder.timeout_ms, 60_000);
174 }
175
176 #[test]
177 fn test_builder_custom_pool_size() {
178 let builder = GammaBuilder::new().pool_size(20);
179 assert_eq!(builder.pool_size, 20);
180 }
181
182 #[test]
183 fn test_builder_custom_retry_config() {
184 let config = RetryConfig {
185 max_retries: 5,
186 initial_backoff_ms: 1000,
187 max_backoff_ms: 30_000,
188 };
189 let builder = GammaBuilder::new().with_retry_config(config);
190 let config = builder.retry_config.unwrap();
191 assert_eq!(config.max_retries, 5);
192 assert_eq!(config.initial_backoff_ms, 1000);
193 }
194
195 #[test]
196 fn test_builder_build_success() {
197 let gamma = Gamma::builder().build();
198 assert!(gamma.is_ok());
199 }
200
201 #[test]
202 fn test_builder_invalid_url() {
203 let result = Gamma::builder().base_url("://bad").build();
204 assert!(result.is_err());
205 }
206
207 #[test]
208 fn test_new_creates_client() {
209 let gamma = Gamma::new();
210 assert!(gamma.is_ok());
211 }
212
213 #[test]
214 fn test_client_namespaces_accessible() {
215 let gamma = Gamma::new().unwrap();
216 let _markets = gamma.markets();
217 let _events = gamma.events();
218 let _series = gamma.series();
219 let _tags = gamma.tags();
220 let _sports = gamma.sports();
221 let _comments = gamma.comments();
222 let _user = gamma.user();
223 let _health = gamma.health();
224 }
225}