drm_exchange_polymarket/
client.rs1use reqwest::Client;
2use serde::de::DeserializeOwned;
3
4use crate::config::PolymarketConfig;
5use crate::error::PolymarketError;
6
7pub struct HttpClient {
8 client: Client,
9 gamma_url: String,
10 clob_url: String,
11 verbose: bool,
12}
13
14impl HttpClient {
15 pub fn new(config: &PolymarketConfig) -> Result<Self, PolymarketError> {
16 let client = Client::builder().timeout(config.base.timeout).build()?;
17
18 Ok(Self {
19 client,
20 gamma_url: config.gamma_url.clone(),
21 clob_url: config.clob_url.clone(),
22 verbose: config.base.verbose,
23 })
24 }
25
26 pub async fn get_gamma<T: DeserializeOwned>(
27 &self,
28 endpoint: &str,
29 ) -> Result<T, PolymarketError> {
30 let url = format!("{}{}", self.gamma_url, endpoint);
31 self.get(&url).await
32 }
33
34 pub async fn get_clob<T: DeserializeOwned>(
35 &self,
36 endpoint: &str,
37 ) -> Result<T, PolymarketError> {
38 let url = format!("{}{}", self.clob_url, endpoint);
39 self.get(&url).await
40 }
41
42 async fn get<T: DeserializeOwned>(&self, url: &str) -> Result<T, PolymarketError> {
43 if self.verbose {
44 tracing::debug!("GET {}", url);
45 }
46
47 let response = self.client.get(url).send().await?;
48 let status = response.status();
49
50 if status == 429 {
51 let retry_after = response
52 .headers()
53 .get("retry-after")
54 .and_then(|h| h.to_str().ok())
55 .and_then(|s| s.parse().ok())
56 .unwrap_or(1);
57 return Err(PolymarketError::RateLimited { retry_after });
58 }
59
60 if !status.is_success() {
61 let message = response.text().await.unwrap_or_default();
62 return Err(PolymarketError::Api(format!("{status}: {message}")));
63 }
64
65 let body = response.json().await?;
66 Ok(body)
67 }
68}