Skip to main content

xapi_okx/common/
response.rs

1use serde::{Deserialize, Serialize};
2use std::fmt::{Display, Formatter};
3use xapi_shared::{rest::error::SharedRestError, ws::response::SharedWsResponseTrait};
4
5pub type OkxRestRespType<T> = Result<OkxRespWrapper<T>, SharedRestError<OkxRespError>>;
6
7#[derive(Debug, Deserialize)]
8pub struct OkxRespWrapper<T> {
9    pub code: String,
10    pub msg: String,
11    pub data: Vec<T>,
12}
13
14#[derive(Debug, Serialize, Deserialize)]
15pub struct OkxRespError {
16    pub code: String,
17    pub msg: String,
18}
19
20impl Display for OkxRespError {
21    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22        write!(
23            f,
24            "{}",
25            serde_json::to_string(self).unwrap_or_else(|_| String::from("{}"))
26        )
27    }
28}
29
30#[derive(Debug)]
31pub struct OkxWsStreamResponse {
32    pub id: String,
33    pub arg: serde_json::Value,
34}
35
36#[derive(Debug, Deserialize)]
37#[serde(rename_all = "camelCase")]
38struct OkxWsStreamRawResponse {
39    id: String,
40    event: OkxWsStreamResponseEvent,
41    arg: Option<serde_json::Value>,
42    #[allow(dead_code)]
43    code: Option<String>,
44    msg: Option<String>,
45    #[allow(dead_code)]
46    conn_id: String,
47}
48
49#[derive(Debug, Deserialize, PartialEq, Eq)]
50#[serde(rename_all = "snake_case")]
51enum OkxWsStreamResponseEvent {
52    Subscribe,
53    Unsubscribe,
54    Error,
55}
56
57impl SharedWsResponseTrait<String> for OkxWsStreamResponse {
58    fn try_parse(
59        text: &str,
60    ) -> Option<Result<Self, (String, xapi_shared::ws::error::SharedWsError)>>
61    where
62        Self: Sized,
63    {
64        match serde_json::from_str::<OkxWsStreamRawResponse>(text) {
65            Err(_) => None,
66            Ok(resp) => {
67                if resp.event == OkxWsStreamResponseEvent::Error {
68                    tracing::error!(?resp, "ws api request failed with error");
69                    return Some(Err((
70                        resp.id,
71                        xapi_shared::ws::error::SharedWsError::AppError(
72                            resp.msg.unwrap_or_else(|| "Unknown error".to_string()),
73                        ),
74                    )));
75                }
76
77                if resp.arg.is_none() {
78                    tracing::error!(?resp, "ws api response missing arg");
79                    return Some(Err((
80                        resp.id,
81                        xapi_shared::ws::error::SharedWsError::AppError(
82                            "Missing arg in response".to_string(),
83                        ),
84                    )));
85                }
86
87                Some(Ok(Self {
88                    id: resp.id,
89                    arg: resp.arg.unwrap(),
90                }))
91            }
92        }
93    }
94
95    fn get_id(&self) -> &String {
96        &self.id
97    }
98}
99
100#[derive(Debug, Deserialize)]
101pub struct OkxWsStreamData {
102    pub arg: serde_json::Value,
103    pub data: serde_json::Value,
104}
105
106impl SharedWsResponseTrait<serde_json::Value> for OkxWsStreamData {
107    fn try_parse(
108        text: &str,
109    ) -> Option<Result<Self, (serde_json::Value, xapi_shared::ws::error::SharedWsError)>>
110    where
111        Self: Sized,
112    {
113        match serde_json::from_str(text) {
114            Err(_) => None,
115            Ok(data) => Some(Ok(data)),
116        }
117    }
118
119    fn get_id(&self) -> &serde_json::Value {
120        &self.arg
121    }
122}