diff --git a/src/lsps0/ser.rs b/src/lsps0/ser.rs index e59fc2f..c3a8908 100644 --- a/src/lsps0/ser.rs +++ b/src/lsps0/ser.rs @@ -633,6 +633,63 @@ pub(crate) mod string_amount_option { } } +pub(crate) mod unchecked_address { + use crate::prelude::{String, ToString}; + use bitcoin::Address; + use core::str::FromStr; + use serde::de::Unexpected; + use serde::{Deserialize, Deserializer, Serializer}; + + pub(crate) fn serialize(x: &Address, s: S) -> Result + where + S: Serializer, + { + s.serialize_str(&x.to_string()) + } + + pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let buf = String::deserialize(deserializer)?; + + let parsed_addr = Address::from_str(&buf).map_err(|_| { + serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid address string") + })?; + Ok(parsed_addr.assume_checked()) + } +} + +pub(crate) mod unchecked_address_option { + use crate::prelude::{String, ToString}; + use bitcoin::Address; + use core::str::FromStr; + use serde::de::Unexpected; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + pub(crate) fn serialize(x: &Option
, s: S) -> Result + where + S: Serializer, + { + let v = x.as_ref().map(|v| v.to_string()); + Option::::serialize(&v, s) + } + + pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + if let Some(buf) = Option::::deserialize(deserializer)? { + let val = Address::from_str(&buf).map_err(|_| { + serde::de::Error::invalid_value(Unexpected::Str(&buf), &"invalid address string") + })?; + Ok(Some(val.assume_checked())) + } else { + Ok(None) + } + } +} + pub(crate) mod u32_fee_rate { use bitcoin::FeeRate; use serde::{Deserialize, Deserializer, Serializer}; diff --git a/src/lsps1/msgs.rs b/src/lsps1/msgs.rs index ccba334..402571f 100644 --- a/src/lsps1/msgs.rs +++ b/src/lsps1/msgs.rs @@ -1,11 +1,13 @@ //! Message, request, and other primitive types used to implement LSPS1. -use crate::lsps0::ser::{string_amount, u32_fee_rate, LSPSMessage, RequestId, ResponseError}; +use crate::lsps0::ser::{ + string_amount, u32_fee_rate, unchecked_address, unchecked_address_option, LSPSMessage, + RequestId, ResponseError, +}; use crate::prelude::String; -use bitcoin::address::{Address, NetworkUnchecked}; -use bitcoin::{FeeRate, OutPoint}; +use bitcoin::{Address, FeeRate, OutPoint}; use lightning_invoice::Bolt11Invoice; @@ -106,7 +108,8 @@ pub struct OrderParameters { /// May contain arbitrary associated data like a coupon code or a authentication token. pub token: Option, /// The address where the LSP will send the funds if the order fails. - pub refund_onchain_address: Option>, + #[serde(with = "unchecked_address_option")] + pub refund_onchain_address: Option
, /// Indicates if the channel should be announced to the network. pub announce_channel: bool, } @@ -182,7 +185,8 @@ pub struct OnchainPaymentInfo { pub order_total_sat: u64, /// An on-chain address the client can send [`Self::order_total_sat`] to to have the channel /// opened. - pub address: Address, + #[serde(with = "unchecked_address")] + pub address: Address, /// The minimum number of block confirmations that are required for the on-chain payment to be /// considered confirmed. pub min_onchain_payment_confirmations: Option,