bybit_rust_api/rest/
client.rs1use crate::consts::{
2 API_REQUEST_KEY, RECV_WINDOW_KEY, SIGNATURE_KEY, SIGN_TYPE_KEY, TIMESTAMP_KEY,
3};
4use crate::rest::api_key_pair::ApiKeyPair;
5use crate::utils::{millis, sign};
6use reqwest::RequestBuilder;
7use serde::de::DeserializeOwned;
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Copy, PartialEq)]
11pub enum SecType {
12 None = 0,
13 Signed = 1,
14}
15
16pub struct RestClient {
17 api_key_pair: ApiKeyPair,
18 base_url: String,
19 debug: bool,
20
21 http_client: reqwest::Client,
22 }
24
25#[derive(Serialize, Deserialize, Debug)]
26pub struct ServerResponse<T> {
27 #[serde(rename = "retCode")]
28 pub ret_code: i32,
29 #[serde(rename = "retMsg")]
30 pub ret_msg: String,
31 #[serde(rename = "result")]
32 pub result: T,
33 #[serde(rename = "retExtInfo")]
34 pub ret_ext_info: serde_json::Value,
35 #[serde(rename = "time")]
36 pub time: i64,
37}
38
39impl RestClient {
40 pub fn new(api_key_pair: ApiKeyPair, base_url: String, debug: bool) -> RestClient {
41 RestClient {
42 api_key_pair,
43 base_url,
44 debug,
45 http_client: reqwest::Client::new(),
46 }
47 }
48
49 fn query_string(&self, query: serde_json::Value) -> String {
50 serde_urlencoded::to_string(query.as_object().unwrap()).unwrap()
51 }
52
53 fn sign_request(
54 &self,
55 request_builder: RequestBuilder,
56 query_or_body_param: String,
57 ) -> RequestBuilder {
58 let recv_window = "5000";
59 let timestamp_str = millis().to_string();
60 let signature = sign(
61 &self.api_key_pair.secret(),
62 &format!(
63 "{}{}{}{}",
64 timestamp_str,
65 self.api_key_pair.key(),
66 recv_window,
67 query_or_body_param
68 ),
69 );
70
71 request_builder
72 .header(SIGN_TYPE_KEY, "2")
73 .header(API_REQUEST_KEY, self.api_key_pair.key())
74 .header(TIMESTAMP_KEY, timestamp_str)
75 .header(RECV_WINDOW_KEY, recv_window)
76 .header(SIGNATURE_KEY, signature)
77 }
78
79 pub async fn get<A: DeserializeOwned>(
80 &self,
81 endpoint: &str,
82 query: serde_json::Value,
83 sec_type: SecType,
84 ) -> Result<A, reqwest::Error> {
85 let mut url = format!("{}/{}", self.base_url, endpoint);
86 let query_string = self.query_string(query);
87
88 if !query_string.is_empty() {
89 url.push_str(&format!("?{}", query_string));
90 }
91
92 let mut request_builder = self.http_client.get(&url);
93 if sec_type == SecType::Signed {
94 request_builder = self.sign_request(request_builder, query_string);
95 }
96
97 println!("url: {}", url);
98
99 let r = request_builder.send().await?;
100 let server_response: A = r.json().await?;
101 Ok(server_response)
102 }
103
104 pub async fn post<A: DeserializeOwned>(
105 &self,
106 endpoint: &str,
107 body: serde_json::Value,
108 sec_type: SecType,
109 ) -> Result<A, reqwest::Error> {
110 let url = format!("{}/{}", self.base_url, endpoint);
111 let mut request_builder = self.http_client.post(&url);
112 if sec_type == SecType::Signed {
113 request_builder = self.sign_request(
114 request_builder,
115 serde_urlencoded::to_string(body.as_object().unwrap()).unwrap(),
116 );
117 }
118
119 let server_response = request_builder.json(&body).send().await?.json().await?;
120 Ok(server_response)
121 }
122}