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