mexc_rs/futures/
mod.rs

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}