use std::collections::HashMap;
use crate::wallet::{Wallet, Options, Error as MwckError};
use bitcoin::{Txid, Transaction, BlockHash, Block, MerkleBlock, ScriptBuf};
use esplora_client::{Error, TxStatus, BlockStatus, MerkleProof, OutputStatus, Tx, BlockSummary};
use reqwest;
use delegate::delegate;
pub struct MempoolAsync {
wallet: Wallet,
}
#[allow(clippy::inline_always)]
impl MempoolAsync {
#[must_use]
pub fn new(options: &Options) -> Self {
let wallet = Wallet::new(options).unwrap();
Self {
wallet,
}
}
#[must_use]
pub fn from_url(url: &str) -> Self {
let options = url_to_options(url).unwrap();
Self::new(&options)
}
pub async fn connect(&self, wait_for_connection: bool) {
self.wallet.connect(wait_for_connection).await
}
pub async fn mwck_scripthash_txs(
&self,
script: &ScriptBuf,
) -> Result<Vec<Tx>, MwckError> {
self.wallet.get_and_watch(script).await.map(|state| state.transactions)
}
pub async fn mwck_confirmed_scripthash_txs(
&self,
script: &ScriptBuf,
) -> Result<Vec<Tx>, MwckError> {
self.wallet.get_and_watch(script).await.map(|state| state.transactions.into_iter().filter(|tx| tx.status.confirmed).collect())
}
delegate! {
to self.wallet.api.client {
pub async fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
pub async fn get_tx_no_opt(&self, txid: &Txid) -> Result<Transaction, Error>;
pub async fn get_txid_at_block_index(
&self,
block_hash: &BlockHash,
index: usize,
) -> Result<Option<Txid>, Error>;
pub async fn get_tx_status(&self, txid: &Txid) -> Result<TxStatus, Error>;
pub async fn get_block_status(&self, block_hash: &BlockHash) -> Result<BlockStatus, Error>;
pub async fn get_block_by_hash(&self, block_hash: &BlockHash) -> Result<Option<Block>, Error>;
pub async fn get_merkle_proof(&self, tx_hash: &Txid) -> Result<Option<MerkleProof>, Error>;
pub async fn get_merkle_block(&self, tx_hash: &Txid) -> Result<Option<MerkleBlock>, Error>;
pub async fn get_output_status(
&self,
txid: &Txid,
index: u64,
) -> Result<Option<OutputStatus>, Error>;
pub async fn broadcast(&self, transaction: &Transaction) -> Result<(), Error>;
pub async fn get_height(&self) -> Result<u32, Error>;
pub async fn get_tip_hash(&self) -> Result<BlockHash, Error>;
pub async fn get_block_hash(&self, block_height: u32) -> Result<BlockHash, Error>;
pub async fn scripthash_txs(
&self,
script: &ScriptBuf,
last_seen: Option<Txid>,
) -> Result<Vec<Tx>, Error>;
pub async fn get_fee_estimates(&self) -> Result<HashMap<String, f64>, Error>;
pub async fn get_blocks(&self, height: Option<u32>) -> Result<Vec<BlockSummary>, Error>;
pub fn url(&self) -> &str;
pub fn client(&self) -> &reqwest::Client;
}
}
}
fn url_to_options(input: &str) -> Result<Options, &'static str> {
let mut iter = input.splitn(3, "://");
let Some(scheme) = iter.next() else {
return Err("Invalid URL");
};
if scheme != "http" && scheme != "https" {
return Err("Invalid URL");
}
let host = match iter.next() {
Some(host_part) => {
let end = host_part.find('/').unwrap_or(host_part.len());
&host_part[0..end]
}
None => return Err("Invalid URL"),
};
Ok(Options {
hostname: host.to_string(),
secure: scheme == "https",
})
}