@@ -54,7 +54,8 @@ const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice_request", "sig
5454/// .features(OfferFeatures::known())
5555/// .quantity(5)?
5656/// .payer_note("foo".to_string())
57- /// .build_signed(|digest| secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))?
57+ /// .build()?
58+ /// .sign(|digest| secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))?
5859/// .write(&mut buffer)
5960/// .unwrap();
6061/// # Ok(())
@@ -126,8 +127,35 @@ impl<'a> InvoiceRequestBuilder<'a> {
126127 self
127128 }
128129
129- ///
130- pub fn build_signed < F > ( mut self , sign : F ) -> Result < InvoiceRequest , secp256k1:: Error >
130+ /// Builds the [`InvoiceRequest`] after checking for valid semantics.
131+ pub fn build ( self ) -> Result < UnsignedInvoiceRequest < ' a > , SemanticError > {
132+ let chain = self . invoice_request . chain . unwrap_or_else ( || self . offer . implied_chain ( ) ) ;
133+ if !self . offer . supports_chain ( chain) {
134+ return Err ( SemanticError :: UnsupportedChain ) ;
135+ }
136+
137+ if self . offer . amount ( ) . is_some ( ) && self . invoice_request . amount_msats . is_none ( ) {
138+ return Err ( SemanticError :: MissingAmount ) ;
139+ }
140+
141+ if self . offer . expects_quantity ( ) && self . invoice_request . quantity . is_none ( ) {
142+ return Err ( SemanticError :: InvalidQuantity ) ;
143+ }
144+
145+ let InvoiceRequestBuilder { offer, invoice_request } = self ;
146+ Ok ( UnsignedInvoiceRequest { offer, invoice_request } )
147+ }
148+ }
149+
150+ /// A semantically valid [`InvoiceRequest`] that hasn't been signed.
151+ pub struct UnsignedInvoiceRequest < ' a > {
152+ offer : & ' a Offer ,
153+ invoice_request : InvoiceRequestContents ,
154+ }
155+
156+ impl < ' a > UnsignedInvoiceRequest < ' a > {
157+ /// Signs the invoice request using the given function.
158+ pub fn sign < F > ( mut self , sign : F ) -> Result < InvoiceRequest , secp256k1:: Error >
131159 where F : FnOnce ( & Message ) -> Signature
132160 {
133161 // Use the offer bytes instead of the offer TLV stream as the offer may have contained
0 commit comments