bdk_esplora/
lib.rs

1#![doc = include_str!("../README.md")]
2//! # Stop Gap
3//!
4//! [`EsploraExt::full_scan`] takes in a `stop_gap` input which is defined as the maximum number of
5//! consecutive unused script pubkeys to scan transactions for before stopping.
6//!
7//! For example, with a `stop_gap` of 3, `full_scan` will keep scanning until it encounters 3
8//! consecutive script pubkeys with no associated transactions.
9//!
10//! This follows the same approach as other Bitcoin-related software,
11//! such as [Electrum](https://electrum.readthedocs.io/en/latest/faq.html#what-is-the-gap-limit),
12//! [BTCPay Server](https://docs.btcpayserver.org/FAQ/Wallet/#the-gap-limit-problem),
13//! and [Sparrow](https://www.sparrowwallet.com/docs/faq.html#ive-restored-my-wallet-but-some-of-my-funds-are-missing).
14//!
15//! A `stop_gap` of 0 will be treated as a `stop_gap` of 1.
16//!
17//! # Async
18//!
19//! Just like how [`EsploraExt`] extends the functionality of an
20//! [`esplora_client::BlockingClient`], [`EsploraAsyncExt`] is the async version which extends
21//! [`esplora_client::AsyncClient`].
22
23use bdk_core::bitcoin::{Amount, OutPoint, TxOut, Txid};
24use bdk_core::{BlockId, ConfirmationBlockTime, TxUpdate};
25use esplora_client::TxStatus;
26
27pub use esplora_client;
28
29#[cfg(feature = "blocking")]
30mod blocking_ext;
31#[cfg(feature = "blocking")]
32pub use blocking_ext::*;
33
34#[cfg(feature = "async")]
35mod async_ext;
36#[cfg(feature = "async")]
37pub use async_ext::*;
38
39fn insert_anchor_from_status(
40    update: &mut TxUpdate<ConfirmationBlockTime>,
41    txid: Txid,
42    status: TxStatus,
43) {
44    if let TxStatus {
45        block_height: Some(height),
46        block_hash: Some(hash),
47        block_time: Some(time),
48        ..
49    } = status
50    {
51        let anchor = ConfirmationBlockTime {
52            block_id: BlockId { height, hash },
53            confirmation_time: time,
54        };
55        update.anchors.insert((anchor, txid));
56    }
57}
58
59/// Inserts floating txouts into `tx_graph` using [`Vin`](esplora_client::api::Vin)s returned by
60/// Esplora.
61fn insert_prevouts(
62    update: &mut TxUpdate<ConfirmationBlockTime>,
63    esplora_inputs: impl IntoIterator<Item = esplora_client::api::Vin>,
64) {
65    let prevouts = esplora_inputs
66        .into_iter()
67        .filter_map(|vin| Some((vin.txid, vin.vout, vin.prevout?)));
68    for (prev_txid, prev_vout, prev_txout) in prevouts {
69        update.txouts.insert(
70            OutPoint::new(prev_txid, prev_vout),
71            TxOut {
72                script_pubkey: prev_txout.scriptpubkey,
73                value: Amount::from_sat(prev_txout.value),
74            },
75        );
76    }
77}