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 [LSPS0 specification](https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS0) for more information.
4
5use crate::lsps0::msgs::{
6	LSPS0Message, LSPS0Request, LSPS0Response, ListProtocolsRequest,
7	LSPS0_LISTPROTOCOLS_METHOD_NAME,
8};
9
10use crate::lsps1::msgs::{
11	LSPS1Message, LSPS1Request, LSPS1Response, LSPS1_CREATE_ORDER_METHOD_NAME,
12	LSPS1_GET_INFO_METHOD_NAME, LSPS1_GET_ORDER_METHOD_NAME,
13};
14use crate::lsps2::msgs::{
15	LSPS2Message, LSPS2Request, LSPS2Response, LSPS2_BUY_METHOD_NAME, LSPS2_GET_INFO_METHOD_NAME,
16};
17use crate::prelude::{HashMap, String};
18
19use lightning::ln::msgs::LightningError;
20use lightning::ln::wire;
21use lightning::util::ser::WithoutLength;
22
23use bitcoin::secp256k1::PublicKey;
24
25use core::fmt;
26use core::str::FromStr;
27
28use serde::de::{self, MapAccess, Visitor};
29use serde::ser::SerializeStruct;
30use serde::{Deserialize, Deserializer, Serialize};
31use serde_json::json;
32
33pub(crate) const LSPS_MESSAGE_SERIALIZED_STRUCT_NAME: &str = "LSPSMessage";
34pub(crate) const JSONRPC_FIELD_KEY: &str = "jsonrpc";
35pub(crate) const JSONRPC_FIELD_VALUE: &str = "2.0";
36pub(crate) const JSONRPC_METHOD_FIELD_KEY: &str = "method";
37pub(crate) const JSONRPC_ID_FIELD_KEY: &str = "id";
38pub(crate) const JSONRPC_PARAMS_FIELD_KEY: &str = "params";
39pub(crate) const JSONRPC_RESULT_FIELD_KEY: &str = "result";
40pub(crate) const JSONRPC_ERROR_FIELD_KEY: &str = "error";
41pub(crate) const JSONRPC_INVALID_MESSAGE_ERROR_CODE: i32 = -32700;
42pub(crate) const JSONRPC_INVALID_MESSAGE_ERROR_MESSAGE: &str = "parse error";
43pub(crate) const JSONRPC_INTERNAL_ERROR_ERROR_CODE: i32 = -32603;
44pub(crate) const JSONRPC_INTERNAL_ERROR_ERROR_MESSAGE: &str = "Internal error";
45
46pub(crate) const LSPS0_CLIENT_REJECTED_ERROR_CODE: i32 = 1;
47
48#[derive(Copy, Clone, Debug, PartialEq, Eq)]
49pub(crate) enum LSPSMethod {
50	LSPS0ListProtocols,
51	LSPS1GetInfo,
52	LSPS1GetOrder,
53	LSPS1CreateOrder,
54	LSPS2GetInfo,
55	LSPS2Buy,
56}
57
58impl LSPSMethod {
59	fn as_static_str(&self) -> &'static str {
60		match self {
61			Self::LSPS0ListProtocols => LSPS0_LISTPROTOCOLS_METHOD_NAME,
62			Self::LSPS1GetInfo => LSPS1_GET_INFO_METHOD_NAME,
63			Self::LSPS1CreateOrder => LSPS1_CREATE_ORDER_METHOD_NAME,
64			Self::LSPS1GetOrder => LSPS1_GET_ORDER_METHOD_NAME,
65			Self::LSPS2GetInfo => LSPS2_GET_INFO_METHOD_NAME,
66			Self::LSPS2Buy => LSPS2_BUY_METHOD_NAME,
67		}
68	}
69}
70
71impl FromStr for LSPSMethod {
72	type Err = &'static str;
73	fn from_str(s: &str) -> Result<Self, Self::Err> {
74		match s {
75			LSPS0_LISTPROTOCOLS_METHOD_NAME => Ok(Self::LSPS0ListProtocols),
76			LSPS1_GET_INFO_METHOD_NAME => Ok(Self::LSPS1GetInfo),
77			LSPS1_CREATE_ORDER_METHOD_NAME => Ok(Self::LSPS1CreateOrder),
78			LSPS1_GET_ORDER_METHOD_NAME => Ok(Self::LSPS1GetOrder),
79			LSPS2_GET_INFO_METHOD_NAME => Ok(Self::LSPS2GetInfo),
80			LSPS2_BUY_METHOD_NAME => Ok(Self::LSPS2Buy),
81			_ => Err(&"Unknown method name"),
82		}
83	}
84}
85
86impl From<&LSPS0Request> for LSPSMethod {
87	fn from(value: &LSPS0Request) -> Self {
88		match value {
89			LSPS0Request::ListProtocols(_) => Self::LSPS0ListProtocols,
90		}
91	}
92}
93
94impl From<&LSPS1Request> for LSPSMethod {
95	fn from(value: &LSPS1Request) -> Self {
96		match value {
97			LSPS1Request::GetInfo(_) => Self::LSPS1GetInfo,
98			LSPS1Request::CreateOrder(_) => Self::LSPS1CreateOrder,
99			LSPS1Request::GetOrder(_) => Self::LSPS1GetOrder,
100		}
101	}
102}
103
104impl From<&LSPS2Request> for LSPSMethod {
105	fn from(value: &LSPS2Request) -> Self {
106		match value {
107			LSPS2Request::GetInfo(_) => Self::LSPS2GetInfo,
108			LSPS2Request::Buy(_) => Self::LSPS2Buy,
109		}
110	}
111}
112
113impl<'de> Deserialize<'de> for LSPSMethod {
114	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
115	where
116		D: Deserializer<'de>,
117	{
118		let s = <&str>::deserialize(deserializer)?;
119		FromStr::from_str(&s).map_err(de::Error::custom)
120	}
121}
122
123impl Serialize for LSPSMethod {
124	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
125	where
126		S: serde::Serializer,
127	{
128		serializer.serialize_str(&self.as_static_str())
129	}
130}
131
132/// The Lightning message type id for LSPS messages.
133pub const LSPS_MESSAGE_TYPE_ID: u16 = 37913;
134
135/// A trait used to implement a specific LSPS protocol.
136///
137/// The messages the protocol uses need to be able to be mapped
138/// from and into [`LSPSMessage`].
139pub(crate) trait ProtocolMessageHandler {
140	type ProtocolMessage: TryFrom<LSPSMessage> + Into<LSPSMessage>;
141	const PROTOCOL_NUMBER: Option<u16>;
142
143	fn handle_message(
144		&self, message: Self::ProtocolMessage, counterparty_node_id: &PublicKey,
145	) -> Result<(), LightningError>;
146}
147
148/// Lightning message type used by LSPS protocols.
149#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
150pub struct RawLSPSMessage {
151	/// The raw string payload that holds the actual message.
152	pub payload: String,
153}
154
155// We encode `RawLSPSMessage`'s payload without a length prefix as LSPS0 expects it to be the
156// remainder of the object.
157impl lightning::util::ser::Writeable for RawLSPSMessage {
158	fn write<W: lightning::util::ser::Writer>(
159		&self, w: &mut W,
160	) -> Result<(), lightning::io::Error> {
161		WithoutLength(&self.payload).write(w)?;
162		Ok(())
163	}
164}
165
166impl lightning::util::ser::Readable for RawLSPSMessage {
167	fn read<R: lightning::io::Read>(r: &mut R) -> Result<Self, lightning::ln::msgs::DecodeError> {
168		let payload_without_length = WithoutLength::read(r)?;
169		Ok(Self { payload: payload_without_length.0 })
170	}
171}
172
173impl wire::Type for RawLSPSMessage {
174	fn type_id(&self) -> u16 {
175		LSPS_MESSAGE_TYPE_ID
176	}
177}
178
179/// A JSON-RPC request's `id`.
180///
181/// Please refer to the [JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification#request_object) for
182/// more information.
183#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
184#[serde(transparent)]
185pub struct RequestId(pub String);
186
187/// An error returned in response to an JSON-RPC request.
188///
189/// Please refer to the [JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification#error_object) for
190/// more information.
191#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
192pub struct ResponseError {
193	/// A number that indicates the error type that occurred.
194	pub code: i32,
195	/// A string providing a short description of the error.
196	pub message: String,
197	/// A primitive or structured value that contains additional information about the error.
198	pub data: Option<String>,
199}
200
201/// A (de-)serializable LSPS message allowing to be sent over the wire.
202#[derive(Clone, Debug, PartialEq, Eq)]
203pub enum LSPSMessage {
204	/// An invalid variant.
205	Invalid(ResponseError),
206	/// An LSPS0 message.
207	LSPS0(LSPS0Message),
208	/// An LSPS1 message.
209	LSPS1(LSPS1Message),
210	/// An LSPS2 message.
211	LSPS2(LSPS2Message),
212}
213
214impl LSPSMessage {
215	/// A constructor returning an `LSPSMessage` from a raw JSON string.
216	///
217	/// The given `request_id_to_method` associates request ids with method names, as response objects
218	/// don't carry the latter.
219	pub(crate) fn from_str_with_id_map(
220		json_str: &str, request_id_to_method_map: &mut HashMap<RequestId, LSPSMethod>,
221	) -> Result<Self, serde_json::Error> {
222		let deserializer = &mut serde_json::Deserializer::from_str(json_str);
223		let visitor = LSPSMessageVisitor { request_id_to_method_map };
224		deserializer.deserialize_any(visitor)
225	}
226
227	/// Returns the request id and the method.
228	pub(crate) fn get_request_id_and_method(&self) -> Option<(RequestId, LSPSMethod)> {
229		match self {
230			LSPSMessage::LSPS0(LSPS0Message::Request(request_id, request)) => {
231				Some((RequestId(request_id.0.clone()), request.into()))
232			},
233			LSPSMessage::LSPS1(LSPS1Message::Request(request_id, request)) => {
234				Some((RequestId(request_id.0.clone()), request.into()))
235			},
236			LSPSMessage::LSPS2(LSPS2Message::Request(request_id, request)) => {
237				Some((RequestId(request_id.0.clone()), request.into()))
238			},
239			_ => None,
240		}
241	}
242}
243
244impl Serialize for LSPSMessage {
245	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
246	where
247		S: serde::Serializer,
248	{
249		let mut jsonrpc_object =
250			serializer.serialize_struct(LSPS_MESSAGE_SERIALIZED_STRUCT_NAME, 3)?;
251
252		jsonrpc_object.serialize_field(JSONRPC_FIELD_KEY, JSONRPC_FIELD_VALUE)?;
253
254		match self {
255			LSPSMessage::LSPS0(LSPS0Message::Request(request_id, request)) => {
256				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
257				jsonrpc_object
258					.serialize_field(JSONRPC_METHOD_FIELD_KEY, &LSPSMethod::from(request))?;
259
260				match request {
261					LSPS0Request::ListProtocols(params) => {
262						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
263					},
264				};
265			},
266			LSPSMessage::LSPS0(LSPS0Message::Response(request_id, response)) => {
267				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
268
269				match response {
270					LSPS0Response::ListProtocols(result) => {
271						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?;
272					},
273					LSPS0Response::ListProtocolsError(error) => {
274						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?;
275					},
276				}
277			},
278			LSPSMessage::LSPS1(LSPS1Message::Request(request_id, request)) => {
279				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
280				jsonrpc_object
281					.serialize_field(JSONRPC_METHOD_FIELD_KEY, &LSPSMethod::from(request))?;
282
283				match request {
284					LSPS1Request::GetInfo(params) => {
285						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
286					},
287					LSPS1Request::CreateOrder(params) => {
288						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
289					},
290					LSPS1Request::GetOrder(params) => {
291						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
292					},
293				}
294			},
295			LSPSMessage::LSPS1(LSPS1Message::Response(request_id, response)) => {
296				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
297
298				match response {
299					LSPS1Response::GetInfo(result) => {
300						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
301					},
302					LSPS1Response::GetInfoError(error) => {
303						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
304					},
305					LSPS1Response::CreateOrder(result) => {
306						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
307					},
308					LSPS1Response::CreateOrderError(error) => {
309						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
310					},
311					LSPS1Response::GetOrder(result) => {
312						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
313					},
314					LSPS1Response::GetOrderError(error) => {
315						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
316					},
317				}
318			},
319			LSPSMessage::LSPS2(LSPS2Message::Request(request_id, request)) => {
320				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
321				jsonrpc_object
322					.serialize_field(JSONRPC_METHOD_FIELD_KEY, &LSPSMethod::from(request))?;
323
324				match request {
325					LSPS2Request::GetInfo(params) => {
326						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
327					},
328					LSPS2Request::Buy(params) => {
329						jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)?
330					},
331				}
332			},
333			LSPSMessage::LSPS2(LSPS2Message::Response(request_id, response)) => {
334				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?;
335
336				match response {
337					LSPS2Response::GetInfo(result) => {
338						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
339					},
340					LSPS2Response::GetInfoError(error) => {
341						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
342					},
343					LSPS2Response::Buy(result) => {
344						jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)?
345					},
346					LSPS2Response::BuyError(error) => {
347						jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)?
348					},
349				}
350			},
351			LSPSMessage::Invalid(error) => {
352				jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &serde_json::Value::Null)?;
353				jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, &error)?;
354			},
355		}
356
357		jsonrpc_object.end()
358	}
359}
360
361struct LSPSMessageVisitor<'a> {
362	request_id_to_method_map: &'a mut HashMap<RequestId, LSPSMethod>,
363}
364
365impl<'de, 'a> Visitor<'de> for LSPSMessageVisitor<'a> {
366	type Value = LSPSMessage;
367
368	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
369		formatter.write_str("JSON-RPC object")
370	}
371
372	fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
373	where
374		A: MapAccess<'de>,
375	{
376		let mut id: Option<RequestId> = None;
377		let mut method: Option<LSPSMethod> = None;
378		let mut params = None;
379		let mut result = None;
380		let mut error: Option<ResponseError> = None;
381
382		while let Some(key) = map.next_key()? {
383			match key {
384				"id" => {
385					id = map.next_value()?;
386				},
387				"method" => {
388					method = Some(map.next_value()?);
389				},
390				"params" => {
391					params = Some(map.next_value()?);
392				},
393				"result" => {
394					result = Some(map.next_value()?);
395				},
396				"error" => {
397					error = Some(map.next_value()?);
398				},
399				_ => {
400					let _: serde_json::Value = map.next_value()?;
401				},
402			}
403		}
404
405		let id = match id {
406			Some(id) => id,
407			None => {
408				if let Some(method) = method {
409					return Err(de::Error::custom(format!(
410						"Received unknown notification: {}",
411						method.as_static_str()
412					)));
413				} else {
414					if let Some(error) = error {
415						if error.code == JSONRPC_INVALID_MESSAGE_ERROR_CODE {
416							return Ok(LSPSMessage::Invalid(error));
417						}
418					}
419
420					return Err(de::Error::custom("Received unknown error message"));
421				}
422			},
423		};
424
425		match method {
426			Some(method) => match method {
427				LSPSMethod::LSPS0ListProtocols => Ok(LSPSMessage::LSPS0(LSPS0Message::Request(
428					id,
429					LSPS0Request::ListProtocols(ListProtocolsRequest {}),
430				))),
431				LSPSMethod::LSPS1GetInfo => {
432					let request = serde_json::from_value(params.unwrap_or(json!({})))
433						.map_err(de::Error::custom)?;
434					Ok(LSPSMessage::LSPS1(LSPS1Message::Request(
435						id,
436						LSPS1Request::GetInfo(request),
437					)))
438				},
439				LSPSMethod::LSPS1CreateOrder => {
440					let request = serde_json::from_value(params.unwrap_or(json!({})))
441						.map_err(de::Error::custom)?;
442					Ok(LSPSMessage::LSPS1(LSPS1Message::Request(
443						id,
444						LSPS1Request::CreateOrder(request),
445					)))
446				},
447				LSPSMethod::LSPS1GetOrder => {
448					let request = serde_json::from_value(params.unwrap_or(json!({})))
449						.map_err(de::Error::custom)?;
450					Ok(LSPSMessage::LSPS1(LSPS1Message::Request(
451						id,
452						LSPS1Request::GetOrder(request),
453					)))
454				},
455				LSPSMethod::LSPS2GetInfo => {
456					let request = serde_json::from_value(params.unwrap_or(json!({})))
457						.map_err(de::Error::custom)?;
458					Ok(LSPSMessage::LSPS2(LSPS2Message::Request(
459						id,
460						LSPS2Request::GetInfo(request),
461					)))
462				},
463				LSPSMethod::LSPS2Buy => {
464					let request = serde_json::from_value(params.unwrap_or(json!({})))
465						.map_err(de::Error::custom)?;
466					Ok(LSPSMessage::LSPS2(LSPS2Message::Request(id, LSPS2Request::Buy(request))))
467				},
468			},
469			None => match self.request_id_to_method_map.remove(&id) {
470				Some(method) => match method {
471					LSPSMethod::LSPS0ListProtocols => {
472						if let Some(error) = error {
473							Ok(LSPSMessage::LSPS0(LSPS0Message::Response(
474								id,
475								LSPS0Response::ListProtocolsError(error),
476							)))
477						} else if let Some(result) = result {
478							let list_protocols_response =
479								serde_json::from_value(result).map_err(de::Error::custom)?;
480							Ok(LSPSMessage::LSPS0(LSPS0Message::Response(
481								id,
482								LSPS0Response::ListProtocols(list_protocols_response),
483							)))
484						} else {
485							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
486						}
487					},
488					LSPSMethod::LSPS1GetInfo => {
489						if let Some(error) = error {
490							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
491								id,
492								LSPS1Response::GetInfoError(error),
493							)))
494						} else if let Some(result) = result {
495							let response =
496								serde_json::from_value(result).map_err(de::Error::custom)?;
497							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
498								id,
499								LSPS1Response::GetInfo(response),
500							)))
501						} else {
502							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
503						}
504					},
505					LSPSMethod::LSPS1CreateOrder => {
506						if let Some(error) = error {
507							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
508								id,
509								LSPS1Response::CreateOrderError(error),
510							)))
511						} else if let Some(result) = result {
512							let response =
513								serde_json::from_value(result).map_err(de::Error::custom)?;
514							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
515								id,
516								LSPS1Response::CreateOrder(response),
517							)))
518						} else {
519							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
520						}
521					},
522					LSPSMethod::LSPS1GetOrder => {
523						if let Some(error) = error {
524							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
525								id,
526								LSPS1Response::GetOrderError(error),
527							)))
528						} else if let Some(result) = result {
529							let response =
530								serde_json::from_value(result).map_err(de::Error::custom)?;
531							Ok(LSPSMessage::LSPS1(LSPS1Message::Response(
532								id,
533								LSPS1Response::GetOrder(response),
534							)))
535						} else {
536							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
537						}
538					},
539					LSPSMethod::LSPS2GetInfo => {
540						if let Some(error) = error {
541							Ok(LSPSMessage::LSPS2(LSPS2Message::Response(
542								id,
543								LSPS2Response::GetInfoError(error),
544							)))
545						} else if let Some(result) = result {
546							let response =
547								serde_json::from_value(result).map_err(de::Error::custom)?;
548							Ok(LSPSMessage::LSPS2(LSPS2Message::Response(
549								id,
550								LSPS2Response::GetInfo(response),
551							)))
552						} else {
553							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
554						}
555					},
556					LSPSMethod::LSPS2Buy => {
557						if let Some(error) = error {
558							Ok(LSPSMessage::LSPS2(LSPS2Message::Response(
559								id,
560								LSPS2Response::BuyError(error),
561							)))
562						} else if let Some(result) = result {
563							let response =
564								serde_json::from_value(result).map_err(de::Error::custom)?;
565							Ok(LSPSMessage::LSPS2(LSPS2Message::Response(
566								id,
567								LSPS2Response::Buy(response),
568							)))
569						} else {
570							Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required"))
571						}
572					},
573				},
574				None => Err(de::Error::custom(format!(
575					"Received response for unknown request id: {}",
576					id.0
577				))),
578			},
579		}
580	}
581}
582
583pub(crate) mod string_amount {
584	use crate::prelude::{String, ToString};
585	use core::str::FromStr;
586	use serde::de::Unexpected;
587	use serde::{Deserialize, Deserializer, Serializer};
588
589	pub(crate) fn serialize<S>(x: &u64, s: S) -> Result<S::Ok, S::Error>
590	where
591		S: Serializer,
592	{
593		s.serialize_str(&x.to_string())
594	}
595
596	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
597	where
598		D: Deserializer<'de>,
599	{
600		let buf = String::deserialize(deserializer)?;
601
602		u64::from_str(&buf).map_err(|_| {
603			serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid u64 amount string")
604		})
605	}
606}
607
608pub(crate) mod string_amount_option {
609	use crate::prelude::{String, ToString};
610	use core::str::FromStr;
611	use serde::de::Unexpected;
612	use serde::{Deserialize, Deserializer, Serialize, Serializer};
613
614	pub(crate) fn serialize<S>(x: &Option<u64>, s: S) -> Result<S::Ok, S::Error>
615	where
616		S: Serializer,
617	{
618		let v = x.as_ref().map(|v| v.to_string());
619		Option::<String>::serialize(&v, s)
620	}
621
622	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
623	where
624		D: Deserializer<'de>,
625	{
626		if let Some(buf) = Option::<String>::deserialize(deserializer)? {
627			let val = u64::from_str(&buf).map_err(|_| {
628				serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid u64 amount string")
629			})?;
630			Ok(Some(val))
631		} else {
632			Ok(None)
633		}
634	}
635}
636
637pub(crate) mod unchecked_address {
638	use crate::prelude::{String, ToString};
639	use bitcoin::Address;
640	use core::str::FromStr;
641	use serde::de::Unexpected;
642	use serde::{Deserialize, Deserializer, Serializer};
643
644	pub(crate) fn serialize<S>(x: &Address, s: S) -> Result<S::Ok, S::Error>
645	where
646		S: Serializer,
647	{
648		s.serialize_str(&x.to_string())
649	}
650
651	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Address, D::Error>
652	where
653		D: Deserializer<'de>,
654	{
655		let buf = String::deserialize(deserializer)?;
656
657		let parsed_addr = Address::from_str(&buf).map_err(|_| {
658			serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid address string")
659		})?;
660		Ok(parsed_addr.assume_checked())
661	}
662}
663
664pub(crate) mod unchecked_address_option {
665	use crate::prelude::{String, ToString};
666	use bitcoin::Address;
667	use core::str::FromStr;
668	use serde::de::Unexpected;
669	use serde::{Deserialize, Deserializer, Serialize, Serializer};
670
671	pub(crate) fn serialize<S>(x: &Option<Address>, s: S) -> Result<S::Ok, S::Error>
672	where
673		S: Serializer,
674	{
675		let v = x.as_ref().map(|v| v.to_string());
676		Option::<String>::serialize(&v, s)
677	}
678
679	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<bitcoin::Address>, D::Error>
680	where
681		D: Deserializer<'de>,
682	{
683		if let Some(buf) = Option::<String>::deserialize(deserializer)? {
684			let val = Address::from_str(&buf).map_err(|_| {
685				serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid address string")
686			})?;
687			Ok(Some(val.assume_checked()))
688		} else {
689			Ok(None)
690		}
691	}
692}
693
694pub(crate) mod u32_fee_rate {
695	use bitcoin::FeeRate;
696	use serde::{Deserialize, Deserializer, Serializer};
697
698	pub(crate) fn serialize<S>(x: &FeeRate, s: S) -> Result<S::Ok, S::Error>
699	where
700		S: Serializer,
701	{
702		let fee_rate_sat_kwu = x.to_sat_per_kwu();
703		s.serialize_u32(fee_rate_sat_kwu as u32)
704	}
705
706	pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<FeeRate, D::Error>
707	where
708		D: Deserializer<'de>,
709	{
710		let fee_rate_sat_kwu = u32::deserialize(deserializer)?;
711
712		Ok(FeeRate::from_sat_per_kwu(fee_rate_sat_kwu as u64))
713	}
714}