/// Output created is under the dust limit, 546 satoshis
OutputBelowDustLimit(usize),
/// Wallet's UTXO set is not enough to cover recipient's requested plus fee
- InsufficientFunds,
+ InsufficientFunds {
+ /// Sats needed for some transaction
+ needed: u64,
+ /// Sats available for spending
+ available: u64,
+ },
/// Branch and bound coin selection possible attempts with sufficiently big UTXO set could grow
/// exponentially, thus a limit is set, and when hit, this error is thrown
BnBTotalTriesExceeded,
//! })
//! .collect::<Vec<_>>();
//! let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
-//!
-//! if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
-//! return Err(bdk::Error::InsufficientFunds);
+//! let amount_needed_with_fees = (fee_amount + additional_fees).ceil() as u64 + amount_needed;
+//! if amount_needed_with_fees > selected_amount {
+//! return Err(bdk::Error::InsufficientFunds{ needed: amount_needed_with_fees, available: selected_amount });
//! }
//!
//! Ok(CoinSelectionResult {
)
.collect::<Vec<_>>();
- if selected_amount < amount_needed + (fee_amount.ceil() as u64) {
- return Err(Error::InsufficientFunds);
+ let amount_needed_with_fees = amount_needed + (fee_amount.ceil() as u64);
+ if selected_amount < amount_needed_with_fees {
+ return Err(Error::InsufficientFunds {
+ needed: amount_needed_with_fees,
+ available: selected_amount,
+ });
}
Ok(CoinSelectionResult {
let cost_of_change = self.size_of_change as f32 * fee_rate.as_sat_vb();
if curr_available_value + curr_value < actual_target {
- return Err(Error::InsufficientFunds);
+ return Err(Error::InsufficientFunds {
+ needed: actual_target,
+ available: curr_available_value + curr_value,
+ });
}
Ok(self
use address_validator::AddressValidator;
use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxBuilderContext};
-use utils::{check_nlocktime, check_nsequence_rbf, descriptor_to_pk_ctx, After, Older, SecpCtx};
+use utils::{
+ check_nlocktime, check_nsequence_rbf, descriptor_to_pk_ctx, After, Older, SecpCtx,
+ DUST_LIMIT_SATOSHI,
+};
use crate::blockchain::{Blockchain, Progress};
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
match change_output {
None if change_val.is_dust() => {
// single recipient, but the only output would be below dust limit
- return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
+ // TODO: or OutputBelowDustLimit?
+ return Err(Error::InsufficientFunds {
+ needed: DUST_LIMIT_SATOSHI,
+ available: change_val,
+ });
}
Some(_) if change_val.is_dust() => {
// skip the change output because it's dust -- just include it in the fee.
}
Some(_) if change_val_after_add.is_dust() => {
// single_recipient but the only output would be below dust limit
- return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
+ // TODO: or OutputBelowDustLimit?
+ return Err(Error::InsufficientFunds {
+ needed: DUST_LIMIT_SATOSHI,
+ available: change_val_after_add,
+ });
}
None => {
removed_updatable_output.value = change_val_after_add;
use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
// De-facto standard "dust limit" (even though it should change based on the output type)
-const DUST_LIMIT_SATOSHI: u64 = 546;
+pub const DUST_LIMIT_SATOSHI: u64 = 546;
// MSB of the nSequence. If set there's no consensus-constraint, so it must be disabled when
// spending using CSV in order to enforce CSV rules