dex_connector/
dex_request.rs1use 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}