Skip to content

Commit 9abdb76

Browse files
committed
test: Add coverage for create_psbt and similar
Adds several tests to exercise create-psbt logic and user flow. - test-utils: Add `insert_tx_anchor` test helper for adding a transaction to the wallet with associated anchor block. - deps: Bump `bitcoin` to 0.32.7 in order to make use of `ScriptBuf::new_p2a`.
1 parent 5d59cbb commit 9abdb76

File tree

5 files changed

+522
-5
lines changed

5 files changed

+522
-5
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ rustdoc-args = ["--cfg", "docsrs"]
2020
bdk_chain = { version = "0.23.1", features = ["miniscript", "serde"], default-features = false }
2121
bdk_coin_select = { version = "0.4.1" }
2222
bdk_tx = { version = "0.1.0" }
23-
bitcoin = { version = "0.32.6", features = ["serde", "base64"], default-features = false }
23+
bitcoin = { version = "0.32.7", features = ["serde", "base64"], default-features = false }
2424
miniscript = { version = "12.3.1", features = ["serde"], default-features = false }
2525
rand_core = { version = "0.6.0" }
2626
serde_json = { version = "1" }

src/test_utils.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,31 @@ pub fn insert_checkpoint(wallet: &mut Wallet, block: BlockId) {
317317
.unwrap();
318318
}
319319

320+
/// Inserts a transaction to be anchored by `block_id`. This is particularly useful for
321+
/// adding a coinbase tx to the wallet for testing, since transactions of this kind
322+
/// must always appear confirmed.
323+
///
324+
/// This will also insert the anchor `block_id`. See [`insert_anchor`] for more.
325+
pub fn insert_tx_anchor(wallet: &mut Wallet, tx: Transaction, block_id: BlockId) {
326+
insert_checkpoint(wallet, block_id);
327+
let anchor = ConfirmationBlockTime {
328+
block_id,
329+
confirmation_time: 1234567000,
330+
};
331+
let txid = tx.compute_txid();
332+
333+
let mut tx_update = TxUpdate::default();
334+
tx_update.txs = vec![Arc::new(tx)];
335+
tx_update.anchors = [(anchor, txid)].into();
336+
337+
wallet
338+
.apply_update(Update {
339+
tx_update,
340+
..Default::default()
341+
})
342+
.expect("failed to apply update");
343+
}
344+
320345
/// Inserts a transaction into the local view, assuming it is currently present in the mempool.
321346
///
322347
/// This can be used, for example, to track a transaction immediately after it is broadcast.

tests/add_foreign_utxo.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use bdk_wallet::signer::SignOptions;
55
use bdk_wallet::test_utils::*;
66
use bdk_wallet::tx_builder::AddForeignUtxoError;
77
use bdk_wallet::KeychainKind;
8-
use bitcoin::{psbt, Address, Amount};
8+
use bitcoin::{hashes::Hash, psbt, Address, Amount, OutPoint, ScriptBuf, Sequence, TxOut};
99

1010
mod common;
1111

@@ -290,3 +290,55 @@ fn test_taproot_foreign_utxo() {
290290
"foreign_utxo should be in there"
291291
);
292292
}
293+
294+
#[test]
295+
fn test_add_planned_psbt_input() -> anyhow::Result<()> {
296+
let (mut wallet, _) = get_funded_wallet_wpkh();
297+
let op1 = wallet.list_unspent().next().unwrap().outpoint;
298+
299+
// We'll use `PsbtParams` to sweep a foreign anchor output.
300+
let op2 = OutPoint::new(Hash::hash(b"txid"), 2);
301+
let txout = TxOut {
302+
value: Amount::ZERO,
303+
script_pubkey: ScriptBuf::new_p2a(),
304+
};
305+
let psbt_input = psbt::Input {
306+
witness_utxo: Some(txout),
307+
..Default::default()
308+
};
309+
let input = bdk_tx::Input::from_psbt_input(
310+
op2,
311+
Sequence::ENABLE_LOCKTIME_NO_RBF,
312+
psbt_input,
313+
/* satisfaction_weight: */ 0,
314+
/* status: */ None,
315+
/* is_coinbase: */ false,
316+
)?;
317+
318+
let send_to = wallet.reveal_next_address(KeychainKind::External).address;
319+
320+
// Build tx: 2-in / 2-out
321+
let mut params = bdk_wallet::PsbtParams::default();
322+
params.add_utxos(&[op1]);
323+
params.add_planned_input(input);
324+
params.add_recipients([(send_to, Amount::from_sat(20_000))]);
325+
326+
let (psbt, _) = wallet.create_psbt(params)?;
327+
328+
assert!(
329+
psbt.unsigned_tx
330+
.input
331+
.iter()
332+
.any(|input| input.previous_output == op1),
333+
"Psbt should contain the wallet spend"
334+
);
335+
assert!(
336+
psbt.unsigned_tx
337+
.input
338+
.iter()
339+
.any(|input| input.previous_output == op2),
340+
"Psbt should contain the planned input"
341+
);
342+
343+
Ok(())
344+
}

0 commit comments

Comments
 (0)