1use crate::futures::auth::{SignRequestParams, SignRequestParamsKind};
2use chrono::Utc;
3
4pub mod auth;
5pub mod error;
6pub mod response;
7pub mod result;
8pub mod v1;
9
10#[cfg(feature = "ws")]
11pub mod ws;
12
13pub enum MexcFuturesApiEndpoint {
14 Base,
15 Custom(String),
16}
17
18impl AsRef<str> for MexcFuturesApiEndpoint {
19 fn as_ref(&self) -> &str {
20 match self {
21 MexcFuturesApiEndpoint::Base => "https://contract.mexc.com",
22 MexcFuturesApiEndpoint::Custom(endpoint) => endpoint,
23 }
24 }
25}
26
27pub struct MexcFuturesApiClient {
28 endpoint: MexcFuturesApiEndpoint,
29 reqwest_client: reqwest::Client,
30}
31
32impl MexcFuturesApiClient {
33 pub fn new(endpoint: MexcFuturesApiEndpoint) -> Self {
34 let reqwest_client = reqwest::Client::builder()
35 .build()
36 .expect("Failed to build reqwest client");
37 Self {
38 endpoint,
39 reqwest_client,
40 }
41 }
42
43 pub fn into_with_authentication(
44 self,
45 api_key: String,
46 secret_key: String,
47 ) -> MexcFuturesApiClientWithAuthentication {
48 MexcFuturesApiClientWithAuthentication::new(self.endpoint, api_key, secret_key)
49 }
50}
51
52impl Default for MexcFuturesApiClient {
53 fn default() -> Self {
54 Self::new(MexcFuturesApiEndpoint::Base)
55 }
56}
57
58pub struct MexcFuturesApiClientWithAuthentication {
59 endpoint: MexcFuturesApiEndpoint,
60 reqwest_client: reqwest::Client,
61 api_key: String,
62 secret_key: String,
63}
64
65impl MexcFuturesApiClientWithAuthentication {
66 pub fn new(endpoint: MexcFuturesApiEndpoint, api_key: String, secret_key: String) -> Self {
67 let _headers = reqwest::header::HeaderMap::new();
68 let reqwest_client = reqwest::Client::builder()
69 .build()
70 .expect("Failed to build reqwest client");
71 Self {
72 endpoint,
73 reqwest_client,
74 api_key,
75 secret_key,
76 }
77 }
78
79 fn get_auth_header_map<T>(
80 &self,
81 params: &T,
82 kind: SignRequestParamsKind,
83 ) -> Result<reqwest::header::HeaderMap, GetAuthHeaderMapError>
84 where
85 T: serde::Serialize,
86 {
87 let mut header_map = reqwest::header::HeaderMap::new();
88 header_map.insert(
89 "ApiKey",
90 self.api_key.parse().expect("Failed to parse api key"),
91 );
92 let now = Utc::now();
93 header_map.insert(
94 "Request-Time",
95 now.timestamp_millis()
96 .to_string()
97 .parse()
98 .expect("Failed to parse request time"),
99 );
100 let sign_request_params = SignRequestParams {
101 time: now,
102 api_key: &self.api_key,
103 secret_key: &self.secret_key,
104 params,
105 params_kind: kind,
106 };
107 let sign_request_output = auth::sign_request(sign_request_params)?;
108 header_map.insert(
109 "Signature",
110 sign_request_output
111 .signature
112 .parse()
113 .expect("Failed to parse signature"),
114 );
115 Ok(header_map)
116 }
117
118 #[allow(dead_code)]
119 #[cfg(test)]
120 fn new_for_test() -> Self {
121 dotenv::dotenv().ok();
122 let api_key = std::env::var("MEXC_API_KEY").expect("MEXC_API_KEY not set");
123 let secret_key = std::env::var("MEXC_SECRET_KEY").expect("MEXC_SECRET_KEY not set");
124 Self::new(MexcFuturesApiEndpoint::Base, api_key, secret_key)
125 }
126}
127
128#[derive(Debug, thiserror::Error)]
129pub enum GetAuthHeaderMapError {
130 #[error("Sign request error: {0}")]
131 SignRequestError(#[from] auth::SignRequestError),
132}