Skip to main content

bybit_api/websocket/
models.rs

1//! WebSocket message models.
2
3use serde::{Deserialize, Serialize};
4
5/// WebSocket operation request.
6#[derive(Debug, Clone, Serialize)]
7pub struct WsRequest {
8    /// Request ID
9    pub req_id: String,
10    /// Operation type
11    pub op: String,
12    /// Arguments
13    pub args: Vec<String>,
14}
15
16/// WebSocket authentication request.
17#[derive(Debug, Clone, Serialize)]
18pub struct WsAuthRequest {
19    /// Request ID
20    pub req_id: String,
21    /// Operation type
22    pub op: String,
23    /// Arguments [api_key, expires, signature]
24    pub args: Vec<serde_json::Value>,
25}
26
27/// WebSocket response.
28#[derive(Debug, Clone, Deserialize)]
29pub struct WsResponse {
30    /// Success flag
31    #[serde(default)]
32    pub success: Option<bool>,
33    /// Return message
34    #[serde(default)]
35    pub ret_msg: Option<String>,
36    /// Connection ID
37    #[serde(default)]
38    pub conn_id: Option<String>,
39    /// Request ID
40    #[serde(default)]
41    pub req_id: Option<String>,
42    /// Operation type
43    #[serde(default)]
44    pub op: Option<String>,
45}
46
47/// WebSocket message (data push).
48#[derive(Debug, Clone, Deserialize)]
49pub struct WsMessage {
50    /// Topic name
51    pub topic: String,
52    /// Message type (snapshot, delta)
53    #[serde(rename = "type")]
54    pub msg_type: Option<String>,
55    /// Timestamp
56    pub ts: Option<u64>,
57    /// Data payload
58    pub data: serde_json::Value,
59}
60
61/// WebSocket ping request.
62#[derive(Debug, Clone, Serialize)]
63pub struct WsPing {
64    /// Request ID
65    pub req_id: String,
66    /// Operation type
67    pub op: String,
68}
69
70impl WsPing {
71    /// Create a new ping message.
72    pub fn new() -> Self {
73        Self {
74            req_id: uuid::Uuid::new_v4().to_string(),
75            op: "ping".to_string(),
76        }
77    }
78}
79
80impl Default for WsPing {
81    fn default() -> Self {
82        Self::new()
83    }
84}
85
86/// WebSocket pong response.
87#[derive(Debug, Clone, Deserialize)]
88pub struct WsPong {
89    /// Success flag
90    #[serde(default)]
91    pub success: Option<bool>,
92    /// Return message
93    #[serde(default)]
94    pub ret_msg: Option<String>,
95    /// Connection ID
96    #[serde(default)]
97    pub conn_id: Option<String>,
98    /// Request ID
99    #[serde(default)]
100    pub req_id: Option<String>,
101    /// Operation type
102    #[serde(default)]
103    pub op: Option<String>,
104}
105
106/// Check if message is a pong response.
107pub fn is_pong(msg: &serde_json::Value) -> bool {
108    if let Some(op) = msg.get("op").and_then(|v| v.as_str()) {
109        return op == "pong";
110    }
111    if let Some(ret_msg) = msg.get("ret_msg").and_then(|v| v.as_str()) {
112        return ret_msg == "pong";
113    }
114    false
115}
116
117/// Check if message is an auth response.
118pub fn is_auth_response(msg: &serde_json::Value) -> bool {
119    msg.get("op")
120        .and_then(|v| v.as_str())
121        .map(|op| op == "auth")
122        .unwrap_or(false)
123}
124
125/// Check if message is a subscription response.
126pub fn is_subscription_response(msg: &serde_json::Value) -> bool {
127    msg.get("op")
128        .and_then(|v| v.as_str())
129        .map(|op| op == "subscribe")
130        .unwrap_or(false)
131}
132
133/// Check if message is a data message.
134pub fn is_data_message(msg: &serde_json::Value) -> bool {
135    msg.get("topic").is_some()
136}