From 971957b839cca1759734fcff55bab9ec06a04967 Mon Sep 17 00:00:00 2001 From: codingpeanut157 Date: Wed, 27 Aug 2025 16:21:22 +0200 Subject: [PATCH] replace transports: Option> with just Vec (#999) with a few serde directive we can get the same behaviour we had with Option> but only using Vec No need to change protocol specification --- .../cashu/src/nuts/nut18/payment_request.rs | 28 +++++++------------ .../src/sub_commands/create_request.rs | 14 +++++----- .../cdk-cli/src/sub_commands/pay_request.rs | 8 +++--- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/crates/cashu/src/nuts/nut18/payment_request.rs b/crates/cashu/src/nuts/nut18/payment_request.rs index 65d90f80..73597012 100644 --- a/crates/cashu/src/nuts/nut18/payment_request.rs +++ b/crates/cashu/src/nuts/nut18/payment_request.rs @@ -3,7 +3,6 @@ //! use std::fmt; -use std::ops::Not; use std::str::FromStr; use bitcoin::base64::engine::{general_purpose, GeneralPurpose}; @@ -40,8 +39,8 @@ pub struct PaymentRequest { pub description: Option, /// Transport #[serde(rename = "t")] - #[serde(skip_serializing_if = "Option::is_none")] - pub transports: Option>, + #[serde(skip_serializing_if = "Vec::is_empty", default = "Vec::default")] + pub transports: Vec, /// Nut10 #[serde(skip_serializing_if = "Option::is_none")] pub nut10: Option, @@ -168,8 +167,6 @@ impl PaymentRequestBuilder { /// Build the PaymentRequest pub fn build(self) -> PaymentRequest { - let transports = self.transports.is_empty().not().then_some(self.transports); - PaymentRequest { payment_id: self.payment_id, amount: self.amount, @@ -177,7 +174,7 @@ impl PaymentRequestBuilder { single_use: self.single_use, mints: self.mints, description: self.description, - transports, + transports: self.transports, nut10: self.nut10, } } @@ -224,8 +221,7 @@ mod tests { ); assert_eq!(req.unit.unwrap(), CurrencyUnit::Sat); - let transport = req.transports.unwrap(); - let transport = transport.first().unwrap(); + let transport = req.transports.first().unwrap(); let expected_transport = Transport {_type: TransportType::Nostr, target: "nprofile1qy28wumn8ghj7un9d3shjtnyv9kh2uewd9hsz9mhwden5te0wfjkccte9curxven9eehqctrv5hszrthwden5te0dehhxtnvdakqqgydaqy7curk439ykptkysv7udhdhu68sucm295akqefdehkf0d495cwunl5".to_string(), tags: Some(vec![vec!["n".to_string(), "17".to_string()]])}; @@ -245,7 +241,7 @@ mod tests { .parse() .expect("valid mint url")]), description: None, - transports: Some(vec![transport.clone()]), + transports: vec![transport.clone()], nut10: None, }; @@ -262,8 +258,7 @@ mod tests { ); assert_eq!(req.unit.unwrap(), CurrencyUnit::Sat); - let t = req.transports.unwrap(); - let t = t.first().unwrap(); + let t = req.transports.first().unwrap(); assert_eq!(&transport, t); } @@ -293,8 +288,7 @@ mod tests { assert_eq!(request.unit.clone().unwrap(), CurrencyUnit::Sat); assert_eq!(request.mints.clone().unwrap(), vec![mint_url]); - let t = request.transports.clone().unwrap(); - let t = t.first().unwrap(); + let t = request.transports.first().clone().unwrap(); assert_eq!(&transport, t); // Test serialization and deserialization @@ -497,8 +491,7 @@ mod tests { vec![MintUrl::from_str("https://8333.space:3338").unwrap()] ); - let transport = payment_request.transports.as_ref().unwrap(); - let transport = transport.first().unwrap(); + let transport = payment_request.transports.first().unwrap(); assert_eq!(transport._type, TransportType::Nostr); assert_eq!(transport.target, "nprofile1qy28wumn8ghj7un9d3shjtnyv9kh2uewd9hsz9mhwden5te0wfjkccte9curxven9eehqctrv5hszrthwden5te0dehhxtnvdakqqgydaqy7curk439ykptkysv7udhdhu68sucm295akqefdehkf0d495cwunl5"); assert_eq!( @@ -562,8 +555,7 @@ mod tests { ] ); - let transport = payment_request_cloned.transports.unwrap(); - let transport = transport.first().unwrap(); + let transport = payment_request_cloned.transports.first().unwrap(); assert_eq!(transport._type, TransportType::Nostr); assert_eq!( transport.target, @@ -614,7 +606,7 @@ mod tests { payment_request_cloned.mints.unwrap(), vec![MintUrl::from_str("https://mint.example.com").unwrap()] ); - assert_eq!(payment_request_cloned.transports, None); + assert_eq!(payment_request_cloned.transports, vec![]); // Test round-trip serialization let encoded = payment_request.to_string(); diff --git a/crates/cdk-cli/src/sub_commands/create_request.rs b/crates/cdk-cli/src/sub_commands/create_request.rs index cda60dd4..d92119e6 100644 --- a/crates/cdk-cli/src/sub_commands/create_request.rs +++ b/crates/cdk-cli/src/sub_commands/create_request.rs @@ -100,7 +100,7 @@ pub async fn create_request( // We'll need the Nostr keys and relays later for listening let transport_info = Some((keys, relays, nprofile.public_key)); - (Some(vec![nostr_transport]), transport_info) + (vec![nostr_transport], transport_info) } "http" => { if let Some(url) = &sub_command_args.http_url { @@ -110,18 +110,18 @@ pub async fn create_request( tags: None, }; - (Some(vec![http_transport]), None) + (vec![http_transport], None) } else { println!( "Warning: HTTP transport selected but no URL provided, skipping transport" ); - (None, None) + (vec![], None) } } - "none" => (None, None), + "none" => (vec![], None), _ => { println!("Warning: Unknown transport type '{transport_type}', defaulting to none"); - (None, None) + (vec![], None) } }; @@ -234,7 +234,7 @@ pub async fn create_request( let nut10 = spending_conditions.map(Nut10SecretRequest::from); // Extract the transports option from our match result - let (transports_option, nostr_info) = transports; + let (transports, nostr_info) = transports; let req = PaymentRequest { payment_id: None, @@ -243,7 +243,7 @@ pub async fn create_request( single_use: Some(true), mints: Some(mints), description: sub_command_args.description.clone(), - transports: transports_option, + transports, nut10, }; diff --git a/crates/cdk-cli/src/sub_commands/pay_request.rs b/crates/cdk-cli/src/sub_commands/pay_request.rs index 6ceeb258..6fd088a4 100644 --- a/crates/cdk-cli/src/sub_commands/pay_request.rs +++ b/crates/cdk-cli/src/sub_commands/pay_request.rs @@ -67,10 +67,10 @@ pub async fn pay_request( let matching_wallet = matching_wallets.first().unwrap(); - let transports = payment_request - .transports - .clone() - .ok_or(anyhow!("Cannot pay request without transport"))?; + if payment_request.transports.is_empty() { + return Err(anyhow!("Cannot pay request without transport")); + } + let transports = payment_request.transports.clone(); // We prefer nostr transport if it is available to hide ip. let transport = transports