bybit/ws/
outgoing_message.rs1use serde::Serialize;
2
3use crate::{SensitiveString, Timestamp, Topic, create_stream_signature, timestamp};
4
5#[derive(Serialize, Debug)]
6#[serde(tag = "op")]
7pub enum OutgoingMessage {
8 #[serde(rename = "subscribe")]
9 Subscribe {
10 #[serde(skip_serializing_if = "Option::is_none")]
11 req_id: Option<String>,
12 args: Vec<Topic>,
13 },
14 #[serde(rename = "unsubscribe")]
15 Unsubscribe {
16 #[serde(skip_serializing_if = "Option::is_none")]
17 req_id: Option<String>,
18 args: Vec<Topic>,
19 },
20 #[serde(rename = "auth")]
21 Auth {
22 #[serde(skip_serializing_if = "Option::is_none")]
23 req_id: Option<String>,
24 args: (String, Timestamp, String),
25 },
26 #[serde(rename = "ping")]
27 Ping {
28 #[serde(skip_serializing_if = "Option::is_none")]
29 req_id: Option<String>,
30 },
31 #[serde(rename = "pong")]
32 Pong {
33 #[serde(skip_serializing_if = "Option::is_none")]
34 req_id: Option<String>,
35 },
36}
37
38pub fn create_outgoing_message_auth(
39 api_key: SensitiveString,
40 api_secret: SensitiveString,
41 req_id: Option<String>,
42 recv_window: Timestamp,
43) -> OutgoingMessage {
44 let api_key = api_key.expose().to_string();
45 let expires = timestamp() + recv_window;
46
47 let signature = create_stream_signature(expires, api_secret);
48
49 OutgoingMessage::Auth {
50 req_id,
51 args: (api_key, expires, signature),
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use crate::*;
58
59 use super::*;
60
61 #[test]
62 fn test_serialize_outgoing_message_subscribe() {
63 let msg = OutgoingMessage::Subscribe {
64 req_id: Some(String::from("request_id")),
65 args: vec![
66 Topic::Ticker(String::from("BTCUSDT")),
67 Topic::Order(Category::Linear),
68 ],
69 };
70 let expected =
71 r#"{"op":"subscribe","req_id":"request_id","args":["tickers.BTCUSDT","order.linear"]}"#;
72 let serialized = serde_json::to_string(&msg).unwrap();
73 assert_eq!(serialized, expected);
74 }
75
76 #[test]
77 fn test_serialize_outgoing_message_unsubscribe() {
78 let msg = OutgoingMessage::Unsubscribe {
79 req_id: Some(String::from("request_id")),
80 args: vec![Topic::Ticker(String::from("BTCUSDT"))],
81 };
82 let expected = r#"{"op":"unsubscribe","req_id":"request_id","args":["tickers.BTCUSDT"]}"#;
83 let serialized = serde_json::to_string(&msg).unwrap();
84 assert_eq!(serialized, expected);
85 }
86
87 #[test]
88 fn test_serialize_outgoing_message_auth() {
89 let msg = OutgoingMessage::Auth {
90 req_id: Some(String::from("request_id")),
91 args: (
92 String::from("api_key"),
93 1662350400000,
94 String::from("signature"),
95 ),
96 };
97 let expected =
98 r#"{"op":"auth","req_id":"request_id","args":["api_key",1662350400000,"signature"]}"#;
99 let serialized = serde_json::to_string(&msg).unwrap();
100 assert_eq!(serialized, expected);
101 }
102}