diff --git a/example-crates/example_cli/Cargo.toml b/example-crates/example_cli/Cargo.toml index 290908a6a..0a467db84 100644 --- a/example-crates/example_cli/Cargo.toml +++ b/example-crates/example_cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] bdk_chain = { path = "../../crates/chain", features = ["serde", "miniscript"]} -bdk_coin_select = "0.3.0" +bdk_coin_select = "0.4" bdk_file_store = { path = "../../crates/file_store" } bitcoin = { version = "0.32.0", features = ["base64"], default-features = false } diff --git a/example-crates/example_cli/src/lib.rs b/example-crates/example_cli/src/lib.rs index e965495e0..2cb278491 100644 --- a/example-crates/example_cli/src/lib.rs +++ b/example-crates/example_cli/src/lib.rs @@ -17,7 +17,7 @@ use bdk_chain::miniscript::{ descriptor::{DescriptorSecretKey, SinglePubKey}, plan::{Assets, Plan}, psbt::PsbtExt, - Descriptor, DescriptorPublicKey, + Descriptor, DescriptorPublicKey, ForEachKey, }; use bdk_chain::ConfirmationBlockTime; use bdk_chain::{ @@ -147,9 +147,14 @@ pub enum PsbtCmd { /// Create a new PSBT. New { /// Amount to send in satoshis + #[clap(required = true)] value: u64, /// Recipient address + #[clap(required = true)] address: Address, + /// Set the feerate of the tx (sat/vbyte) + #[clap(long, short, default_value = "1.0")] + feerate: Option, /// Set max absolute timelock (from consensus value) #[clap(long, short)] after: Option, @@ -165,20 +170,21 @@ pub enum PsbtCmd { }, /// Sign with a hot signer Sign { - /// PSBT - #[clap(long)] - psbt: Option, - /// Private descriptor - #[clap(long, short = 'd')] + /// Private descriptor [env: DESCRIPTOR=] + #[clap(long, short)] descriptor: Option, + /// PSBT + #[clap(long, short, required = true)] + psbt: String, }, /// Extract transaction Extract { /// PSBT + #[clap(long, short, required = true)] psbt: String, /// Whether to try broadcasting the tx - #[clap(long, short = 'b')] - try_broadcast: bool, + #[clap(long, short)] + broadcast: bool, #[clap(flatten)] chain_specific: S, }, @@ -260,6 +266,7 @@ pub fn create_tx( cs_algorithm: CoinSelectionAlgo, address: Address, value: u64, + feerate: f32, ) -> anyhow::Result<(Psbt, Option)> where O::Error: std::error::Error + Send + Sync + 'static, @@ -288,7 +295,7 @@ where .map(|(plan, utxo)| { Candidate::new( utxo.txout.value.to_sat(), - plan.satisfaction_weight() as u32, + plan.satisfaction_weight() as u64, plan.witness_version().is_some(), ) }) @@ -330,9 +337,12 @@ where outputs: TargetOutputs::fund_outputs( outputs .iter() - .map(|output| (output.weight().to_wu() as u32, output.value.to_sat())), + .map(|output| (output.weight().to_wu(), output.value.to_sat())), ), - fee: TargetFee::default(), + fee: TargetFee { + rate: FeeRate::from_sat_per_vb(feerate), + ..Default::default() + }, }; let change_policy = ChangePolicy { @@ -444,7 +454,7 @@ pub fn handle_commands( chain: &Mutex, db: &Mutex>, network: Network, - broadcast: impl FnOnce(S, &Transaction) -> anyhow::Result<()>, + broadcast_fn: impl FnOnce(S, &Transaction) -> anyhow::Result<()>, cmd: Commands, ) -> anyhow::Result<()> { match cmd { @@ -584,6 +594,7 @@ pub fn handle_commands( PsbtCmd::New { value, address, + feerate, after, older, coin_select, @@ -596,26 +607,30 @@ pub fn handle_commands( let chain = chain.lock().unwrap(); // collect assets we can sign for - let mut assets = Assets::new(); + let mut pks = vec![]; + for (_, desc) in graph.index.keychains() { + desc.for_each_key(|k| { + pks.push(k.clone()); + true + }); + } + let mut assets = Assets::new().add(pks); if let Some(n) = after { assets = assets.after(absolute::LockTime::from_consensus(n)); } if let Some(n) = older { assets = assets.older(relative::LockTime::from_consensus(n)?); } - for (_, desc) in graph.index.keychains() { - match desc { - Descriptor::Wpkh(wpkh) => { - assets = assets.add(wpkh.clone().into_inner()); - } - Descriptor::Tr(tr) => { - assets = assets.add(tr.internal_key().clone()); - } - _ => bail!("unsupported descriptor type"), - } - } - create_tx(&mut graph, &*chain, &assets, coin_select, address, value)? + create_tx( + &mut graph, + &*chain, + &assets, + coin_select, + address, + value, + feerate.expect("must have feerate"), + )? }; if let Some(ChangeInfo { @@ -659,7 +674,7 @@ pub fn handle_commands( Ok(()) } PsbtCmd::Sign { psbt, descriptor } => { - let mut psbt = Psbt::from_str(psbt.unwrap_or_default().as_str())?; + let mut psbt = Psbt::from_str(&psbt)?; let desc_str = match descriptor { Some(s) => s, @@ -697,20 +712,20 @@ pub fn handle_commands( Ok(()) } PsbtCmd::Extract { - try_broadcast, + broadcast, chain_specific, psbt, } => { - let mut psbt = Psbt::from_str(psbt.as_str())?; + let mut psbt = Psbt::from_str(&psbt)?; psbt.finalize_mut(&Secp256k1::new()) .map_err(|errors| anyhow::anyhow!("failed to finalize PSBT {errors:?}"))?; let tx = psbt.extract_tx()?; - if try_broadcast { + if broadcast { let mut graph = graph.lock().unwrap(); - match broadcast(chain_specific, &tx) { + match broadcast_fn(chain_specific, &tx) { Ok(_) => { println!("Broadcasted Tx: {}", tx.compute_txid()); diff --git a/example-crates/example_esplora/src/main.rs b/example-crates/example_esplora/src/main.rs index b6a58e4cf..8ef39c2fb 100644 --- a/example-crates/example_esplora/src/main.rs +++ b/example-crates/example_esplora/src/main.rs @@ -87,7 +87,7 @@ impl EsploraArgs { #[derive(Parser, Debug, Clone, PartialEq)] pub struct ScanOptions { /// Max number of concurrent esplora server requests. - #[clap(long, default_value = "5")] + #[clap(long, default_value = "2")] pub parallel_requests: usize, }