@@ -150,10 +150,8 @@ pub use error::{CreateRequestError, ValidationError};
150150pub ( crate ) use error:: { InternalCreateRequestError , InternalValidationError } ;
151151use url:: Url ;
152152
153- use self :: error:: ConfigurationError ;
154153use crate :: input_type:: InputType ;
155154use crate :: psbt:: PsbtExt ;
156- use crate :: send:: error:: InternalConfigurationError ;
157155use crate :: uri:: UriExt ;
158156use crate :: weight:: { varint_size, ComputeWeight } ;
159157use crate :: PjUri ;
@@ -199,18 +197,30 @@ impl<'a> RequestBuilder<'a> {
199197 } )
200198 }
201199
200+ /// Disable output substitution even if the receiver didn't.
201+ ///
202+ /// This forbids receiver switching output or decreasing amount.
203+ /// It is generally **not** recommended to set this as it may prevent the receiver from
204+ /// doing advanced operations such as opening LN channels and it also guarantees the
205+ /// receiver will **not** reward the sender with a discount.
206+ pub fn always_disable_output_substitution ( mut self , disable : bool ) -> Self {
207+ self . disable_output_substitution = disable;
208+ self
209+ }
210+
202211 // Calculate the recommended fee contribution for an Original PSBT.
203212 //
204213 // BIP 78 recommends contributing `originalPSBTFeeRate * vsize(sender_input_type)`.
205214 // The minfeerate parameter is set if the contribution is available in change.
206215 //
207216 // This method fails if no recommendation can be made or if the PSBT is malformed.
208- pub fn with_recommended_params (
217+ pub fn build_recommended (
209218 self ,
210- payout_scripts : impl IntoIterator < Item = ScriptBuf > ,
211219 min_fee_rate : FeeRate ,
212- ) -> Result < Self , ConfigurationError > {
213- let mut payout_scripts = payout_scripts. into_iter ( ) ;
220+ ) -> Result < ( Request , Context ) , CreateRequestError > {
221+ // TODO support optional batched payout scripts. This would require a change to
222+ // build() which now checks for a single payee.
223+ let mut payout_scripts = std:: iter:: once ( self . uri . address . script_pubkey ( ) ) ;
214224 if let Some ( ( additional_fee_index, fee_available) ) = self
215225 . psbt
216226 . unsigned_tx
@@ -226,13 +236,13 @@ impl<'a> RequestBuilder<'a> {
226236 . input_pairs ( )
227237 . map ( |input| {
228238 let txo =
229- input. previous_txout ( ) . map_err ( InternalConfigurationError :: PrevTxOut ) ?;
239+ input. previous_txout ( ) . map_err ( InternalCreateRequestError :: PrevTxOut ) ?;
230240 Ok ( InputType :: from_spent_input ( txo, input. psbtin )
231- . map_err ( InternalConfigurationError :: InputType ) ?)
241+ . map_err ( InternalCreateRequestError :: InputType ) ?)
232242 } )
233- . collect :: < Result < Vec < InputType > , ConfigurationError > > ( ) ?;
243+ . collect :: < Result < Vec < InputType > , InternalCreateRequestError > > ( ) ?;
234244
235- let first_type = input_types. first ( ) . ok_or ( InternalConfigurationError :: NoInputs ) ?;
245+ let first_type = input_types. first ( ) . ok_or ( InternalCreateRequestError :: NoInputs ) ?;
236246 // use cheapest default if mixed input types
237247 let mut input_vsize = InputType :: Taproot . expected_input_weight ( ) ;
238248 // Check if all inputs are the same type
@@ -243,16 +253,21 @@ impl<'a> RequestBuilder<'a> {
243253 let recommended_additional_fee = min_fee_rate * input_vsize;
244254 if fee_available < recommended_additional_fee {
245255 log:: warn!( "Insufficient funds to maintain specified minimum feerate." ) ;
246- return Ok ( self
247- . with_fee_contribution ( fee_available, Some ( additional_fee_index) )
248- . clamp_fee_contribution ( true ) ) ;
256+ return self . build_with_additional_fee (
257+ fee_available,
258+ Some ( additional_fee_index) ,
259+ min_fee_rate,
260+ true ,
261+ ) ;
249262 }
250- return Ok ( self
251- . with_fee_contribution ( recommended_additional_fee, Some ( additional_fee_index) )
252- . clamp_fee_contribution ( false )
253- . min_fee_rate ( min_fee_rate) ) ;
263+ return self . build_with_additional_fee (
264+ recommended_additional_fee,
265+ Some ( additional_fee_index) ,
266+ min_fee_rate,
267+ false ,
268+ ) ;
254269 }
255- Ok ( self . non_incentivizing ( ) )
270+ self . build_non_incentivizing ( )
256271 }
257272
258273 /// Offer the receiver contribution to pay for his input.
@@ -262,62 +277,39 @@ impl<'a> RequestBuilder<'a> {
262277 ///
263278 /// `change_index` specifies which output can be used to pay fee. If `None` is provided, then
264279 /// the output is auto-detected unless the supplied transaction has more than two outputs.
265- pub fn with_fee_contribution (
266- self ,
280+ ///
281+ /// `clamp_fee_contribution` decreases fee contribution instead of erroring.
282+ ///
283+ /// If this option is true and a transaction with change amount lower than fee
284+ /// contribution is provided then instead of returning error the fee contribution will
285+ /// be just lowered in the request to match the change amount.
286+ pub fn build_with_additional_fee (
287+ mut self ,
267288 max_fee_contribution : bitcoin:: Amount ,
268289 change_index : Option < usize > ,
269- ) -> Self {
270- Self {
271- disable_output_substitution : false ,
272- fee_contribution : Some ( ( max_fee_contribution, change_index) ) ,
273- clamp_fee_contribution : false ,
274- min_fee_rate : FeeRate :: ZERO ,
275- ..self
276- }
290+ min_fee_rate : FeeRate ,
291+ clamp_fee_contribution : bool ,
292+ ) -> Result < ( Request , Context ) , CreateRequestError > {
293+ self . fee_contribution = Some ( ( max_fee_contribution, change_index) ) ;
294+ self . clamp_fee_contribution = clamp_fee_contribution;
295+ self . min_fee_rate = min_fee_rate;
296+ self . build ( )
277297 }
278298
279299 /// Perform Payjoin without incentivizing the payee to cooperate.
280300 ///
281301 /// While it's generally better to offer some contribution some users may wish not to.
282302 /// This function disables contribution.
283- pub fn non_incentivizing ( self ) -> Self {
284- Self {
285- disable_output_substitution : false ,
286- fee_contribution : None ,
287- clamp_fee_contribution : false ,
288- min_fee_rate : FeeRate :: ZERO ,
289- ..self
290- }
291- }
292-
293- /// Disable output substitution even if the receiver didn't.
294- ///
295- /// This forbids receiver switching output or decreasing amount.
296- /// It is generally **not** recommended to set this as it may prevent the receiver from
297- /// doing advanced operations such as opening LN channels and it also guarantees the
298- /// receiver will **not** reward the sender with a discount.
299- pub fn always_disable_output_substitution ( mut self , disable : bool ) -> Self {
300- self . disable_output_substitution = disable;
301- self
302- }
303-
304- /// Decrease fee contribution instead of erroring.
305- ///
306- /// If this option is set and a transaction with change amount lower than fee
307- /// contribution is provided then instead of returning error the fee contribution will
308- /// be just lowered to match the change amount.
309- pub fn clamp_fee_contribution ( mut self , clamp : bool ) -> Self {
310- self . clamp_fee_contribution = clamp;
311- self
312- }
313-
314- /// Sets minimum fee rate required by the sender.
315- pub fn min_fee_rate ( mut self , fee_rate : FeeRate ) -> Self {
316- self . min_fee_rate = fee_rate;
317- self
303+ pub fn build_non_incentivizing ( mut self ) -> Result < ( Request , Context ) , CreateRequestError > {
304+ // since this is a builder, these should already be cleared
305+ // but we'll reset them to be sure
306+ self . fee_contribution = None ;
307+ self . clamp_fee_contribution = false ;
308+ self . min_fee_rate = FeeRate :: ZERO ;
309+ self . build ( )
318310 }
319311
320- pub fn build ( self ) -> Result < ( Request , Context ) , CreateRequestError > {
312+ fn build ( self ) -> Result < ( Request , Context ) , CreateRequestError > {
321313 let mut psbt =
322314 self . psbt . validate ( ) . map_err ( InternalCreateRequestError :: InconsistentOriginalPsbt ) ?;
323315 psbt. validate_input_utxos ( true )
0 commit comments