barter_data/exchange/bybit/
subscription.rs1use barter_integration::{Validator, error::SocketError};
2use serde::{Deserialize, Serialize};
3
4#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
28pub struct BybitResponse {
29 pub success: bool,
30 #[serde(default)]
31 pub ret_msg: BybitReturnMessage,
32}
33
34#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
35pub enum BybitReturnMessage {
36 #[serde(alias = "")]
37 None,
38 #[serde(alias = "pong")]
39 Pong,
40 #[serde(alias = "subscribe")]
41 Subscribe,
42}
43
44impl Default for BybitReturnMessage {
45 fn default() -> Self {
46 Self::None
47 }
48}
49
50impl Validator for BybitResponse {
51 fn validate(self) -> Result<Self, SocketError>
52 where
53 Self: Sized,
54 {
55 match self.ret_msg {
56 BybitReturnMessage::None | BybitReturnMessage::Subscribe => {
57 if self.success {
58 Ok(self)
59 } else {
60 Err(SocketError::Subscribe(
61 "received failure subscription response".to_owned(),
62 ))
63 }
64 }
65 _ => Err(SocketError::Subscribe(
66 "received other message out of sequence".to_owned(),
67 )),
68 }
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 mod de {
77 use super::*;
78
79 #[test]
80 fn test_bybit_sub_response() {
81 struct TestCase {
82 input: &'static str,
83 expected: Result<BybitResponse, SocketError>,
84 }
85
86 let cases = vec![
87 TestCase {
88 input: r#"
90 {
91 "success": true,
92 "ret_msg": "subscribe",
93 "conn_id": "2324d924-aa4d-45b0-a858-7b8be29ab52b",
94 "req_id": "10001",
95 "op": "subscribe"
96 }
97 "#,
98 expected: Ok(BybitResponse {
99 success: true,
100 ret_msg: BybitReturnMessage::Subscribe,
101 }),
102 },
103 TestCase {
104 input: r#"
106 {
107 "success": false,
108 "conn_id": "",
109 "op": ""
110 }
111 "#,
112 expected: Ok(BybitResponse {
113 success: false,
114 ret_msg: BybitReturnMessage::None,
115 }),
116 },
117 ];
118
119 for (index, test) in cases.into_iter().enumerate() {
120 let actual = serde_json::from_str::<BybitResponse>(test.input);
121 match (actual, test.expected) {
122 (Ok(actual), Ok(expected)) => {
123 assert_eq!(actual, expected, "TC{} failed", index)
124 }
125 (Err(_), Err(_)) => {
126 }
128 (actual, expected) => {
129 panic!(
131 "TC{index} failed because actual != expected. \nActual: {actual:?}\nExpected: {expected:?}\n"
132 );
133 }
134 }
135 }
136 }
137 }
138
139 #[test]
140 fn test_validate_bybit_sub_response() {
141 struct TestCase {
142 input_response: BybitResponse,
143 is_valid: bool,
144 }
145
146 let cases = vec![
147 TestCase {
148 input_response: BybitResponse {
150 success: true,
151 ret_msg: BybitReturnMessage::Subscribe,
152 },
153 is_valid: true,
154 },
155 TestCase {
156 input_response: BybitResponse {
158 success: true,
159 ret_msg: BybitReturnMessage::None,
160 },
161 is_valid: true,
162 },
163 TestCase {
164 input_response: BybitResponse {
166 success: false,
167 ret_msg: BybitReturnMessage::Pong,
168 },
169 is_valid: false,
170 },
171 ];
172
173 for (index, test) in cases.into_iter().enumerate() {
174 let actual = test.input_response.validate().is_ok();
175 assert_eq!(actual, test.is_valid, "TestCase {} failed", index);
176 }
177 }
178}