binance_sdk/stocks/rest_api/apis/
user_data_streams_api.rs1#![allow(unused_imports)]
15use async_trait::async_trait;
16use derive_builder::Builder;
17use reqwest;
18use rust_decimal::prelude::*;
19use serde::{Deserialize, Serialize};
20use serde_json::{Value, json};
21use std::collections::BTreeMap;
22
23use crate::common::{
24 config::ConfigurationRestApi,
25 models::{ParamBuildError, RestApiResponse},
26 utils::send_request,
27};
28use crate::stocks::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait UserDataStreamsApi: Send + Sync {
34 async fn create_renew_listen_key(
35 &self,
36 params: CreateRenewListenKeyParams,
37 ) -> anyhow::Result<RestApiResponse<models::CreateRenewListenKeyResponse>>;
38}
39
40#[derive(Debug, Clone)]
41pub struct UserDataStreamsApiClient {
42 configuration: ConfigurationRestApi,
43}
44
45impl UserDataStreamsApiClient {
46 pub fn new(configuration: ConfigurationRestApi) -> Self {
47 Self { configuration }
48 }
49}
50
51#[derive(Clone, Debug, Builder, Deserialize, Default)]
56#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
57pub struct CreateRenewListenKeyParams {
58 #[builder(setter(into), default)]
62 #[serde(rename = "recvWindow", default)]
63 pub recv_window: Option<i64>,
64}
65
66impl CreateRenewListenKeyParams {
67 #[must_use]
70 pub fn builder() -> CreateRenewListenKeyParamsBuilder {
71 CreateRenewListenKeyParamsBuilder::default()
72 }
73}
74
75#[async_trait]
76impl UserDataStreamsApi for UserDataStreamsApiClient {
77 async fn create_renew_listen_key(
78 &self,
79 params: CreateRenewListenKeyParams,
80 ) -> anyhow::Result<RestApiResponse<models::CreateRenewListenKeyResponse>> {
81 let CreateRenewListenKeyParams { recv_window } = params;
82
83 let mut query_params = BTreeMap::new();
84 let body_params = BTreeMap::new();
85
86 if let Some(rw) = recv_window {
87 query_params.insert("recvWindow".to_string(), json!(rw));
88 }
89
90 send_request::<models::CreateRenewListenKeyResponse>(
91 &self.configuration,
92 "/sapi/v1/equity/listenKey",
93 reqwest::Method::POST,
94 query_params,
95 body_params,
96 if HAS_TIME_UNIT {
97 self.configuration.time_unit
98 } else {
99 None
100 },
101 false,
102 )
103 .await
104 }
105}
106
107#[cfg(all(test, feature = "stocks"))]
108mod tests {
109 use super::*;
110 use crate::TOKIO_SHARED_RT;
111 use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
112 use async_trait::async_trait;
113 use std::collections::HashMap;
114
115 struct DummyRestApiResponse<T> {
116 inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
117 status: u16,
118 headers: HashMap<String, String>,
119 rate_limits: Option<Vec<RestApiRateLimit>>,
120 }
121
122 impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
123 fn from(dummy: DummyRestApiResponse<T>) -> Self {
124 Self {
125 data_fn: dummy.inner,
126 status: dummy.status,
127 headers: dummy.headers,
128 rate_limits: dummy.rate_limits,
129 }
130 }
131 }
132
133 struct MockUserDataStreamsApiClient {
134 force_error: bool,
135 }
136
137 #[async_trait]
138 impl UserDataStreamsApi for MockUserDataStreamsApiClient {
139 async fn create_renew_listen_key(
140 &self,
141 _params: CreateRenewListenKeyParams,
142 ) -> anyhow::Result<RestApiResponse<models::CreateRenewListenKeyResponse>> {
143 if self.force_error {
144 return Err(ConnectorError::ConnectorClientError {
145 msg: "ResponseError".to_string(),
146 code: None,
147 }
148 .into());
149 }
150
151 let resp_json: Value = serde_json::from_str(
152 r#"{"listenKey":"pqia91ma19a5s61cv6a81va65sdf19v8a65s1cv1zuz3ee1c5xz2ef6ad7"}"#,
153 )
154 .unwrap_or_else(|_| serde_json::json!({}));
155 let dummy_response: models::CreateRenewListenKeyResponse =
156 serde_json::from_value(resp_json.clone())
157 .expect("should parse into models::CreateRenewListenKeyResponse");
158
159 let dummy = DummyRestApiResponse {
160 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
161 status: 200,
162 headers: HashMap::new(),
163 rate_limits: None,
164 };
165
166 Ok(dummy.into())
167 }
168 }
169
170 #[test]
171 fn create_renew_listen_key_required_params_success() {
172 TOKIO_SHARED_RT.block_on(async {
173 let client = MockUserDataStreamsApiClient { force_error: false };
174
175 let params = CreateRenewListenKeyParams::builder().build().unwrap();
176
177 let resp_json: Value = serde_json::from_str(
178 r#"{"listenKey":"pqia91ma19a5s61cv6a81va65sdf19v8a65s1cv1zuz3ee1c5xz2ef6ad7"}"#,
179 )
180 .unwrap_or_else(|_| serde_json::json!({}));
181 let expected_response: models::CreateRenewListenKeyResponse =
182 serde_json::from_value(resp_json.clone())
183 .expect("should parse into models::CreateRenewListenKeyResponse");
184
185 let resp = client
186 .create_renew_listen_key(params)
187 .await
188 .expect("Expected a response");
189 let data_future = resp.data();
190 let actual_response = data_future.await.unwrap();
191 assert_eq!(actual_response, expected_response);
192 });
193 }
194
195 #[test]
196 fn create_renew_listen_key_optional_params_success() {
197 TOKIO_SHARED_RT.block_on(async {
198 let client = MockUserDataStreamsApiClient { force_error: false };
199
200 let params = CreateRenewListenKeyParams::builder()
201 .recv_window(5000)
202 .build()
203 .unwrap();
204
205 let resp_json: Value = serde_json::from_str(
206 r#"{"listenKey":"pqia91ma19a5s61cv6a81va65sdf19v8a65s1cv1zuz3ee1c5xz2ef6ad7"}"#,
207 )
208 .unwrap_or_else(|_| serde_json::json!({}));
209 let expected_response: models::CreateRenewListenKeyResponse =
210 serde_json::from_value(resp_json.clone())
211 .expect("should parse into models::CreateRenewListenKeyResponse");
212
213 let resp = client
214 .create_renew_listen_key(params)
215 .await
216 .expect("Expected a response");
217 let data_future = resp.data();
218 let actual_response = data_future.await.unwrap();
219 assert_eq!(actual_response, expected_response);
220 });
221 }
222
223 #[test]
224 fn create_renew_listen_key_response_error() {
225 TOKIO_SHARED_RT.block_on(async {
226 let client = MockUserDataStreamsApiClient { force_error: true };
227
228 let params = CreateRenewListenKeyParams::builder().build().unwrap();
229
230 match client.create_renew_listen_key(params).await {
231 Ok(_) => panic!("Expected an error"),
232 Err(err) => {
233 assert_eq!(err.to_string(), "Connector client error: ResponseError");
234 }
235 }
236 });
237 }
238}