lightning_liquidity/lsps0/
ser.rs

1//! Contains basic data types that allow for the (de-)seralization of LSPS messages in the JSON-RPC 2.0 format.
2//!
3//! Please refer to the [bLIP-50 / LSPS0
4//! specification](https://github.com/lightning/blips/blob/master/blip-0050.md) for more
5//! information.
6
7use alloc::string::String;
8
9use core::fmt::{self, Display};
10use core::str::FromStr;
11
12use crate::lsps0::msgs::{
13	LSPS0ListProtocolsRequest, LSPS0Message, LSPS0Request, LSPS0Response,
14	LSPS0_LISTPROTOCOLS_METHOD_NAME,
15};
16
17use crate::lsps1::msgs::{
18	LSPS1Message, LSPS1Request, LSPS1Response, LSPS1_CREATE_ORDER_METHOD_NAME,
19	LSPS1_GET_INFO_METHOD_NAME, LSPS1_GET_ORDER_METHOD_NAME,
20};
21use crate::lsps2::msgs::{
22	LSPS2Message, LSPS2Request, LSPS2Response, LSPS2_BUY_METHOD_NAME, LSPS2_GET_INFO_METHOD_NAME,
23};
24use crate::lsps5::msgs::{
25	LSPS5Message, LSPS5Request, LSPS5Response, LSPS5_LIST_WEBHOOKS_METHOD_NAME,
26	LSPS5_REMOVE_WEBHOOK_METHOD_NAME, LSPS5_SET_WEBHOOK_METHOD_NAME,
27};
28
29use crate::prelude::HashMap;
30
31use lightning::ln::msgs::{DecodeError, LightningError};
32use lightning::ln::wire;
33use lightning::util::ser::{LengthLimitedRead, LengthReadable, Readable, WithoutLength, Writeable};
34
35use bitcoin::secp256k1::PublicKey;
36
37use core::time::Duration;
38#[cfg(feature = "time")]
39use std::time::{SystemTime, UNIX_EPOCH};
40
41use serde::de::{self, MapAccess, Visitor};
42use serde::ser::SerializeStruct;
43use serde::{Deserialize, Deserializer, Serialize};
44use serde_json::json;
45
46pub(crate) const LSPS_MESSAGE_SERIALIZED_STRUCT_NAME: &str = "LSPSMessage";
47pub(crate) const JSONRPC_FIELD_KEY: &str = "jsonrpc";
48pub(crate) const JSONRPC_FIELD_VALUE: &str = "2.0";
49pub(crate) const JSONRPC_METHOD_FIELD_KEY: &str = "method";
50pub(crate) const JSONRPC_ID_FIELD_KEY: &str = "id";
51pub(crate) const JSONRPC_PARAMS_FIELD_KEY: &str = "params";
52pub(crate) const JSONRPC_RESULT_FIELD_KEY: &str = "result";
53pub(crate) const JSONRPC_ERROR_FIELD_KEY: &str = "error";
54pub(crate) const JSONRPC_INVALID_MESSAGE_ERROR_CODE: i32 = -32700;
55pub(crate) const JSONRPC_INVALID_MESSAGE_ERROR_MESSAGE: &str = "parse error";
56pub(crate) const JSONRPC_INTERNAL_ERROR_ERROR_CODE: i32 = -32603;
57pub(crate) const JSONRPC_INTERNAL_ERROR_ERROR_MESSAGE: &str = "Internal error";
58
59pub(crate) const LSPS0_CLIENT_REJECTED_ERROR_CODE: i32 = 1;
60
61#[derive(Copy, Clone, Debug, PartialEq, Eq)]
62pub(crate) enum LSPSMethod {
63	LSPS0ListProtocols,
64	LSPS1GetInfo,
65	LSPS1GetOrder,
66	LSPS1CreateOrder,
67	LSPS2GetInfo,
68	LSPS2Buy,
69	LSPS5SetWebhook,
70	LSPS5ListWebhooks,
71	LSPS5RemoveWebhook,
72}
73
74impl LSPSMethod {
75	fn as_static_str(&self) -> &'static str {
76		match self {
77			Self::LSPS0ListProtocols => LSPS0_LISTPROTOCOLS_METHOD_NAME,
78			Self::LSPS1GetInfo => LSPS1_GET_INFO_METHOD_NAME,
79			Self::LSPS1CreateOrder => LSPS1_CREATE_ORDER_METHOD_NAME,
80			Self::LSPS1GetOrder => LSPS1_GET_ORDER_METHOD_NAME,
81			Self::LSPS2GetInfo => LSPS2_GET_INFO_METHOD_NAME,
82			Self::LSPS2Buy => LSPS2_BUY_METHOD_NAME,
83			Self::LSPS5SetWebhook => LSPS5_SET_WEBHOOK_METHOD_NAME,
84			Self::LSPS5ListWebhooks => LSPS5_LIST_WEBHOOKS_METHOD_NAME,
85			Self::LSPS5RemoveWebhook => LSPS5_REMOVE_WEBHOOK_METHOD_NAME,
86		}
87	}
88}
89
90impl FromStr for LSPSMethod {
91	type Err = &'static str;
92	fn from_str(s: &str) -> Result<Self, Self::Err> {
93		match s {
94			LSPS0_LISTPROTOCOLS_METHOD_NAME => Ok(Self::LSPS0ListProtocols),
95			LSPS1_GET_INFO_METHOD_NAME => Ok(Self::LSPS1GetInfo),
96			LSPS1_CREATE_ORDER_METHOD_NAME => Ok(Self::LSPS1CreateOrder),
97			LSPS1_GET_ORDER_METHOD_NAME => Ok(Self::LSPS1GetOrder),
98			LSPS2_GET_INFO_METHOD_NAME => Ok(Self::LSPS2GetInfo),
99			LSPS2_BUY_METHOD_NAME => Ok(Self::LSPS2Buy),
100			LSPS5_SET_WEBHOOK_METHOD_NAME => Ok(Self::LSPS5SetWebhook),
101			LSPS5_LIST_WEBHOOKS_METHOD_NAME => Ok(Self::LSPS5ListWebhooks),
102			LSPS5_REMOVE_WEBHOOK_METHOD_NAME => Ok(Self::LSPS5RemoveWebhook),
103			_ => Err(&"Unknown method name"),
104		}
105	}
106}
107
108impl From<&LSPS0Request> for LSPSMethod {
109	fn from(value: &LSPS0Request) -> Self {
110		match value {
111			LSPS0Request::ListProtocols(_) => Self::LSPS0ListProtocols,
112		}
113	}
114}
115
116impl From<&LSPS1Request> for LSPSMethod {
117	fn from(value: &LSPS1Request) -> Self {
118		match value {
119			LSPS1Request::GetInfo(_) => Self::LSPS1GetInfo,
120			LSPS1Request::CreateOrder(_) => Self::LSPS1CreateOrder,
121			LSPS1Request::GetOrder(_) => Self::LSPS1GetOrder,
122		}
123	}
124}
125
126impl From<&LSPS2Request> for LSPSMethod {
127	fn from(value: &LSPS2Request) -> Self {
128		match value {
129			LSPS2Request::GetInfo(_) => Self::LSPS2GetInfo,
130			LSPS2Request::Buy(_) => Self::LSPS2Buy,
131		}
132	}
133}
134
135impl From<&LSPS5Request> for LSPSMethod {
136	fn from(value: &LSPS5Request) -> Self {
137		match value {
138			LSPS5Request::SetWebhook(_) => Self::LSPS5SetWebhook,
139			LSPS5Request::ListWebhooks(_) => Self::LSPS5ListWebhooks,
140			LSPS5Request::RemoveWebhook(_) => Self::LSPS5RemoveWebhook,
141		}
142	}
143}
144
145impl<'de> Deserialize<'de> for LSPSMethod {
146	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
147	where
148		D: Deserializer<'de>,
149	{
150		let s = <&str>::deserialize(deserializer)?;
151		FromStr::from_str(&s).map_err(de::Error::custom)
152	}
153}
154
155impl Serialize for LSPSMethod {
156	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
157	where
158		S: serde::Serializer,
159	{
160		serializer.serialize_str(&self.as_static_str())
161	}
162}
163
164/// The Lightning message type id for LSPS messages.
165pub const LSPS_MESSAGE_TYPE_ID: u16 = 37913;
166
167/// A trait used to implement a specific LSPS protocol.
168///
169/// The messages the protocol uses need to be able to be mapped
170/// from and into [`LSPSMessage`].
171pub(crate) trait LSPSProtocolMessageHandler {
172	type ProtocolMessage: TryFrom<LSPSMessage> + Into<LSPSMessage>;
173	const PROTOCOL_NUMBER: Option<u16>;
174
175	fn handle_message(
176		&self, message: Self::ProtocolMessage, counterparty_node_id: &PublicKey,
177	) -> Result<(), LightningError>;
178}
179
180/// Lightning message type used by LSPS protocols.
181#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
182pub struct RawLSPSMessage {
183	/// The raw string payload that holds the actual message.
184	pub payload: String,
185}
186
187// We encode `RawLSPSMessage`'s payload without a length prefix as LSPS0 expects it to be the
188// remainder of the object.
189impl lightning::util::ser::Writeable for RawLSPSMessage {
190	fn write<W: lightning::util::ser::Writer>(
191		&self, w: &mut W,
192	) -> Result<(), lightning::io::Error> {
193		WithoutLength(&self.payload).write(w)?;
194		Ok(())
195	}
196}
197
198impl LengthReadable for RawLSPSMessage {
199	fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
200		let payload_without_length: WithoutLength<String> =
201			LengthReadable::read_from_fixed_length_buffer(r)?;
202		Ok(Self { payload: payload_without_length.0 })
203	}
204}
205
206impl wire::Type for RawLSPSMessage {
207	fn type_id(&self) -> u16 {
208		LSPS_MESSAGE_TYPE_ID
209	}
210}
211
212/// A JSON-RPC request's `id`.
213///
214/// Please refer to the [JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification#request_object) for
215/// more information.
216#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
217#[serde(transparent)]
218pub struct LSPSRequestId(pub String);
219
220impl Writeable for LSPSRequestId {
221	fn write<W: lightning::util::ser::Writer>(
222		&self, writer: &mut W,
223	) -> Result<(), lightning::io::Error> {
224		self.0.write(writer)?;
225		Ok(())
226	}
227}
228
229impl Readable for LSPSRequestId {
230	fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
231		let s: String = Readable::read(reader)?;
232		Ok(Self(s))
233	}
234}
235
236/// An object representing datetimes as described in bLIP-50 / LSPS0.
237#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
238#[serde(transparent)]
239pub struct LSPSDateTime(pub chrono::DateTime<chrono::Utc>);
240
241impl LSPSDateTime {
242	/// Returns the LSPSDateTime as RFC3339 formatted string.
243	pub fn to_rfc3339(&self) -> String {
244		self.0.to_rfc3339()
245	}
246
247	/// Returns if the given time is in the past.
248	#[cfg(feature = "time")]
249	pub fn is_past(&self) -> bool {
250		let now_seconds_since_epoch = SystemTime::now()
251			.duration_since(UNIX_EPOCH)
252			.expect("system clock to be ahead of the unix epoch")
253			.as_secs();
254		let datetime_seconds_since_epoch =
255			self.0.timestamp().try_into().expect("expiration to be ahead of unix epoch");
256		now_seconds_since_epoch > datetime_seconds_since_epoch
257	}
258
259	/// Returns the absolute difference between two datetimes as a `Duration`.
260	pub fn duration_since(&self, other: &Self) -> Duration {
261		let diff_secs = self.0.timestamp().abs_diff(other.0.timestamp());
262		Duration::from_secs(diff_secs)
263	}
264
265	/// Returns the time in seconds since the unix epoch.
266	pub fn new_from_duration_since_epoch(duration: Duration) -> Self {
267		Self(chrono::DateTime::UNIX_EPOCH + duration)
268	}
269}
270
271impl FromStr for LSPSDateTime {
272	type Err = ();
273	fn from_str(s: &str) -> Result<Self, Self::Err> {
274		let datetime = chrono::DateTime::parse_from_rfc3339(s).map_err(|_| ())?;
275		Ok(Self(datetime.into()))
276	}
277}
278
279impl Display for LSPSDateTime {
280	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281		write!(f, "{}", self.to_rfc3339())
282	}
283}
284
285impl Writeable for LSPSDateTime {
286	fn write<W: lightning::util::ser::Writer>(
287		&self, writer: &mut W,
288	) -> Result<(), lightning::io::Error> {
289		self.to_rfc3339().write(writer)?;
290		Ok(())
291	}
292}
293
294impl Readable for LSPSDateTime {
295	fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
296		let s: String = Readable::read(reader)?;
297		let val = Self::from_str(&s).map_err(|_| lightning::ln::msgs::DecodeError::InvalidValue)?;
298		Ok(val)
299	}
300}
301
302/// An error returned in response to an JSON-RPC request.
303///
304/// Please refer to the [JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification#error_object) for
305/// more information.
306#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
307pub struct LSPSResponseError {
308	/// A number that indicates the error type that occurred.
309	pub code: i32,
310	/// A string providing a short description of the error.
311	pub message: String,
312	/// A primitive or structured value that contains additional information about the error.
313	pub data: Option<String>,
314}
315
316/// A (de-)serializable LSPS message allowing to be sent over the wire.
317#[derive(Clone, Debug, PartialEq, Eq)]
318pub enum LSPSMessage {
319	/// An invalid variant.
320	Invalid(LSPSResponseError),
321	/// An LSPS0 message.
322	LSPS0(LSPS0Message),
323	/// An LSPS1 message.
324	LSPS1(LSPS1Message),
325	/// An LSPS2 message.
326	LSPS2(LSPS2Message),
327	/// An LSPS5 message.
328	LSPS5(LSPS5Message),
329}
330
331impl LSPSMessage {
332	/// A constructor returning an `LSPSMessage` from a raw JSON string.
333	///
334	/// The given `request_id_to_method` associates request ids with method names, as response objects
335	/// don't carry the latter.
336	pub(crate) fn from_str_with_id_map(
337		json_str: &str, request_id_to_method_map: &mut HashMap<LSPSRequestId, LSPSMethod>,
338	) -> Result<Self, serde_json::Error> {
339		let deserializer = &mut serde_json::Deserializer::from_str(json_str);
340		let visitor = LSPSMessageVisitor { request_id_to_method_map };
341		deserializer.deserialize_any(visitor)
342	}
343
344	/// Returns the request id and the method.
345	pub(crate) fn get_request_id_and_method(&self) -> Option<(LSPSRequestId, LSPSMethod)> {
346		match self {
347			LSPSMessage::LSPS0(LSPS0Message::Request(request_id, request)) => {
348				Some((LSPSRequestId(request_id.0.clone()), request.into()))
349			},
350			LSPSMessage::LSPS1(LSPS1Message::Request(request_id, request)) => {
351				Some((LSPSRequestId(request_id.0.clone()), request.into()))
352			},
353			LSPSMessage::LSPS2(LSPS2Message::Request(request_id, request)) => {
354				Some((LSPSRequestId(request_id.0.clone()), request.into()))
355			},
356			LSPSMessage::LSPS5(LSPS5Message::Request(request_id, request)) => {
357				Some((LSPSRequestId(request_id.0.clone()), request.into()))
358			},
359			_ => None,
360		}
361	}
362}
363
364impl Serialize for LSPSMessage {
365	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
366	where
367		S: serde::Serializer,
368	{
369		let mut jsonrpc_object =
370			serializer.serialize_struct(LSPS_MESSAGE_SERIALIZED_STRUCT_NAME, 3)?;
371
372		jsonrpc_object.serialize_field(JSONRPC_FIELD_KEY, JSONRPC_FIELD_VALUE)?;
373
374		match self {
375			LSPSMessage::LSPS0(LSPS0Message::Request(request_id, request)) => {
376				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
377				jsonrpc_object
378					.serialize_field(JSONRPC_METHOD_FIELD_KEY, &LSPSMethod::from(request))?;
379
380				match request {
381					LSPS0Request::ListProtocols(params) => {
382						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
383					},
384				};
385			},
386			LSPSMessage::LSPS0(LSPS0Message::Response(request_id, response)) => {
387				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
388
389				match response {
390					LSPS0Response::ListProtocols(result) => {
391						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?;
392					},
393					LSPS0Response::ListProtocolsError(error) => {
394						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?;
395					},
396				}
397			},
398			LSPSMessage::LSPS1(LSPS1Message::Request(request_id, request)) => {
399				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
400				jsonrpc_object
401					.serialize_field(JSONRPC_METHOD_FIELD_KEY, &LSPSMethod::from(request))?;
402
403				match request {
404					LSPS1Request::GetInfo(params) => {
405						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
406					},
407					LSPS1Request::CreateOrder(params) => {
408						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
409					},
410					LSPS1Request::GetOrder(params) => {
411						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
412					},
413				}
414			},
415			LSPSMessage::LSPS1(LSPS1Message::Response(request_id, response)) => {
416				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
417
418				match response {
419					LSPS1Response::GetInfo(result) => {
420						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
421					},
422					LSPS1Response::GetInfoError(error) => {
423						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
424					},
425					LSPS1Response::CreateOrder(result) => {
426						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
427					},
428					LSPS1Response::CreateOrderError(error) => {
429						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
430					},
431					LSPS1Response::GetOrder(result) => {
432						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
433					},
434					LSPS1Response::GetOrderError(error) => {
435						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
436					},
437				}
438			},
439			LSPSMessage::LSPS2(LSPS2Message::Request(request_id, request)) => {
440				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
441				jsonrpc_object
442					.serialize_field(JSONRPC_METHOD_FIELD_KEY, &LSPSMethod::from(request))?;
443
444				match request {
445					LSPS2Request::GetInfo(params) => {
446						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
447					},
448					LSPS2Request::Buy(params) => {
449						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
450					},
451				}
452			},
453			LSPSMessage::LSPS2(LSPS2Message::Response(request_id, response)) => {
454				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
455
456				match response {
457					LSPS2Response::GetInfo(result) => {
458						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
459					},
460					LSPS2Response::GetInfoError(error) => {
461						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
462					},
463					LSPS2Response::Buy(result) => {
464						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
465					},
466					LSPS2Response::BuyError(error) => {
467						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
468					},
469				}
470			},
471			LSPSMessage::Invalid(error) => {
472				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &serde_json::Value::Null)?;
473				jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, &error)?;
474			},
475			LSPSMessage::LSPS5(LSPS5Message::Request(request_id, request)) => {
476				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
477				jsonrpc_object
478					.serialize_field(JSONRPC_METHOD_FIELD_KEY, &LSPSMethod::from(request))?;
479
480				match request {
481					LSPS5Request::SetWebhook(params) => {
482						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
483					},
484					LSPS5Request::ListWebhooks(params) => {
485						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
486					},
487					LSPS5Request::RemoveWebhook(params) => {
488						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
489					},
490				}
491			},
492			LSPSMessage::LSPS5(LSPS5Message::Response(request_id, response)) => {
493				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
494
495				match response {
496					LSPS5Response::SetWebhook(result) => {
497						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
498					},
499					LSPS5Response::SetWebhookError(error) => {
500						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
501					},
502					LSPS5Response::ListWebhooks(result) => {
503						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
504					},
505					LSPS5Response::RemoveWebhook(result) => {
506						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
507					},
508					LSPS5Response::RemoveWebhookError(error) => {
509						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
510					},
511				}
512			},
513		}
514
515		jsonrpc_object.end()
516	}
517}
518
519struct LSPSMessageVisitor<'a> {
520	request_id_to_method_map: &'a mut HashMap<LSPSRequestId, LSPSMethod>,
521}
522
523impl<'de, 'a> Visitor<'de> for LSPSMessageVisitor<'a> {
524	type Value = LSPSMessage;
525
526	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
527		formatter.write_str("JSON-RPC object")
528	}
529
530	fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
531	where
532		A: MapAccess<'de>,
533	{
534		let mut id: Option<LSPSRequestId> = None;
535		let mut method: Option<LSPSMethod> = None;
536		let mut params = None;
537		let mut result = None;
538		let mut error: Option<LSPSResponseError> = None;
539
540		while let Some(key) = map.next_key()? {
541			match key {
542				"id" => {
543					id = map.next_value()?;
544				},
545				"method" => {
546					method = Some(map.next_value()?);
547				},
548				"params" => {
549					params = Some(map.next_value()?);
550				},
551				"result" => {
552					result = Some(map.next_value()?);
553				},
554				"error" => {
555					error = Some(map.next_value()?);
556				},
557				_ => {
558					let _: serde_json::Value = map.next_value()?;
559				},
560			}
561		}
562
563		let id = match id {
564			Some(id) => id,
565			None => {
566				if let Some(method) = method {
567					return Err(de::Error::custom(format!(
568						"Received unknown notification: {}",
569						method.as_static_str()
570					)));
571				} else {
572					if let Some(error) = error {
573						if error.code == JSONRPC_INVALID_MESSAGE_ERROR_CODE {
574							return Ok(LSPSMessage::Invalid(error));
575						}
576					}
577
578					return Err(de::Error::custom("Received unknown error message"));
579				}
580			},
581		};
582
583		match method {
584			Some(method) => match method {
585				LSPSMethod::LSPS0ListProtocols => Ok(LSPSMessage::LSPS0(LSPS0Message::Request(
586					id,
587					LSPS0Request::ListProtocols(LSPS0ListProtocolsRequest {}),
588				))),
589				LSPSMethod::LSPS1GetInfo => {
590					let request = serde_json::from_value(params.unwrap_or(json!({})))
591						.map_err(de::Error::custom)?;
592					Ok(LSPSMessage::LSPS1(LSPS1Message::Request(
593						id,
594						LSPS1Request::GetInfo(request),
595					)))
596				},
597				LSPSMethod::LSPS1CreateOrder => {
598					let request = serde_json::from_value(params.unwrap_or(json!({})))
599						.map_err(de::Error::custom)?;
600					Ok(LSPSMessage::LSPS1(LSPS1Message::Request(
601						id,
602						LSPS1Request::CreateOrder(request),
603					)))
604				},
605				LSPSMethod::LSPS1GetOrder => {
606					let request = serde_json::from_value(params.unwrap_or(json!({})))
607						.map_err(de::Error::custom)?;
608					Ok(LSPSMessage::LSPS1(LSPS1Message::Request(
609						id,
610						LSPS1Request::GetOrder(request),
611					)))
612				},
613				LSPSMethod::LSPS2GetInfo => {
614					let request = serde_json::from_value(params.unwrap_or(json!({})))
615						.map_err(de::Error::custom)?;
616					Ok(LSPSMessage::LSPS2(LSPS2Message::Request(
617						id,
618						LSPS2Request::GetInfo(request),
619					)))
620				},
621				LSPSMethod::LSPS2Buy => {
622					let request = serde_json::from_value(params.unwrap_or(json!({})))
623						.map_err(de::Error::custom)?;
624					Ok(LSPSMessage::LSPS2(LSPS2Message::Request(id, LSPS2Request::Buy(request))))
625				},
626				LSPSMethod::LSPS5SetWebhook => {
627					let request = serde_json::from_value(params.unwrap_or(json!({})))
628						.map_err(de::Error::custom)?;
629					Ok(LSPSMessage::LSPS5(LSPS5Message::Request(
630						id,
631						LSPS5Request::SetWebhook(request),
632					)))
633				},
634				LSPSMethod::LSPS5ListWebhooks => {
635					let request = serde_json::from_value(params.unwrap_or(json!({})))
636						.map_err(de::Error::custom)?;
637					Ok(LSPSMessage::LSPS5(LSPS5Message::Request(
638						id,
639						LSPS5Request::ListWebhooks(request),
640					)))
641				},
642				LSPSMethod::LSPS5RemoveWebhook => {
643					let request = serde_json::from_value(params.unwrap_or(json!({})))
644						.map_err(de::Error::custom)?;
645					Ok(LSPSMessage::LSPS5(LSPS5Message::Request(
646						id,
647						LSPS5Request::RemoveWebhook(request),
648					)))
649				},
650			},
651			None => match self.request_id_to_method_map.remove(&id) {
652				Some(method) => match method {
653					LSPSMethod::LSPS0ListProtocols => {
654						if let Some(error) = error {
655							Ok(LSPSMessage::LSPS0(LSPS0Message::Response(
656								id,
657								LSPS0Response::ListProtocolsError(error),
658							)))
659						} else if let Some(result) = result {
660							let list_protocols_response =
661								serde_json::from_value(result).map_err(de::Error::custom)?;
662							Ok(LSPSMessage::LSPS0(LSPS0Message::Response(
663								id,
664								LSPS0Response::ListProtocols(list_protocols_response),
665							)))
666						} else {
667							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
668						}
669					},
670					LSPSMethod::LSPS1GetInfo => {
671						if let Some(error) = error {
672							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
673								id,
674								LSPS1Response::GetInfoError(error),
675							)))
676						} else if let Some(result) = result {
677							let response =
678								serde_json::from_value(result).map_err(de::Error::custom)?;
679							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
680								id,
681								LSPS1Response::GetInfo(response),
682							)))
683						} else {
684							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
685						}
686					},
687					LSPSMethod::LSPS1CreateOrder => {
688						if let Some(error) = error {
689							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
690								id,
691								LSPS1Response::CreateOrderError(error),
692							)))
693						} else if let Some(result) = result {
694							let response =
695								serde_json::from_value(result).map_err(de::Error::custom)?;
696							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
697								id,
698								LSPS1Response::CreateOrder(response),
699							)))
700						} else {
701							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
702						}
703					},
704					LSPSMethod::LSPS1GetOrder => {
705						if let Some(error) = error {
706							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
707								id,
708								LSPS1Response::GetOrderError(error),
709							)))
710						} else if let Some(result) = result {
711							let response =
712								serde_json::from_value(result).map_err(de::Error::custom)?;
713							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
714								id,
715								LSPS1Response::GetOrder(response),
716							)))
717						} else {
718							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
719						}
720					},
721					LSPSMethod::LSPS2GetInfo => {
722						if let Some(error) = error {
723							Ok(LSPSMessage::LSPS2(LSPS2Message::Response(
724								id,
725								LSPS2Response::GetInfoError(error),
726							)))
727						} else if let Some(result) = result {
728							let response =
729								serde_json::from_value(result).map_err(de::Error::custom)?;
730							Ok(LSPSMessage::LSPS2(LSPS2Message::Response(
731								id,
732								LSPS2Response::GetInfo(response),
733							)))
734						} else {
735							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
736						}
737					},
738					LSPSMethod::LSPS2Buy => {
739						if let Some(error) = error {
740							Ok(LSPSMessage::LSPS2(LSPS2Message::Response(
741								id,
742								LSPS2Response::BuyError(error),
743							)))
744						} else if let Some(result) = result {
745							let response =
746								serde_json::from_value(result).map_err(de::Error::custom)?;
747							Ok(LSPSMessage::LSPS2(LSPS2Message::Response(
748								id,
749								LSPS2Response::Buy(response),
750							)))
751						} else {
752							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
753						}
754					},
755					LSPSMethod::LSPS5SetWebhook => {
756						if let Some(error) = error {
757							Ok(LSPSMessage::LSPS5(LSPS5Message::Response(
758								id,
759								LSPS5Response::SetWebhookError(error.into()),
760							)))
761						} else if let Some(result) = result {
762							let response =
763								serde_json::from_value(result).map_err(de::Error::custom)?;
764							Ok(LSPSMessage::LSPS5(LSPS5Message::Response(
765								id,
766								LSPS5Response::SetWebhook(response),
767							)))
768						} else {
769							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
770						}
771					},
772					LSPSMethod::LSPS5ListWebhooks => {
773						if let Some(result) = result {
774							let response =
775								serde_json::from_value(result).map_err(de::Error::custom)?;
776							Ok(LSPSMessage::LSPS5(LSPS5Message::Response(
777								id,
778								LSPS5Response::ListWebhooks(response),
779							)))
780						} else {
781							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
782						}
783					},
784					LSPSMethod::LSPS5RemoveWebhook => {
785						if let Some(error) = error {
786							Ok(LSPSMessage::LSPS5(LSPS5Message::Response(
787								id,
788								LSPS5Response::RemoveWebhookError(error.into()),
789							)))
790						} else if let Some(result) = result {
791							let response =
792								serde_json::from_value(result).map_err(de::Error::custom)?;
793							Ok(LSPSMessage::LSPS5(LSPS5Message::Response(
794								id,
795								LSPS5Response::RemoveWebhook(response),
796							)))
797						} else {
798							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
799						}
800					},
801				},
802				None => Err(de::Error::custom(format!(
803					"Received response for unknown request id: {}",
804					id.0
805				))),
806			},
807		}
808	}
809}
810
811pub(crate) mod string_amount {
812	use alloc::string::{String, ToString};
813	use core::str::FromStr;
814	use serde::de::Unexpected;
815	use serde::{Deserialize, Deserializer, Serializer};
816
817	pub(crate) fn serialize<S>(x: &u64, s: S) -> Result<S::Ok, S::Error>
818	where
819		S: Serializer,
820	{
821		s.serialize_str(&x.to_string())
822	}
823
824	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
825	where
826		D: Deserializer<'de>,
827	{
828		let buf = String::deserialize(deserializer)?;
829
830		u64::from_str(&buf).map_err(|_| {
831			serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid u64 amount string")
832		})
833	}
834}
835
836pub(crate) mod string_amount_option {
837	use alloc::string::{String, ToString};
838	use core::str::FromStr;
839	use serde::de::Unexpected;
840	use serde::{Deserialize, Deserializer, Serialize, Serializer};
841
842	pub(crate) fn serialize<S>(x: &Option<u64>, s: S) -> Result<S::Ok, S::Error>
843	where
844		S: Serializer,
845	{
846		let v = x.as_ref().map(|v| v.to_string());
847		Option::<String>::serialize(&v, s)
848	}
849
850	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
851	where
852		D: Deserializer<'de>,
853	{
854		if let Some(buf) = Option::<String>::deserialize(deserializer)? {
855			let val = u64::from_str(&buf).map_err(|_| {
856				serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid u64 amount string")
857			})?;
858			Ok(Some(val))
859		} else {
860			Ok(None)
861		}
862	}
863}
864
865pub(crate) mod string_offer {
866	use alloc::string::{String, ToString};
867	use core::str::FromStr;
868	use lightning::offers::offer::Offer;
869	use serde::de::Unexpected;
870	use serde::{Deserialize, Deserializer, Serializer};
871
872	pub(crate) fn serialize<S>(x: &Offer, s: S) -> Result<S::Ok, S::Error>
873	where
874		S: Serializer,
875	{
876		s.serialize_str(&x.to_string())
877	}
878
879	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Offer, D::Error>
880	where
881		D: Deserializer<'de>,
882	{
883		let buf = String::deserialize(deserializer)?;
884
885		Offer::from_str(&buf).map_err(|_| {
886			serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid offer string")
887		})
888	}
889}
890
891pub(crate) mod unchecked_address {
892	use alloc::string::{String, ToString};
893	use bitcoin::Address;
894	use core::str::FromStr;
895	use serde::de::Unexpected;
896	use serde::{Deserialize, Deserializer, Serializer};
897
898	pub(crate) fn serialize<S>(x: &Address, s: S) -> Result<S::Ok, S::Error>
899	where
900		S: Serializer,
901	{
902		s.serialize_str(&x.to_string())
903	}
904
905	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Address, D::Error>
906	where
907		D: Deserializer<'de>,
908	{
909		let buf = String::deserialize(deserializer)?;
910
911		let parsed_addr = Address::from_str(&buf).map_err(|_| {
912			serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid address string")
913		})?;
914		Ok(parsed_addr.assume_checked())
915	}
916}
917
918pub(crate) mod unchecked_address_option {
919	use alloc::string::{String, ToString};
920	use bitcoin::Address;
921	use core::str::FromStr;
922	use serde::de::Unexpected;
923	use serde::{Deserialize, Deserializer, Serialize, Serializer};
924
925	pub(crate) fn serialize<S>(x: &Option<Address>, s: S) -> Result<S::Ok, S::Error>
926	where
927		S: Serializer,
928	{
929		let v = x.as_ref().map(|v| v.to_string());
930		Option::<String>::serialize(&v, s)
931	}
932
933	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<bitcoin::Address>, D::Error>
934	where
935		D: Deserializer<'de>,
936	{
937		if let Some(buf) = Option::<String>::deserialize(deserializer)? {
938			let val = Address::from_str(&buf).map_err(|_| {
939				serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid address string")
940			})?;
941			Ok(Some(val.assume_checked()))
942		} else {
943			Ok(None)
944		}
945	}
946}
947
948pub(crate) mod u32_fee_rate {
949	use bitcoin::FeeRate;
950	use serde::{Deserialize, Deserializer, Serializer};
951
952	pub(crate) fn serialize<S>(x: &FeeRate, s: S) -> Result<S::Ok, S::Error>
953	where
954		S: Serializer,
955	{
956		let fee_rate_sat_kwu = x.to_sat_per_kwu();
957		s.serialize_u32(fee_rate_sat_kwu as u32)
958	}
959
960	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<FeeRate, D::Error>
961	where
962		D: Deserializer<'de>,
963	{
964		let fee_rate_sat_kwu = u32::deserialize(deserializer)?;
965
966		Ok(FeeRate::from_sat_per_kwu(fee_rate_sat_kwu as u64))
967	}
968}
969
970#[cfg(test)]
971mod tests {
972	use super::*;
973
974	use lightning::io::Cursor;
975
976	#[test]
977	fn datetime_serializaton() {
978		let expected_datetime = LSPSDateTime::from_str("2035-05-20T08:30:45Z").unwrap();
979		let mut buf = Vec::new();
980		expected_datetime.write(&mut buf).unwrap();
981		let decoded_datetime: LSPSDateTime = Readable::read(&mut Cursor::new(buf)).unwrap();
982		assert_eq!(expected_datetime, decoded_datetime);
983	}
984}