esplora-client = { version = "0.9.0", default-features = false }
async-trait = { version = "0.1.66", optional = true }
futures = { version = "0.3.26", optional = true }
-
-bitcoin = { version = "0.32.0", optional = true, default-features = false }
miniscript = { version = "12.0.0", optional = true, default-features = false }
[dev-dependencies]
use async_trait::async_trait;
use bdk_chain::spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult};
use bdk_chain::{
- bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid},
+ bitcoin::{BlockHash, OutPoint, ScriptBuf, Txid},
collections::BTreeMap,
local_chain::CheckPoint,
BlockId, ConfirmationBlockTime, TxGraph,
};
use bdk_chain::{Anchor, Indexed};
-use esplora_client::{Amount, Tx, TxStatus};
+use esplora_client::{Tx, TxStatus};
use futures::{stream::FuturesOrdered, TryStreamExt};
-use crate::anchor_from_status;
+use crate::{insert_anchor_from_status, insert_prevouts};
/// [`esplora_client::Error`]
type Error = Box<esplora_client::Error>;
}
for tx in txs {
let _ = tx_graph.insert_tx(tx.to_tx());
- if let Some(anchor) = anchor_from_status(&tx.status) {
- let _ = tx_graph.insert_anchor(tx.txid, anchor);
- }
-
- let previous_outputs = tx.vin.iter().filter_map(|vin| {
- let prevout = vin.prevout.as_ref()?;
- Some((
- OutPoint {
- txid: vin.txid,
- vout: vin.vout,
- },
- TxOut {
- script_pubkey: prevout.scriptpubkey.clone(),
- value: Amount::from_sat(prevout.value),
- },
- ))
- });
-
- for (outpoint, txout) in previous_outputs {
- let _ = tx_graph.insert_txout(outpoint, txout);
- }
+ insert_anchor_from_status(&mut tx_graph, tx.txid, tx.status);
+ insert_prevouts(&mut tx_graph, tx.vin);
}
}
for (txid, resp) in handles.try_collect::<Vec<_>>().await? {
match resp {
EsploraResp::TxStatus(status) => {
- if let Some(anchor) = anchor_from_status(&status) {
- let _ = tx_graph.insert_anchor(txid, anchor);
- }
+ insert_anchor_from_status(&mut tx_graph, txid, status);
}
EsploraResp::Tx(Some(tx_info)) => {
let _ = tx_graph.insert_tx(tx_info.to_tx());
- if let Some(anchor) = anchor_from_status(&tx_info.status) {
- let _ = tx_graph.insert_anchor(txid, anchor);
- }
+ insert_anchor_from_status(&mut tx_graph, txid, tx_info.status);
+ insert_prevouts(&mut tx_graph, tx_info.vin);
}
_ => continue,
}
missing_txs.push(spend_txid);
}
if let Some(spend_status) = op_status.status {
- if let Some(spend_anchor) = anchor_from_status(&spend_status) {
- let _ = tx_graph.insert_anchor(spend_txid, spend_anchor);
- }
+ insert_anchor_from_status(&mut tx_graph, spend_txid, spend_status);
}
}
}
use bdk_chain::collections::BTreeMap;
use bdk_chain::spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult};
use bdk_chain::{
- bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, TxOut, Txid},
+ bitcoin::{BlockHash, OutPoint, ScriptBuf, Txid},
local_chain::CheckPoint,
BlockId, ConfirmationBlockTime, TxGraph,
};
use bdk_chain::{Anchor, Indexed};
use esplora_client::{OutputStatus, Tx, TxStatus};
-use crate::anchor_from_status;
+use crate::{insert_anchor_from_status, insert_prevouts};
/// [`esplora_client::Error`]
pub type Error = Box<esplora_client::Error>;
}
for tx in txs {
let _ = tx_graph.insert_tx(tx.to_tx());
- if let Some(anchor) = anchor_from_status(&tx.status) {
- let _ = tx_graph.insert_anchor(tx.txid, anchor);
- }
-
- let previous_outputs = tx.vin.iter().filter_map(|vin| {
- let prevout = vin.prevout.as_ref()?;
- Some((
- OutPoint {
- txid: vin.txid,
- vout: vin.vout,
- },
- TxOut {
- script_pubkey: prevout.scriptpubkey.clone(),
- value: Amount::from_sat(prevout.value),
- },
- ))
- });
-
- for (outpoint, txout) in previous_outputs {
- let _ = tx_graph.insert_txout(outpoint, txout);
- }
+ insert_anchor_from_status(&mut tx_graph, tx.txid, tx.status);
+ insert_prevouts(&mut tx_graph, tx.vin);
}
}
let (txid, resp) = handle.join().expect("thread must not panic")?;
match resp {
EsploraResp::TxStatus(status) => {
- if let Some(anchor) = anchor_from_status(&status) {
- let _ = tx_graph.insert_anchor(txid, anchor);
- }
+ insert_anchor_from_status(&mut tx_graph, txid, status);
}
EsploraResp::Tx(Some(tx_info)) => {
let _ = tx_graph.insert_tx(tx_info.to_tx());
- if let Some(anchor) = anchor_from_status(&tx_info.status) {
- let _ = tx_graph.insert_anchor(txid, anchor);
- }
+ insert_anchor_from_status(&mut tx_graph, txid, tx_info.status);
+ insert_prevouts(&mut tx_graph, tx_info.vin);
}
_ => continue,
}
missing_txs.push(spend_txid);
}
if let Some(spend_status) = op_status.status {
- if let Some(spend_anchor) = anchor_from_status(&spend_status) {
- let _ = tx_graph.insert_anchor(spend_txid, spend_anchor);
- }
+ insert_anchor_from_status(&mut tx_graph, spend_txid, spend_status);
}
}
}
//! [`ChainOracle`]: bdk_chain::ChainOracle
//! [`example_esplora`]: https://github.com/bitcoindevkit/bdk/tree/master/example-crates/example_esplora
-use bdk_chain::{BlockId, ConfirmationBlockTime};
+use bdk_chain::bitcoin::{Amount, OutPoint, TxOut, Txid};
+use bdk_chain::{BlockId, ConfirmationBlockTime, TxGraph};
use esplora_client::TxStatus;
pub use esplora_client;
#[cfg(feature = "async")]
pub use async_ext::*;
-fn anchor_from_status(status: &TxStatus) -> Option<ConfirmationBlockTime> {
+fn insert_anchor_from_status(
+ tx_graph: &mut TxGraph<ConfirmationBlockTime>,
+ txid: Txid,
+ status: TxStatus,
+) {
if let TxStatus {
block_height: Some(height),
block_hash: Some(hash),
block_time: Some(time),
..
- } = status.clone()
+ } = status
{
- Some(ConfirmationBlockTime {
+ let anchor = ConfirmationBlockTime {
block_id: BlockId { height, hash },
confirmation_time: time,
- })
- } else {
- None
+ };
+ let _ = tx_graph.insert_anchor(txid, anchor);
+ }
+}
+
+/// Inserts floating txouts into `tx_graph` using [`Vin`](esplora_client::api::Vin)s returned by
+/// Esplora.
+fn insert_prevouts(
+ tx_graph: &mut TxGraph<ConfirmationBlockTime>,
+ esplora_inputs: impl IntoIterator<Item = esplora_client::api::Vin>,
+) {
+ let prevouts = esplora_inputs
+ .into_iter()
+ .filter_map(|vin| Some((vin.txid, vin.vout, vin.prevout?)));
+ for (prev_txid, prev_vout, prev_txout) in prevouts {
+ let _ = tx_graph.insert_txout(
+ OutPoint::new(prev_txid, prev_vout),
+ TxOut {
+ script_pubkey: prev_txout.scriptpubkey,
+ value: Amount::from_sat(prev_txout.value),
+ },
+ );
}
}