bdk_wallet/wallet/
error.rs1use crate::descriptor::policy::PolicyError;
15use crate::descriptor::DescriptorError;
16use crate::wallet::coin_selection;
17use crate::{descriptor, KeychainKind};
18use alloc::string::String;
19use bitcoin::{absolute, psbt, Amount, OutPoint, Sequence, Txid};
20use core::fmt;
21
22#[derive(Debug, Clone)]
24pub enum MiniscriptPsbtError {
25 Conversion(miniscript::descriptor::ConversionError),
27 UtxoUpdate(miniscript::psbt::UtxoUpdateError),
29 OutputUpdate(miniscript::psbt::OutputUpdateError),
31}
32
33impl fmt::Display for MiniscriptPsbtError {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 Self::Conversion(err) => write!(f, "Conversion error: {err}"),
37 Self::UtxoUpdate(err) => write!(f, "UTXO update error: {err}"),
38 Self::OutputUpdate(err) => write!(f, "Output update error: {err}"),
39 }
40 }
41}
42
43#[cfg(feature = "std")]
44impl std::error::Error for MiniscriptPsbtError {}
45
46#[derive(Debug)]
47pub enum CreateTxError {
51 Descriptor(DescriptorError),
53 Policy(PolicyError),
55 SpendingPolicyRequired(KeychainKind),
57 Version0,
59 Version1Csv,
61 LockTime {
63 requested: absolute::LockTime,
65 required: absolute::LockTime,
67 },
68 RbfSequenceCsv {
70 sequence: Sequence,
72 csv: Sequence,
74 },
75 FeeTooLow {
77 required: Amount,
79 },
80 FeeRateTooLow {
82 required: bitcoin::FeeRate,
84 },
85 NoUtxosSelected,
87 OutputBelowDustLimit(usize),
89 CoinSelection(coin_selection::InsufficientFunds),
91 NoRecipients,
93 Psbt(psbt::Error),
95 MissingKeyOrigin(String),
101 UnknownUtxo,
103 MissingNonWitnessUtxo(OutPoint),
105 MiniscriptPsbt(MiniscriptPsbtError),
107}
108
109impl fmt::Display for CreateTxError {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 match self {
112 Self::Descriptor(e) => e.fmt(f),
113 Self::Policy(e) => e.fmt(f),
114 CreateTxError::SpendingPolicyRequired(keychain_kind) => {
115 write!(f, "Spending policy required: {keychain_kind}")
116 }
117 CreateTxError::Version0 => {
118 write!(f, "Invalid version `0`")
119 }
120 CreateTxError::Version1Csv => {
121 write!(
122 f,
123 "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
124 )
125 }
126 CreateTxError::LockTime {
127 requested,
128 required,
129 } => {
130 write!(f, "TxBuilder requested timelock of `{requested}`, but at least `{required}` is required to spend from this script")
131 }
132 CreateTxError::RbfSequenceCsv { sequence, csv } => {
133 write!(
134 f,
135 "Cannot enable RBF with nSequence `{sequence}` given a required OP_CSV of `{csv}`"
136 )
137 }
138 CreateTxError::FeeTooLow { required } => {
139 write!(f, "Fee to low: required {}", required.display_dynamic())
140 }
141 CreateTxError::FeeRateTooLow { required } => {
142 write!(
143 f,
144 "Fee rate too low: required {} sat/vb",
147 crate::floating_rate!(required)
148 )
149 }
150 CreateTxError::NoUtxosSelected => {
151 write!(f, "No UTXO selected")
152 }
153 CreateTxError::OutputBelowDustLimit(limit) => {
154 write!(f, "Output below the dust limit: {limit}")
155 }
156 CreateTxError::CoinSelection(e) => e.fmt(f),
157 CreateTxError::NoRecipients => {
158 write!(f, "Cannot build tx without recipients")
159 }
160 CreateTxError::Psbt(e) => e.fmt(f),
161 CreateTxError::MissingKeyOrigin(err) => {
162 write!(f, "Missing key origin: {err}")
163 }
164 CreateTxError::UnknownUtxo => {
165 write!(f, "UTXO not found in the internal database")
166 }
167 CreateTxError::MissingNonWitnessUtxo(outpoint) => {
168 write!(f, "Missing non_witness_utxo on foreign utxo {outpoint}")
169 }
170 CreateTxError::MiniscriptPsbt(err) => {
171 write!(f, "Miniscript PSBT error: {err}")
172 }
173 }
174 }
175}
176
177impl From<descriptor::error::Error> for CreateTxError {
178 fn from(err: descriptor::error::Error) -> Self {
179 CreateTxError::Descriptor(err)
180 }
181}
182
183impl From<PolicyError> for CreateTxError {
184 fn from(err: PolicyError) -> Self {
185 CreateTxError::Policy(err)
186 }
187}
188
189impl From<MiniscriptPsbtError> for CreateTxError {
190 fn from(err: MiniscriptPsbtError) -> Self {
191 CreateTxError::MiniscriptPsbt(err)
192 }
193}
194
195impl From<psbt::Error> for CreateTxError {
196 fn from(err: psbt::Error) -> Self {
197 CreateTxError::Psbt(err)
198 }
199}
200
201impl From<coin_selection::InsufficientFunds> for CreateTxError {
202 fn from(err: coin_selection::InsufficientFunds) -> Self {
203 CreateTxError::CoinSelection(err)
204 }
205}
206
207#[cfg(feature = "std")]
208impl std::error::Error for CreateTxError {}
209
210#[derive(Debug)]
211pub enum BuildFeeBumpError {
215 UnknownUtxo(OutPoint),
217 TransactionNotFound(Txid),
219 TransactionConfirmed(Txid),
221 IrreplaceableTransaction(Txid),
223 FeeRateUnavailable,
225 InvalidOutputIndex(OutPoint),
227}
228
229impl fmt::Display for BuildFeeBumpError {
230 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231 match self {
232 Self::UnknownUtxo(outpoint) => write!(
233 f,
234 "UTXO not found in the internal database with txid: {}, vout: {}",
235 outpoint.txid, outpoint.vout
236 ),
237 Self::TransactionNotFound(txid) => {
238 write!(
239 f,
240 "Transaction not found in the internal database with txid: {txid}"
241 )
242 }
243 Self::TransactionConfirmed(txid) => {
244 write!(f, "Transaction already confirmed with txid: {txid}")
245 }
246 Self::IrreplaceableTransaction(txid) => {
247 write!(f, "Transaction can't be replaced with txid: {txid}")
248 }
249 Self::FeeRateUnavailable => write!(f, "Fee rate unavailable"),
250 Self::InvalidOutputIndex(op) => {
251 write!(f, "A txin referenced an invalid output: {op}")
252 }
253 }
254 }
255}
256
257#[cfg(feature = "std")]
258impl std::error::Error for BuildFeeBumpError {}