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}
47
48impl From<ParseDecimalError> for DexError {
49    fn from(e: ParseDecimalError) -> Self {
50        DexError::Other(format!("{:?}", e))
51    }
52}
53
54impl Display for DexError {
55    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56        match *self {
57            DexError::Serde(ref e) => write!(f, "Serde JSON error: {}", e),
58            DexError::Reqwest(ref e) => write!(f, "Reqwest error: {}", e),
59            DexError::ServerResponse(ref e) => write!(f, "Server response error: {}", e),
60            DexError::Other(ref e) => write!(f, "Other error: {}", e),
61            DexError::NoConnection => write!(f, "No running WebSocketConnection"),
62            DexError::WebSocketError(ref e) => write!(f, "WebSocket error: {}", e),
63            DexError::UpcomingMaintenance => write!(f, "Network upgrade scheduled in < 2h"),
64        }
65    }
66}
67
68impl StdError for DexError {
69    fn source(&self) -> Option<&(dyn StdError + 'static)> {
70        match *self {
71            DexError::Serde(ref e) => Some(e),
72            DexError::Reqwest(ref e) => Some(e),
73            DexError::ServerResponse(_) => None,
74            DexError::Other(_) => None,
75            DexError::NoConnection => None,
76            DexError::WebSocketError(_) => None,
77            DexError::UpcomingMaintenance => None,
78        }
79    }
80}
81
82impl From<reqwest::Error> for DexError {
83    fn from(error: reqwest::Error) -> Self {
84        DexError::Reqwest(error)
85    }
86}
87
88impl DexRequest {
89    pub async fn new(endpoint: String) -> Result<Self, DexError> {
90        let client = Client::builder().cookie_store(true).build()?;
91
92        Ok(DexRequest { client, endpoint })
93    }
94
95    pub async fn handle_request<T: serde::de::DeserializeOwned, U: Serialize + ?Sized>(
96        &self,
97        method: HttpMethod,
98        request_url: String,
99        headers: &HashMap<String, String>,
100        json_payload: String,
101    ) -> Result<T, DexError> {
102        let url = format!("{}{}", self.endpoint, request_url);
103
104        let mut header_map = HeaderMap::new();
105        header_map.insert(
106            reqwest::header::CONTENT_TYPE,
107            HeaderValue::from_static("application/json"),
108        );
109
110        for (key, value) in headers.iter() {
111            let key = reqwest::header::HeaderName::from_bytes(key.as_bytes())
112                .expect("Failed to create HeaderName");
113            let value = HeaderValue::from_str(value).expect("Failed to create HeaderValue");
114            header_map.insert(key, value);
115        }
116
117        let client = self.client.clone();
118        let request_builder = client
119            .request(Method::from(method), &url)
120            .headers(header_map);
121
122        log::trace!("payload = {}", json_payload);
123
124        let request_builder = if !json_payload.is_empty() {
125            request_builder.body(json_payload.clone())
126        } else {
127            request_builder
128        };
129
130        let response = request_builder.send().await.map_err(DexError::from)?;
131        let status = response.status();
132
133        if !status.is_success() {
134            let error_message =
135                format!("Server returned error: {}. requested url: {}", status, url);
136            log::error!("{}", &error_message);
137        }
138
139        let response_headers = response.headers().clone();
140        log::trace!("Response header: {:?}", response_headers);
141
142        let response_body = response.text().await.map_err(DexError::from)?;
143        log::trace!("Response body: {}", response_body);
144
145        serde_json::from_str(&response_body).map_err(|e| {
146            log::error!(
147                "Failed to deserialize response: {}, payload = {}",
148                e,
149                json_payload
150            );
151            DexError::Serde(e)
152        })
153    }
154}