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