dydx_v3_rust/modules/
eth_private.rs1pub use super::super::types::*;
2use super::super::{ResponseError, Result};
3use super::eth_sign::*;
4use chrono::Utc;
5use http::{Method, StatusCode};
6use serde::Deserialize;
7use std::time::Duration;
8
9#[derive(Debug, Clone)]
10pub struct EthPrivate<'a> {
11 client: reqwest::Client,
12 host: &'a str,
13 network_id: usize,
14 eth_private_key: &'a str,
15}
16
17impl EthPrivate<'_> {
18 pub fn new<'a>(host: &'a str, network_id: usize, api_timeout: u64, eth_private_key: &'a str) -> EthPrivate<'a> {
19 EthPrivate {
20 client: reqwest::ClientBuilder::new()
21 .timeout(Duration::from_secs(api_timeout))
22 .build()
23 .expect("Client::new()"),
24 host,
25 network_id,
26 eth_private_key,
27 }
28 }
29
30 pub async fn recovery(&self, ethereum_address: &str) -> Result<RecoveryResponse> {
31 let response = self
32 .request("recovery", Method::GET, ethereum_address)
33 .await;
34 response
35 }
36
37 pub async fn create_api_key(
38 &self,
39 ethereum_address: &str,
40 ) -> Result<ApiKeyCredentialsResponse> {
41 let response = self
42 .request("api-keys", Method::POST, ethereum_address)
43 .await;
44 response
45 }
46
47 pub async fn delete_api_key(
48 &self,
49 api_key: &str,
50 ethereum_address: &str,
51 ) -> Result<StatusCode> {
52 let parameter = vec![("apiKey", api_key)];
53 let response = self.delete("api-keys", ethereum_address, parameter).await;
54 response
55 }
56
57 async fn request<T: for<'de> Deserialize<'de>>(
58 &self,
59 path: &str,
60 method: Method,
61 ethereum_address: &str,
62 ) -> Result<T> {
63 let iso_timestamp = Utc::now().format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string();
64
65 let request_path = format!("/v3/{}", path);
66
67 let signature = sign_private(
68 self.network_id,
69 ethereum_address,
70 method.as_str(),
71 request_path.as_str(),
72 "{}",
73 &iso_timestamp,
74 self.eth_private_key,
75 )
76 .unwrap();
77
78 let url = format!("{}/v3/{}", &self.host, path);
79
80 let req_builder = match method {
81 Method::GET => self.client.get(url),
82 Method::POST => self.client.post(url),
83 _ => self.client.get(url),
84 };
85
86 let req_builder = req_builder
87 .header("DYDX-SIGNATURE", signature.as_str())
88 .header("DYDX-TIMESTAMP", iso_timestamp.as_str())
89 .header("DYDX-ETHEREUM-ADDRESS", ethereum_address);
90
91 let response = req_builder.send().await;
92
93 match response {
94 Ok(response) => match response.status() {
95 StatusCode::OK | StatusCode::CREATED => {
96 return Ok(response.json::<T>().await.unwrap())
97 }
98 _ => {
99 let error = ResponseError {
100 code: response.status().to_string(),
101 message: response.text().await.unwrap(),
102 };
103 return Err(Box::new(error));
104 }
105 },
106 Err(err) => {
107 return Err(Box::new(err));
108 }
109 };
110 }
111
112 async fn delete(
113 &self,
114 path: &str,
115 ethereum_address: &str,
116 parameters: Vec<(&str, &str)>,
117 ) -> Result<StatusCode> {
118 let request_path = if parameters.len() == 0 {
119 format!("/v3/{}", &path)
120 } else {
121 let request_path = format!("/v3/{}", &path);
122 let dummy_url = reqwest::Url::parse_with_params("https://example.net", ¶meters);
123 format!("{}?{}", request_path, dummy_url.unwrap().query().unwrap())
124 };
125 let iso_timestamp = Utc::now().format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string();
126
127 let signature = sign_private(
128 self.network_id,
129 ethereum_address,
130 "DELETE",
131 request_path.as_str(),
132 "{}",
133 &iso_timestamp,
134 self.eth_private_key,
135 )
136 .unwrap();
137
138 let url = format!("{}/v3/{}", &self.host, path);
139
140 let req_builder = self.client.delete(url);
141
142 let req_builder = req_builder
143 .header("DYDX-SIGNATURE", signature.as_str())
144 .header("DYDX-TIMESTAMP", iso_timestamp.as_str())
145 .header("DYDX-ETHEREUM-ADDRESS", ethereum_address)
146 .query(¶meters);
147
148 let response = req_builder.send().await;
149
150 Ok(response.unwrap().status())
151 }
152}