deribit_base/model/
response.rs

1/******************************************************************************
2   Author: Joaquín Béjar García
3   Email: jb@taunais.com
4   Date: 21/7/25
5******************************************************************************/
6
7use serde::{Deserialize, Serialize};
8
9/// Generic JSON-RPC 2.0 response wrapper
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct JsonRpcResponse<T> {
12    /// JSON-RPC version
13    pub jsonrpc: String,
14    /// Request ID
15    pub id: Option<serde_json::Value>,
16    /// Result data (present on success)
17    pub result: Option<T>,
18    /// Error information (present on error)
19    pub error: Option<JsonRpcError>,
20    /// Test net flag
21    pub testnet: Option<bool>,
22    /// Use server time
23    #[serde(rename = "usIn")]
24    pub us_in: Option<i64>,
25    /// Use out time
26    #[serde(rename = "usOut")]
27    pub us_out: Option<i64>,
28    /// Use diff time
29    #[serde(rename = "usDiff")]
30    pub us_diff: Option<i64>,
31}
32
33impl<T> JsonRpcResponse<T> {
34    /// Create a successful response
35    pub fn success(id: Option<serde_json::Value>, result: T) -> Self {
36        Self {
37            jsonrpc: "2.0".to_string(),
38            id,
39            result: Some(result),
40            error: None,
41            testnet: None,
42            us_in: None,
43            us_out: None,
44            us_diff: None,
45        }
46    }
47
48    /// Create an error response
49    pub fn error(id: Option<serde_json::Value>, error: JsonRpcError) -> Self {
50        Self {
51            jsonrpc: "2.0".to_string(),
52            id,
53            result: None,
54            error: Some(error),
55            testnet: None,
56            us_in: None,
57            us_out: None,
58            us_diff: None,
59        }
60    }
61
62    /// Check if the response is successful
63    pub fn is_success(&self) -> bool {
64        self.error.is_none() && self.result.is_some()
65    }
66
67    /// Check if the response is an error
68    pub fn is_error(&self) -> bool {
69        self.error.is_some()
70    }
71
72    /// Get the result, consuming the response
73    pub fn into_result(self) -> Result<T, JsonRpcError> {
74        match (self.result, self.error) {
75            (Some(result), None) => Ok(result),
76            (None, Some(error)) => Err(error),
77            (Some(_), Some(error)) => Err(error), // Error takes precedence
78            (None, None) => Err(JsonRpcError {
79                code: -32603,
80                message: "Internal error: neither result nor error present".to_string(),
81                data: None,
82            }),
83        }
84    }
85}
86
87/// JSON-RPC error information
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct JsonRpcError {
90    /// Error code
91    pub code: i32,
92    /// Error message
93    pub message: String,
94    /// Additional error data
95    pub data: Option<serde_json::Value>,
96}
97
98impl JsonRpcError {
99    /// Create a new JSON-RPC error
100    pub fn new(code: i32, message: String) -> Self {
101        Self {
102            code,
103            message,
104            data: None,
105        }
106    }
107
108    /// Create an error with additional data
109    pub fn with_data(code: i32, message: String, data: serde_json::Value) -> Self {
110        Self {
111            code,
112            message,
113            data: Some(data),
114        }
115    }
116
117    /// Parse error (-32700)
118    pub fn parse_error() -> Self {
119        Self::new(-32700, "Parse error".to_string())
120    }
121
122    /// Invalid request (-32600)
123    pub fn invalid_request() -> Self {
124        Self::new(-32600, "Invalid Request".to_string())
125    }
126
127    /// Method not found (-32601)
128    pub fn method_not_found() -> Self {
129        Self::new(-32601, "Method not found".to_string())
130    }
131
132    /// Invalid params (-32602)
133    pub fn invalid_params() -> Self {
134        Self::new(-32602, "Invalid params".to_string())
135    }
136
137    /// Internal error (-32603)
138    pub fn internal_error() -> Self {
139        Self::new(-32603, "Internal error".to_string())
140    }
141
142    /// Check if this is a server error (code between -32099 and -32000)
143    pub fn is_server_error(&self) -> bool {
144        self.code <= -32000 && self.code >= -32099
145    }
146
147    /// Check if this is an application error (code > -32000)
148    pub fn is_application_error(&self) -> bool {
149        self.code > -32000
150    }
151}
152
153impl std::fmt::Display for JsonRpcError {
154    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155        write!(f, "JSON-RPC Error {}: {}", self.code, self.message)
156    }
157}
158
159impl std::error::Error for JsonRpcError {}
160
161/// Authentication response
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct AuthResponse {
164    /// Access token
165    pub access_token: String,
166    /// Token type (usually "bearer")
167    pub token_type: String,
168    /// Expires in seconds
169    pub expires_in: i64,
170    /// Refresh token
171    pub refresh_token: String,
172    /// Scope
173    pub scope: String,
174}
175
176/// Pagination information
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct Pagination {
179    /// Current page
180    pub page: Option<u32>,
181    /// Items per page
182    pub per_page: Option<u32>,
183    /// Total items
184    pub total: Option<u64>,
185    /// Total pages
186    pub pages: Option<u32>,
187    /// Has more pages
188    pub has_more: Option<bool>,
189}
190
191/// Generic paginated response
192#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct PaginatedResponse<T> {
194    /// Data items
195    pub data: Vec<T>,
196    /// Pagination information
197    pub pagination: Option<Pagination>,
198}
199
200impl<T> PaginatedResponse<T> {
201    /// Create a new paginated response
202    pub fn new(data: Vec<T>) -> Self {
203        Self {
204            data,
205            pagination: None,
206        }
207    }
208
209    /// Create a paginated response with pagination info
210    pub fn with_pagination(data: Vec<T>, pagination: Pagination) -> Self {
211        Self {
212            data,
213            pagination: Some(pagination),
214        }
215    }
216
217    /// Check if there are more pages
218    pub fn has_more(&self) -> bool {
219        self.pagination
220            .as_ref()
221            .and_then(|p| p.has_more)
222            .unwrap_or(false)
223    }
224
225    /// Get the number of items
226    pub fn len(&self) -> usize {
227        self.data.len()
228    }
229
230    /// Check if the response is empty
231    pub fn is_empty(&self) -> bool {
232        self.data.is_empty()
233    }
234}
235
236/// WebSocket notification
237#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct Notification<T> {
239    /// JSON-RPC version
240    pub jsonrpc: String,
241    /// Method name
242    pub method: String,
243    /// Parameters/data
244    pub params: T,
245}
246
247impl<T> Notification<T> {
248    /// Create a new notification
249    pub fn new(method: String, params: T) -> Self {
250        Self {
251            jsonrpc: "2.0".to_string(),
252            method,
253            params,
254        }
255    }
256}
257
258/// Subscription response
259#[derive(Debug, Clone, Serialize, Deserialize)]
260pub struct SubscriptionResponse {
261    /// Subscription ID
262    pub subscription: String,
263    /// Channel name
264    pub channel: String,
265}
266
267/// Heartbeat response
268#[derive(Debug, Clone, Serialize, Deserialize)]
269pub struct HeartbeatResponse {
270    /// Type (always "heartbeat")
271    #[serde(rename = "type")]
272    pub type_: String,
273}
274
275/// Test response for connectivity checks
276#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct TestResponse {
278    /// Version information
279    pub version: String,
280}
281
282/// Server time response
283#[derive(Debug, Clone, Serialize, Deserialize)]
284pub struct ServerTimeResponse {
285    /// Server timestamp in milliseconds
286    pub timestamp: i64,
287}