Skip to content

Commit d710838

Browse files
committed
test: add test for multiple recipients and sp code
1 parent a040a55 commit d710838

2 files changed

Lines changed: 171 additions & 0 deletions

File tree

tests/integration/init.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,37 @@ mod test_config {
292292
assert_eq!(config["int_descriptor"].as_str().unwrap(), int_desc);
293293
}
294294
}
295+
296+
297+
// SILENT PAYMENTS
298+
#[cfg(feature = "silent-payments")]
299+
mod test_silent_payments {
300+
use super::*;
301+
302+
const SCAN: &str = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798";
303+
const SPEND: &str = "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5";
304+
305+
#[test]
306+
fn test_silent_payment_code_network_hrp() {
307+
BdkCli::new("regtest", None)
308+
.cmd("silent_payment_code", &["--scan_key", SCAN, "--spend_key", SPEND])
309+
.assert()
310+
.success()
311+
.stdout(predicate::str::contains("sprt1"));
312+
313+
BdkCli::new("testnet", None)
314+
.cmd("silent_payment_code", &["--scan_key", SCAN, "--spend_key", SPEND])
315+
.assert()
316+
.success()
317+
.stdout(predicate::str::contains("tsp1"));
318+
}
319+
320+
#[test]
321+
fn test_silent_payment_code_rejects_invalid_pubkey() {
322+
BdkCli::new("regtest", None)
323+
.cmd("silent_payment_code", &["--scan_key", "deadbeef", "--spend_key", SPEND])
324+
.assert()
325+
.failure()
326+
.stderr(predicate::str::contains("malformed public key"));
327+
}
328+
}

tests/integration/online.rs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,4 +433,141 @@ mod test_online {
433433
"balance should reflect exactly one confirmed spend after RBF, got {final_balance}"
434434
);
435435
}
436+
437+
#[test]
438+
fn test_create_tx_multiple_recipients() {
439+
use bdk_wallet::bitcoin::Psbt;
440+
441+
let (cli, mut cmd_init, env) = setup_online_wallet();
442+
cmd_init.assert().success();
443+
fund_and_sync_wallet(&cli, &env);
444+
445+
let second = cli_new_address(&cli);
446+
447+
let psbt_b64 = run_wallet_json(
448+
&cli,
449+
&[
450+
"create_tx",
451+
"--to",
452+
&format!("{RECIPIENT}:20000"),
453+
"--to",
454+
&format!("{second}:30000"),
455+
],
456+
)["psbt"]
457+
.as_str()
458+
.expect("create_tx: missing 'psbt' field")
459+
.to_string();
460+
461+
let psbt: Psbt = psbt_b64
462+
.parse()
463+
.expect("create_tx returned an invalid PSBT");
464+
let values: Vec<u64> = psbt
465+
.unsigned_tx
466+
.output
467+
.iter()
468+
.map(|o| o.value.to_sat())
469+
.collect();
470+
471+
assert!(
472+
values.contains(&20_000),
473+
"first recipient (20_000) output missing: {values:?}"
474+
);
475+
assert!(
476+
values.contains(&30_000),
477+
"second recipient (30_000) output missing: {values:?}"
478+
);
479+
assert!(
480+
psbt.unsigned_tx.output.len() >= 2,
481+
"expected at least the two recipient outputs, got {}",
482+
psbt.unsigned_tx.output.len()
483+
);
484+
}
485+
486+
#[cfg(feature = "rpc")]
487+
mod test_online_rpc {
488+
use crate::common::BdkCli;
489+
use bdk_testenv::{TestEnv, bitcoincore_rpc::RpcApi};
490+
use bdk_wallet::bitcoin::{Address, Amount, Network};
491+
use serde_json::Value;
492+
use std::str::FromStr;
493+
use tempfile::TempDir;
494+
495+
static WALLET_NAME: &str = "test_rpc_wallet";
496+
497+
498+
#[test]
499+
fn test_rpc_full_scan_reflects_funding() {
500+
let env = TestEnv::new().expect("start testenv");
501+
let rpc_url = env.bitcoind.rpc_url();
502+
let cookie = env
503+
.bitcoind
504+
.params
505+
.cookie_file
506+
.to_str()
507+
.unwrap()
508+
.to_string();
509+
510+
let temp_dir = TempDir::new().unwrap();
511+
let cli = BdkCli::new("regtest", Some(temp_dir.path().to_path_buf()));
512+
513+
// descriptors
514+
let desc = cli.cmd("descriptor", &["--type", "tr"]).output().unwrap();
515+
let dv: Value = serde_json::from_slice(&desc.stdout).unwrap();
516+
let ext = dv["private_descriptors"]["external"].as_str().unwrap();
517+
let int = dv["private_descriptors"]["internal"].as_str().unwrap();
518+
519+
// config: rpc client-type, --url flag, cookie as a POSITIONAL arg
520+
cli.build_base_cmd()
521+
.args(["wallet", "--wallet", WALLET_NAME, "config"])
522+
.args(["--ext-descriptor", ext, "--int-descriptor", int])
523+
.args(["--client-type", "rpc", "--database-type", "sqlite"])
524+
.args(["--url", &rpc_url])
525+
.arg(&cookie)
526+
.assert()
527+
.success();
528+
529+
// wallet address to fund
530+
let out = cli
531+
.wallet_cmd(&["--wallet", WALLET_NAME, "new_address"])
532+
.output()
533+
.unwrap();
534+
let addr_json: Value = serde_json::from_slice(&out.stdout).unwrap();
535+
let address = Address::from_str(addr_json["address"].as_str().unwrap())
536+
.unwrap()
537+
.require_network(Network::Regtest)
538+
.unwrap();
539+
540+
// fund + confirm
541+
let node_addr = env
542+
.rpc_client()
543+
.get_new_address(None, None)
544+
.unwrap()
545+
.assume_checked();
546+
env.mine_blocks(101, Some(node_addr)).unwrap();
547+
env.send(&address, Amount::from_btc(0.5).unwrap()).unwrap();
548+
env.mine_blocks(3, None).unwrap();
549+
550+
// full_scan + balance via rpc
551+
let scan = cli
552+
.wallet_cmd(&["--wallet", WALLET_NAME, "full_scan"])
553+
.output()
554+
.unwrap();
555+
assert!(
556+
scan.status.success(),
557+
"rpc full_scan failed: {}",
558+
String::from_utf8_lossy(&scan.stderr)
559+
);
560+
561+
let bal = cli
562+
.wallet_cmd(&["--wallet", WALLET_NAME, "balance"])
563+
.output()
564+
.unwrap();
565+
let bj: Value = serde_json::from_slice(&bal.stdout).unwrap();
566+
assert_eq!(
567+
bj["confirmed"].as_u64(),
568+
Some(50_000_000),
569+
"rpc-synced confirmed balance mismatch: {bj}"
570+
);
571+
}
572+
}
436573
}

0 commit comments

Comments
 (0)