xapi_binance/common/
response.rs1use http::StatusCode;
2use serde::{Deserialize, Serialize};
3use std::fmt::{Display, Formatter};
4use xapi_shared::{
5 repr::de_status_code::deserialize_status_code,
6 rest::error::SharedRestError,
7 ws::{error::SharedWsError, response::SharedWsResponseTrait},
8};
9
10pub type BnRestRespType<T> = Result<T, SharedRestError<BnRespError>>;
11pub type BnWsApiRespType<T> = Result<T, SharedWsError>;
12
13#[derive(Debug, Serialize, Deserialize)]
14pub struct BnRespError {
15 pub code: i32,
16 pub msg: String,
17}
18
19impl Display for BnRespError {
20 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
21 write!(
22 f,
23 "{}",
24 serde_json::to_string(self).unwrap_or_else(|_| String::from("{}"))
25 )
26 }
27}
28
29#[derive(Debug)]
30pub struct BnWsApiResponse {
31 pub id: String,
32 pub result: serde_json::Value,
33}
34
35impl SharedWsResponseTrait<String> for BnWsApiResponse {
36 fn try_parse(text: &str) -> Option<Result<Self, (String, SharedWsError)>>
37 where
38 Self: Sized,
39 {
40 match serde_json::from_str::<BnWsApiRawResponse>(text) {
41 Err(_) => None,
42 Ok(resp) => {
43 if !resp.status.is_success() || resp.error.is_some() || resp.result.is_none() {
44 tracing::error!(
45 status = ?resp.status,
46 id = resp.id,
47 ?resp,
48 "ws api request failed with status code"
49 );
50 let err_str = serde_json::to_string(&resp.error)
51 .inspect_err(|err| {
52 tracing::error!(?err, "failed to serialize ws api error response")
53 })
54 .unwrap_or_else(|_| format!("{:?}", resp.error));
55 return Some(Err((resp.id, SharedWsError::AppError(err_str))));
56 }
57
58 Some(Ok(Self {
59 id: resp.id,
60 result: resp.result.unwrap(),
61 }))
62 }
63 }
64 }
65
66 fn get_id(&self) -> &String {
67 &self.id
68 }
69}
70
71#[derive(Debug, Deserialize)]
72struct BnWsApiRawResponse {
73 id: String,
74 #[serde(deserialize_with = "deserialize_status_code")]
75 status: StatusCode,
76 result: Option<serde_json::Value>,
77 error: Option<BnRespError>,
78}
79
80#[derive(Debug)]
81pub struct BnWsStreamResponse {
82 pub id: String,
83 pub result: serde_json::Value,
84}
85
86impl SharedWsResponseTrait<String> for BnWsStreamResponse {
87 fn try_parse(text: &str) -> Option<Result<Self, (String, SharedWsError)>>
88 where
89 Self: Sized,
90 {
91 match serde_json::from_str::<BnWsStreamRawResponse>(text) {
92 Err(_) => None,
93 Ok(resp) => {
94 if let Some(err) = &resp.error {
95 tracing::error!(id = resp.id, ?err, "ws stream request failed with error");
96 return Some(Err((resp.id, SharedWsError::AppError(err.msg.clone()))));
97 }
98
99 Some(Ok(Self {
100 id: resp.id,
101 result: resp.result.unwrap_or_default(),
102 }))
103 }
104 }
105 }
106
107 fn get_id(&self) -> &String {
108 &self.id
109 }
110}
111
112#[derive(Debug, Deserialize)]
113struct BnWsStreamRawResponse {
114 id: String,
115 result: Option<serde_json::Value>,
116 error: Option<BnWsStreamError>,
117}
118
119#[derive(Debug, Deserialize)]
120struct BnWsStreamError {
121 #[allow(dead_code)]
122 code: i64,
123 msg: String,
124 #[allow(dead_code)]
125 id: Option<String>,
126}
127
128#[derive(Debug, Deserialize)]
129pub struct BnWsStreamData {
130 pub stream: String,
131 pub data: serde_json::Value,
132}
133
134impl SharedWsResponseTrait<String> for BnWsStreamData {
135 fn try_parse(text: &str) -> Option<Result<Self, (String, SharedWsError)>>
136 where
137 Self: Sized,
138 {
139 match serde_json::from_str(text) {
140 Err(_) => None,
141 Ok(data) => Some(Ok(data)),
142 }
143 }
144
145 fn get_id(&self) -> &String {
146 &self.stream
147 }
148}