Skip to main content

cashu/nuts/nut17/
ws.rs

1//! Websocket types
2
3use serde::de::DeserializeOwned;
4use serde::{Deserialize, Serialize};
5
6use super::{NotificationPayload, Params};
7
8/// JSON RPC version
9pub const JSON_RPC_VERSION: &str = "2.0";
10
11/// The response to a subscription request
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[serde(bound = "I: Serialize + DeserializeOwned")]
14pub struct WsSubscribeResponse<I> {
15    /// Status
16    pub status: String,
17    /// Subscription ID
18    #[serde(rename = "subId")]
19    pub sub_id: I,
20}
21
22/// The response to an unsubscription request
23#[derive(Debug, Clone, Serialize, Deserialize)]
24#[serde(bound = "I: Serialize + DeserializeOwned")]
25pub struct WsUnsubscribeResponse<I> {
26    /// Status
27    pub status: String,
28    /// Subscription ID
29    #[serde(rename = "subId")]
30    pub sub_id: I,
31}
32
33/// The notification
34///
35/// This is the notification that is sent to the client when an event matches a
36/// subscription
37#[derive(Debug, Clone, Serialize, Deserialize)]
38#[serde(bound = "T: Serialize + DeserializeOwned, I: Serialize + DeserializeOwned")]
39pub struct NotificationInner<T, I>
40where
41    T: Clone,
42{
43    /// The subscription ID
44    #[serde(rename = "subId")]
45    pub sub_id: I,
46
47    /// The notification payload
48    pub payload: NotificationPayload<T>,
49}
50
51/// Responses from the web socket server
52#[derive(Debug, Clone, Serialize, Deserialize)]
53#[serde(bound = "I: Serialize + DeserializeOwned")]
54#[serde(untagged)]
55pub enum WsResponseResult<I> {
56    /// A response to a subscription request
57    Subscribe(WsSubscribeResponse<I>),
58    /// Unsubscribe
59    Unsubscribe(WsUnsubscribeResponse<I>),
60}
61
62impl<I> From<WsSubscribeResponse<I>> for WsResponseResult<I> {
63    fn from(response: WsSubscribeResponse<I>) -> Self {
64        WsResponseResult::Subscribe(response)
65    }
66}
67
68impl<I> From<WsUnsubscribeResponse<I>> for WsResponseResult<I> {
69    fn from(response: WsUnsubscribeResponse<I>) -> Self {
70        WsResponseResult::Unsubscribe(response)
71    }
72}
73
74/// The request to unsubscribe
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(bound = "I: Serialize + DeserializeOwned")]
77pub struct WsUnsubscribeRequest<I> {
78    /// Subscription ID
79    #[serde(rename = "subId")]
80    pub sub_id: I,
81}
82
83/// The inner method of the websocket request
84#[derive(Debug, Clone, Serialize, Deserialize)]
85#[serde(rename_all = "snake_case", tag = "method", content = "params")]
86#[serde(bound = "I: Serialize + DeserializeOwned")]
87pub enum WsMethodRequest<I> {
88    /// Subscribe method
89    Subscribe(Params<I>),
90    /// Unsubscribe method
91    Unsubscribe(WsUnsubscribeRequest<I>),
92}
93
94/// Websocket request
95#[derive(Debug, Clone, Serialize, Deserialize)]
96#[serde(bound = "I: Serialize + DeserializeOwned")]
97pub struct WsRequest<I> {
98    /// JSON RPC version
99    pub jsonrpc: String,
100    /// The method body
101    #[serde(flatten)]
102    pub method: WsMethodRequest<I>,
103    /// The request ID
104    pub id: usize,
105}
106
107impl<I> From<(WsMethodRequest<I>, usize)> for WsRequest<I> {
108    fn from((method, id): (WsMethodRequest<I>, usize)) -> Self {
109        WsRequest {
110            jsonrpc: JSON_RPC_VERSION.to_owned(),
111            method,
112            id,
113        }
114    }
115}
116
117/// Notification from the server
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct WsNotification<T> {
120    /// JSON RPC version
121    pub jsonrpc: String,
122    /// The method
123    pub method: String,
124    /// The parameters
125    pub params: T,
126}
127
128/// Websocket error
129#[derive(Debug, Clone, Deserialize, Serialize)]
130pub struct WsErrorBody {
131    /// Error code
132    pub code: i32,
133    /// Error message
134    pub message: String,
135}
136
137/// Websocket response
138#[derive(Debug, Clone, Serialize, Deserialize)]
139#[serde(bound = "I: Serialize + DeserializeOwned")]
140pub struct WsResponse<I> {
141    /// JSON RPC version
142    pub jsonrpc: String,
143    /// The result
144    pub result: WsResponseResult<I>,
145    /// The request ID
146    pub id: usize,
147}
148
149/// WebSocket error response
150#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct WsErrorResponse {
152    /// JSON RPC version
153    pub jsonrpc: String,
154    /// The result
155    pub error: WsErrorBody,
156    /// The request ID
157    pub id: usize,
158}
159
160/// Message from the server to the client
161#[derive(Debug, Clone, Serialize, Deserialize)]
162#[serde(bound = "I: Serialize + DeserializeOwned")]
163#[serde(untagged)]
164pub enum WsMessageOrResponse<I> {
165    /// A response to a request
166    Response(WsResponse<I>),
167    /// An error response
168    ErrorResponse(WsErrorResponse),
169    /// A notification
170    Notification(Box<WsNotification<NotificationInner<String, I>>>),
171}
172
173impl<I> From<(usize, Result<WsResponseResult<I>, WsErrorBody>)> for WsMessageOrResponse<I> {
174    fn from((id, result): (usize, Result<WsResponseResult<I>, WsErrorBody>)) -> Self {
175        match result {
176            Ok(result) => WsMessageOrResponse::Response(WsResponse {
177                jsonrpc: JSON_RPC_VERSION.to_owned(),
178                result,
179                id,
180            }),
181            Err(err) => WsMessageOrResponse::ErrorResponse(WsErrorResponse {
182                jsonrpc: JSON_RPC_VERSION.to_owned(),
183                error: err,
184                id,
185            }),
186        }
187    }
188}