Skip to content

Commit eb89884

Browse files
nickfarrowLLFourn
andauthored
Prioritise unused change addresses for split (#85)
* prioritise unused change addresses for split * Fix clippy warnings Co-authored-by: LLFourn <[email protected]>
1 parent cab4ba1 commit eb89884

File tree

2 files changed

+40
-33
lines changed

2 files changed

+40
-33
lines changed

src/cmd/wallet.rs

+36-29
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ fn list_keychain_addresses(
112112
Some(index) => scripts
113113
.iter()
114114
.take(index as usize + 1)
115-
.filter_map(|script| {
115+
.map(|script| {
116116
let address = Address::from_script(script, wallet.bdk_wallet().network()).unwrap();
117117
let value = utxo_map
118118
.get(script)
@@ -129,13 +129,13 @@ fn list_keychain_addresses(
129129
KeychainKind::Internal => "internal",
130130
}
131131
.to_string();
132-
Some(vec![
132+
vec![
133133
Cell::String(address.to_string()),
134134
Cell::Amount(value),
135135
Cell::Int(count as u64),
136136
Cell::Int(txn_count),
137137
Cell::String(keychain_name),
138-
])
138+
]
139139
})
140140
// newest should go first
141141
.rev()
@@ -555,7 +555,7 @@ pub struct SplitOpt {
555555
#[structopt(parse(try_from_str = FromCliStr::from_cli_str))]
556556
output_size: Amount,
557557
/// Number of outputs to create. If omitted it will use the maximum possible.
558-
n: Option<usize>,
558+
n: usize,
559559
#[structopt(flatten)]
560560
spend_opt: SpendOpt,
561561
}
@@ -577,32 +577,39 @@ pub fn run_split_cmd(wallet: &GunWallet, opt: SplitOpt) -> anyhow::Result<CmdOut
577577

578578
builder.unspendable(already_correct.map(|utxo| utxo.outpoint).collect());
579579

580-
match n {
581-
Some(n) => {
582-
for _ in 0..n {
583-
builder.add_recipient(
584-
bdk_wallet
585-
.get_change_address(AddressIndex::New)?
586-
.address
587-
.script_pubkey(),
588-
output_size.as_sat(),
589-
);
590-
}
591-
}
592-
None => {
593-
builder
594-
.drain_wallet()
595-
// add one recipient so we at least get one split utxo of the correct size.
596-
.add_recipient(
597-
bdk_wallet
598-
.get_change_address(AddressIndex::New)?
599-
.address
600-
.script_pubkey(),
601-
output_size.as_sat(),
602-
)
603-
.split_change(output_size.as_sat(), usize::MAX);
580+
let txo_map = index_txos(&bdk_wallet.database().iter_raw_txs()?);
581+
582+
let last_unused_index = bdk_wallet
583+
.get_change_address(AddressIndex::LastUnused)?
584+
.index;
585+
let mut added_recipients = 0;
586+
// Check for unused change addresses up to most recent
587+
for check_used_index in 0..(last_unused_index + 1) {
588+
let check_script_pk = bdk_wallet
589+
.get_change_address(AddressIndex::Peek(check_used_index as u32))?
590+
.address
591+
.script_pubkey();
592+
593+
let used = txo_map.get(&check_script_pk).is_some();
594+
// Keep adding unused recipients until we have n
595+
if !used {
596+
builder.add_recipient(check_script_pk, output_size.as_sat());
597+
added_recipients += 1;
598+
if added_recipients == n {
599+
break;
600+
};
604601
}
605-
};
602+
}
603+
// If we don't have enough unused addresses, fill remaining n-added with new
604+
for _ in 0..(n - added_recipients) {
605+
builder.add_recipient(
606+
bdk_wallet
607+
.get_change_address(AddressIndex::New)?
608+
.address
609+
.script_pubkey(),
610+
output_size.as_sat(),
611+
);
612+
}
606613

607614
spend_opt.spend_coins(wallet, builder)
608615
}

src/wallet.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,9 @@ impl GunWallet {
291291
.expect("extracting policy should not have error")
292292
.expect("policy for external wallet exists");
293293

294-
match policy.contribution {
295-
Satisfaction::Complete { .. } | Satisfaction::PartialComplete { .. } => false,
296-
_ => true,
297-
}
294+
!matches!(
295+
policy.contribution,
296+
Satisfaction::Complete { .. } | Satisfaction::PartialComplete { .. }
297+
)
298298
}
299299
}

0 commit comments

Comments
 (0)