Add delegating wrapper for esplora_client

This commit is contained in:
Mononaut 2023-10-14 00:17:09 +00:00
parent 9074ada760
commit 718acc2fb2
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
6 changed files with 135 additions and 4 deletions

View File

@ -18,6 +18,8 @@ serde_json = "1.0"
hex = { package = "hex-conservative", version = "0.1.1", default-features = false }
esplora-client = { version = "0.6", features = ["async"], default-features = false }
wasm-bindgen-futures = "0.4.37"
delegate = "0.10.0"
reqwest = { version = "0.11", default-features = false, features = ["json"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
env_logger = "0.10.0"

View File

@ -33,7 +33,6 @@ impl JsWallet {
network,
wallet: Arc::new(Mutex::new(Wallet::new(&Options {
hostname: host,
network,
secure: false,
}).unwrap()))
}

View File

@ -6,7 +6,7 @@ use esplora_client::{AsyncClient as EsploraClient, Builder, Error, Tx};
#[derive(Debug, Clone)]
pub struct Client {
client: EsploraClient,
pub client: EsploraClient,
}
impl Client {

129
src/async_client.rs Normal file
View File

@ -0,0 +1,129 @@
use std::collections::HashMap;
use crate::wallet::{Wallet, Options};
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)
}
delegate! {
to self.wallet.api.client {
/// Get a [`Transaction`] option given its [`Txid`]
pub async fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
/// Get a [`Transaction`] given its [`Txid`].
pub async fn get_tx_no_opt(&self, txid: &Txid) -> Result<Transaction, Error>;
/// Get a [`Txid`] of a transaction given its index in a block with a given hash.
pub async fn get_txid_at_block_index(
&self,
block_hash: &BlockHash,
index: usize,
) -> Result<Option<Txid>, Error>;
/// Get the status of a [`Transaction`] given its [`Txid`].
pub async fn get_tx_status(&self, txid: &Txid) -> Result<TxStatus, Error>;
/// Get the [`BlockStatus`] given a particular [`BlockHash`].
pub async fn get_block_status(&self, block_hash: &BlockHash) -> Result<BlockStatus, Error>;
/// Get a [`Block`] given a particular [`BlockHash`].
pub async fn get_block_by_hash(&self, block_hash: &BlockHash) -> Result<Option<Block>, Error>;
/// Get a merkle inclusion proof for a [`Transaction`] with the given [`Txid`].
pub async fn get_merkle_proof(&self, tx_hash: &Txid) -> Result<Option<MerkleProof>, Error>;
/// Get a [`MerkleBlock`] inclusion proof for a [`Transaction`] with the given [`Txid`].
pub async fn get_merkle_block(&self, tx_hash: &Txid) -> Result<Option<MerkleBlock>, Error>;
/// Get the spending status of an output given a [`Txid`] and the output index.
pub async fn get_output_status(
&self,
txid: &Txid,
index: u64,
) -> Result<Option<OutputStatus>, Error>;
/// Broadcast a [`Transaction`] to Esplora
pub async fn broadcast(&self, transaction: &Transaction) -> Result<(), Error>;
/// Get the current height of the blockchain tip
pub async fn get_height(&self) -> Result<u32, Error>;
/// Get the [`BlockHash`] of the current blockchain tip.
pub async fn get_tip_hash(&self) -> Result<BlockHash, Error>;
/// Get the [`BlockHash`] of a specific block height
pub async fn get_block_hash(&self, block_height: u32) -> Result<BlockHash, Error>;
/// Get confirmed transaction history for the specified address/scripthash,
/// sorted with newest first. Returns 25 transactions per page.
/// More can be requested by specifying the last txid seen by the previous query.
pub async fn scripthash_txs(
&self,
script: &ScriptBuf,
last_seen: Option<Txid>,
) -> Result<Vec<Tx>, Error>;
/// Get an map where the key is the confirmation target (in number of blocks)
/// and the value is the estimated feerate (in sat/vB).
pub async fn get_fee_estimates(&self) -> Result<HashMap<String, f64>, Error>;
/// Gets some recent block summaries starting at the tip or at `height` if provided.
///
/// The maximum number of summaries returned depends on the backend itself: esplora returns `10`
/// while [mempool.space](https://mempool.space/docs/api) returns `15`.
pub async fn get_blocks(&self, height: Option<u32>) -> Result<Vec<BlockSummary>, Error>;
/// Get the underlying base URL.
pub fn url(&self) -> &str;
/// Get the underlying [`Client`].
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",
})
}

View File

@ -6,3 +6,5 @@ mod api;
mod socket;
mod compat;
pub mod wallet;
pub mod async_client;
pub use async_client::MempoolAsync;

View File

@ -13,7 +13,6 @@ use address::{State, Tracker};
pub struct Options {
pub hostname: String,
pub network: Network,
pub secure: bool,
}
@ -44,7 +43,7 @@ impl std::fmt::Display for Event {
#[derive(Clone)]
pub struct Wallet {
api: api::Client,
pub api: api::Client,
ws: socket::Client,
addresses: Arc<Mutex<HashMap<ScriptBuf, Arc<Mutex<Tracker>>>>>,
event_sender: broadcast::Sender<Event>,