dex_connector/
dex_request.rs

1use debot_utils::ParseDecimalError;
2use reqwest::{
3    header::{HeaderMap, HeaderValue},
4    Client, Method,
5};
6use serde::Serialize;
7use std::{
8    collections::HashMap,
9    error::Error as StdError,
10    fmt::{self, Display},
11};
12
13pub enum HttpMethod {
14    Get,
15    Post,
16    Put,
17    Delete,
18}
19
20impl From<HttpMethod> for Method {
21    fn from(method: HttpMethod) -> Self {
22        match method {
23            HttpMethod::Get => Method::GET,
24            HttpMethod::Post => Method::POST,
25            HttpMethod::Put => Method::PUT,
26            HttpMethod::Delete => Method::DELETE,
27        }
28    }
29}
30
31#[derive(Clone, Debug)]
32pub struct DexRequest {
33    client: Client,
34    endpoint: String,
35}
36
37#[derive(Debug)]
38pub enum DexError {
39    Serde(serde_json::Error),
40    Reqwest(reqwest::Error),
41    ServerResponse(String),
42    WebSocketError(String),
43    Other(String),
44    NoConnection,
45    UpcomingMaintenance,
46    ApiKeyRegistrationRequired,
47}
48
49impl From<ParseDecimalError> for DexError {
50    fn from(e: ParseDecimalError) -> Self {
51        DexError::Other(format!("{:?}", e))
52    }
53}
54
55impl Display for DexError {
56    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57        match *self {
58            DexError::Serde(ref e) => write!(f, "Serde JSON error: {}", e),
59            DexError::Reqwest(ref e) => write!(f, "Reqwest error: {}", e),
60            DexError::ServerResponse(ref e) => write!(f, "Server response error: {}", e),
61            DexError::Other(ref e) => write!(f, "Other error: {}", e),
62            DexError::NoConnection => write!(f, "No running WebSocketConnection"),
63            DexError::WebSocketError(ref e) => write!(f, "WebSocket error: {}", e),
64            DexError::UpcomingMaintenance => write!(f, "Network upgrade scheduled in < 2h"),
65            DexError::ApiKeyRegistrationRequired => write!(f, "API key registration is required"),
66        }
67    }
68}
69
70impl StdError for DexError {
71    fn source(&self) -> Option<&(dyn StdError + 'static)> {
72        match *self {
73            DexError::Serde(ref e) => Some(e),
74            DexError::Reqwest(ref e) => Some(e),
75            DexError::ServerResponse(_) => None,
76            DexError::Other(_) => None,
77            DexError::NoConnection => None,
78            DexError::WebSocketError(_) => None,
79            DexError::UpcomingMaintenance => None,
80            DexError::ApiKeyRegistrationRequired => None,
81        }
82    }
83}
84
85impl From<reqwest::Error> for DexError {
86    fn from(error: reqwest::Error) -> Self {
87        DexError::Reqwest(error)
88    }
89}
90
91impl DexRequest {
92    pub async fn new(endpoint: String) -> Result<Self, DexError> {
93        let client = Client::builder().cookie_store(true).build()?;
94
95        Ok(DexRequest { client, endpoint })
96    }
97
98    pub async fn handle_request<T: serde::de::DeserializeOwned, U: Serialize + ?Sized>(
99        &self,
100        method: HttpMethod,
101        request_url: String,
102        headers: &HashMap<String, String>,
103        json_payload: String,
104    ) -> Result<T, DexError> {
105        let url = format!("{}{}", self.endpoint, request_url);
106
107        let mut header_map = HeaderMap::new();
108        header_map.insert(
109            reqwest::header::CONTENT_TYPE,
110            HeaderValue::from_static("application/json"),
111        );
112
113        for (key, value) in headers.iter() {
114            let key = reqwest::header::HeaderName::from_bytes(key.as_bytes())
115                .expect("Failed to create HeaderName");
116            let value = HeaderValue::from_str(value).expect("Failed to create HeaderValue");
117            header_map.insert(key, value);
118        }
119
120        let client = self.client.clone();
121        let request_builder = client
122            .request(Method::from(method), &url)
123            .headers(header_map);
124
125        log::trace!("payload = {}", json_payload);
126
127        let request_builder = if !json_payload.is_empty() {
128            request_builder.body(json_payload.clone())
129        } else {
130            request_builder
131        };
132
133        let response = request_builder.send().await.map_err(DexError::from)?;
134        let status = response.status();
135
136        if !status.is_success() {
137            let error_message =
138                format!("Server returned error: {}. requested url: {}", status, url);
139            log::error!("{}", &error_message);
140        }
141
142        let response_headers = response.headers().clone();
143        log::trace!("Response header: {:?}", response_headers);
144
145        let response_body = response.text().await.map_err(DexError::from)?;
146        log::trace!("Response body: {}", response_body);
147
148        serde_json::from_str(&response_body).map_err(|e| {
149            log::error!(
150                "Failed to deserialize response: {}, payload = {}",
151                e,
152                json_payload
153            );
154            DexError::Serde(e)
155        })
156    }
157}