@@ -17,7 +17,7 @@ use bdk_chain::miniscript::{
1717 descriptor:: { DescriptorSecretKey , SinglePubKey } ,
1818 plan:: { Assets , Plan } ,
1919 psbt:: PsbtExt ,
20- Descriptor , DescriptorPublicKey ,
20+ Descriptor , DescriptorPublicKey , ForEachKey ,
2121} ;
2222use bdk_chain:: ConfirmationBlockTime ;
2323use bdk_chain:: {
@@ -147,9 +147,14 @@ pub enum PsbtCmd<S: clap::Args> {
147147 /// Create a new PSBT.
148148 New {
149149 /// Amount to send in satoshis
150+ #[ clap( required = true ) ]
150151 value : u64 ,
151152 /// Recipient address
153+ #[ clap( required = true ) ]
152154 address : Address < NetworkUnchecked > ,
155+ /// Set the feerate of the tx (sat/vbyte)
156+ #[ clap( long, short, default_value = "1.0" ) ]
157+ feerate : Option < f32 > ,
153158 /// Set max absolute timelock (from consensus value)
154159 #[ clap( long, short) ]
155160 after : Option < u32 > ,
@@ -165,20 +170,21 @@ pub enum PsbtCmd<S: clap::Args> {
165170 } ,
166171 /// Sign with a hot signer
167172 Sign {
168- /// PSBT
169- #[ clap( long) ]
170- psbt : Option < String > ,
171- /// Private descriptor
172- #[ clap( long, short = 'd' ) ]
173+ /// Private descriptor [env: DESCRIPTOR=]
174+ #[ clap( long, short) ]
173175 descriptor : Option < String > ,
176+ /// PSBT
177+ #[ clap( long, short, required = true ) ]
178+ psbt : String ,
174179 } ,
175180 /// Extract transaction
176181 Extract {
177182 /// PSBT
183+ #[ clap( long, short, required = true ) ]
178184 psbt : String ,
179185 /// Whether to try broadcasting the tx
180- #[ clap( long, short = 'b' ) ]
181- try_broadcast : bool ,
186+ #[ clap( long, short) ]
187+ broadcast : bool ,
182188 #[ clap( flatten) ]
183189 chain_specific : S ,
184190 } ,
@@ -260,6 +266,7 @@ pub fn create_tx<O: ChainOracle>(
260266 cs_algorithm : CoinSelectionAlgo ,
261267 address : Address ,
262268 value : u64 ,
269+ feerate : f32 ,
263270) -> anyhow:: Result < ( Psbt , Option < ChangeInfo > ) >
264271where
265272 O :: Error : std:: error:: Error + Send + Sync + ' static ,
@@ -288,7 +295,7 @@ where
288295 . map ( |( plan, utxo) | {
289296 Candidate :: new (
290297 utxo. txout . value . to_sat ( ) ,
291- plan. satisfaction_weight ( ) as u32 ,
298+ plan. satisfaction_weight ( ) as u64 ,
292299 plan. witness_version ( ) . is_some ( ) ,
293300 )
294301 } )
@@ -330,9 +337,12 @@ where
330337 outputs : TargetOutputs :: fund_outputs (
331338 outputs
332339 . iter ( )
333- . map ( |output| ( output. weight ( ) . to_wu ( ) as u32 , output. value . to_sat ( ) ) ) ,
340+ . map ( |output| ( output. weight ( ) . to_wu ( ) , output. value . to_sat ( ) ) ) ,
334341 ) ,
335- fee : TargetFee :: default ( ) ,
342+ fee : TargetFee {
343+ rate : FeeRate :: from_sat_per_vb ( feerate) ,
344+ ..Default :: default ( )
345+ } ,
336346 } ;
337347
338348 let change_policy = ChangePolicy {
@@ -444,7 +454,7 @@ pub fn handle_commands<CS: clap::Subcommand, S: clap::Args>(
444454 chain : & Mutex < LocalChain > ,
445455 db : & Mutex < Store < ChangeSet > > ,
446456 network : Network ,
447- broadcast : impl FnOnce ( S , & Transaction ) -> anyhow:: Result < ( ) > ,
457+ broadcast_fn : impl FnOnce ( S , & Transaction ) -> anyhow:: Result < ( ) > ,
448458 cmd : Commands < CS , S > ,
449459) -> anyhow:: Result < ( ) > {
450460 match cmd {
@@ -584,6 +594,7 @@ pub fn handle_commands<CS: clap::Subcommand, S: clap::Args>(
584594 PsbtCmd :: New {
585595 value,
586596 address,
597+ feerate,
587598 after,
588599 older,
589600 coin_select,
@@ -596,26 +607,30 @@ pub fn handle_commands<CS: clap::Subcommand, S: clap::Args>(
596607 let chain = chain. lock ( ) . unwrap ( ) ;
597608
598609 // collect assets we can sign for
599- let mut assets = Assets :: new ( ) ;
610+ let mut pks = vec ! [ ] ;
611+ for ( _, desc) in graph. index . keychains ( ) {
612+ desc. for_each_key ( |k| {
613+ pks. push ( k. clone ( ) ) ;
614+ true
615+ } ) ;
616+ }
617+ let mut assets = Assets :: new ( ) . add ( pks) ;
600618 if let Some ( n) = after {
601619 assets = assets. after ( absolute:: LockTime :: from_consensus ( n) ) ;
602620 }
603621 if let Some ( n) = older {
604622 assets = assets. older ( relative:: LockTime :: from_consensus ( n) ?) ;
605623 }
606- for ( _, desc) in graph. index . keychains ( ) {
607- match desc {
608- Descriptor :: Wpkh ( wpkh) => {
609- assets = assets. add ( wpkh. clone ( ) . into_inner ( ) ) ;
610- }
611- Descriptor :: Tr ( tr) => {
612- assets = assets. add ( tr. internal_key ( ) . clone ( ) ) ;
613- }
614- _ => bail ! ( "unsupported descriptor type" ) ,
615- }
616- }
617624
618- create_tx ( & mut graph, & * chain, & assets, coin_select, address, value) ?
625+ create_tx (
626+ & mut graph,
627+ & * chain,
628+ & assets,
629+ coin_select,
630+ address,
631+ value,
632+ feerate. expect ( "must have feerate" ) ,
633+ ) ?
619634 } ;
620635
621636 if let Some ( ChangeInfo {
@@ -659,7 +674,7 @@ pub fn handle_commands<CS: clap::Subcommand, S: clap::Args>(
659674 Ok ( ( ) )
660675 }
661676 PsbtCmd :: Sign { psbt, descriptor } => {
662- let mut psbt = Psbt :: from_str ( psbt. unwrap_or_default ( ) . as_str ( ) ) ?;
677+ let mut psbt = Psbt :: from_str ( & psbt) ?;
663678
664679 let desc_str = match descriptor {
665680 Some ( s) => s,
@@ -697,20 +712,20 @@ pub fn handle_commands<CS: clap::Subcommand, S: clap::Args>(
697712 Ok ( ( ) )
698713 }
699714 PsbtCmd :: Extract {
700- try_broadcast ,
715+ broadcast ,
701716 chain_specific,
702717 psbt,
703718 } => {
704- let mut psbt = Psbt :: from_str ( psbt. as_str ( ) ) ?;
719+ let mut psbt = Psbt :: from_str ( & psbt) ?;
705720 psbt. finalize_mut ( & Secp256k1 :: new ( ) )
706721 . map_err ( |errors| anyhow:: anyhow!( "failed to finalize PSBT {errors:?}" ) ) ?;
707722
708723 let tx = psbt. extract_tx ( ) ?;
709724
710- if try_broadcast {
725+ if broadcast {
711726 let mut graph = graph. lock ( ) . unwrap ( ) ;
712727
713- match broadcast ( chain_specific, & tx) {
728+ match broadcast_fn ( chain_specific, & tx) {
714729 Ok ( _) => {
715730 println ! ( "Broadcasted Tx: {}" , tx. compute_txid( ) ) ;
716731
0 commit comments