Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/cont_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ jobs:
run: echo "${{ matrix.rust.version }} ${{ matrix.features }}" | tee .cache_key
- name: cache
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('.cache_key') }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('.cache_key') }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: Set default toolchain
run: rustup default ${{ matrix.rust.version }}
- name: Set profile
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@ tokio = { version = "1.20.1", features = ["full"] }
electrsd = { version = "0.22.0", features = ["legacy", "esplora_a33e97e1", "bitcoind_22_0"] }
electrum-client = "0.12.0"
lazy_static = "1.4.0"
# zip versions after 0.6.3 don't work with our MSRV 1.57.0
zip = "=0.6.3"
# base64ct versions at 1.6.0 and higher have MSRV 1.60.0
base64ct = "<1.6.0"

[features]
default = ["blocking", "async", "async-https"]
blocking = ["ureq", "ureq/socks-proxy"]
async = ["reqwest", "reqwest/socks"]
async-https = ["reqwest/default-tls"]
async-https = ["async", "reqwest/default-tls"]
4 changes: 2 additions & 2 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ pub struct Tx {
pub fee: u64,
}

#[derive(Deserialize, Clone, Debug, PartialEq)]
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct BlockTime {
pub timestamp: u64,
pub height: u32,
}

#[derive(Debug, Clone, Deserialize, PartialEq)]
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
pub struct BlockSummary {
pub id: BlockHash,
#[serde(flatten)]
Expand Down
64 changes: 35 additions & 29 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,25 @@
//! You can create a blocking client as follows:
//!
//! ```no_run
//! # #[cfg(feature = "blocking")]
//! # {
//! use esplora_client::Builder;
//! let builder = Builder::new("https://blockstream.info/testnet/api");
//! let blocking_client = builder.build_blocking();
//! # Ok::<(), esplora_client::Error>(());
//! # }
//! ```
//!
//! Here is an example of how to create an asynchronous client.
//!
//! ```no_run
//! # #[cfg(feature = "async")]
//! # {
//! use esplora_client::Builder;
//! let builder = Builder::new("https://blockstream.info/testnet/api");
//! let async_client = builder.build_async();
//! # Ok::<(), esplora_client::Error>(());
//! # }
//! ```
//!
//! ## Features
Expand Down Expand Up @@ -54,15 +60,15 @@ use bitcoin::{BlockHash, Txid};

pub mod api;

#[cfg(any(feature = "async", feature = "async-https"))]
#[cfg(feature = "async")]
pub mod r#async;
#[cfg(feature = "blocking")]
pub mod blocking;

pub use api::*;
#[cfg(feature = "blocking")]
pub use blocking::BlockingClient;
#[cfg(any(feature = "async", feature = "async-https"))]
#[cfg(feature = "async")]
pub use r#async::AsyncClient;

/// Get a fee value in sats/vbytes from the estimates
Expand Down Expand Up @@ -146,7 +152,7 @@ pub enum Error {
#[cfg(feature = "blocking")]
UreqTransport(::ureq::Transport),
/// Error during reqwest HTTP request
#[cfg(any(feature = "async", feature = "async-https"))]
#[cfg(feature = "async")]
Reqwest(::reqwest::Error),
/// HTTP response error
HttpResponse(u16),
Expand Down Expand Up @@ -191,7 +197,7 @@ macro_rules! impl_error {
impl std::error::Error for Error {}
#[cfg(feature = "blocking")]
impl_error!(::ureq::Transport, UreqTransport, Error);
#[cfg(any(feature = "async", feature = "async-https"))]
#[cfg(feature = "async")]
impl_error!(::reqwest::Error, Reqwest, Error);
impl_error!(io::Error, Io, Error);
impl_error!(std::num::ParseIntError, Parsing, Error);
Expand All @@ -205,7 +211,7 @@ mod test {
use lazy_static::lazy_static;
use std::env;
use tokio::sync::Mutex;
#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
use {
bitcoin::hashes::Hash,
bitcoin::Amount,
Expand Down Expand Up @@ -243,10 +249,10 @@ mod test {
static ref MINER: Mutex<()> = Mutex::new(());
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
static PREMINE: OnceCell<()> = OnceCell::const_new();

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
async fn setup_clients() -> (BlockingClient, AsyncClient) {
PREMINE
.get_or_init(|| async {
Expand All @@ -266,14 +272,14 @@ mod test {
(blocking_client, async_client)
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
fn generate_blocks_and_wait(num: usize) {
let cur_height = BITCOIND.client.get_block_count().unwrap();
generate_blocks(num);
wait_for_block(cur_height as usize + num);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
fn generate_blocks(num: usize) {
let address = BITCOIND
.client
Expand All @@ -285,7 +291,7 @@ mod test {
.unwrap();
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
fn wait_for_block(min_height: usize) {
let mut header = ELECTRSD.client.block_headers_subscribe().unwrap();
loop {
Expand All @@ -300,7 +306,7 @@ mod test {
}
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
fn exponential_backoff_poll<T, F>(mut poll: F) -> T
where
F: FnMut() -> Option<T>,
Expand Down Expand Up @@ -361,7 +367,7 @@ mod test {
);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_tx() {
let (blocking_client, async_client) = setup_clients().await;
Expand Down Expand Up @@ -391,7 +397,7 @@ mod test {
assert_eq!(tx, tx_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_tx_no_opt() {
let (blocking_client, async_client) = setup_clients().await;
Expand Down Expand Up @@ -421,7 +427,7 @@ mod test {
assert_eq!(tx_no_opt, tx_no_opt_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_tx_status() {
let (blocking_client, async_client) = setup_clients().await;
Expand Down Expand Up @@ -452,7 +458,7 @@ mod test {
assert!(tx_status.confirmed);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_header_by_hash() {
let (blocking_client, async_client) = setup_clients().await;
Expand All @@ -464,7 +470,7 @@ mod test {
assert_eq!(block_header, block_header_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_block_status() {
let (blocking_client, async_client) = setup_clients().await;
Expand All @@ -484,7 +490,7 @@ mod test {
assert_eq!(expected, block_status_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_non_existing_block_status() {
// Esplora returns the same status for orphaned blocks as for non-existing blocks:
Expand All @@ -509,7 +515,7 @@ mod test {
assert_eq!(expected, block_status_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_block_by_hash() {
let (blocking_client, async_client) = setup_clients().await;
Expand All @@ -524,7 +530,7 @@ mod test {
assert_eq!(expected, block_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_block_by_hash_not_existing() {
let (blocking_client, async_client) = setup_clients().await;
Expand All @@ -540,7 +546,7 @@ mod test {
assert!(block_async.is_none());
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_merkle_proof() {
let (blocking_client, async_client) = setup_clients().await;
Expand Down Expand Up @@ -571,7 +577,7 @@ mod test {
assert!(merkle_proof.pos > 0);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_merkle_block() {
let (blocking_client, async_client) = setup_clients().await;
Expand Down Expand Up @@ -611,7 +617,7 @@ mod test {
assert!(indexes[0] > 0);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_output_status() {
let (blocking_client, async_client) = setup_clients().await;
Expand Down Expand Up @@ -649,7 +655,7 @@ mod test {
assert_eq!(output_status, output_status_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_height() {
let (blocking_client, async_client) = setup_clients().await;
Expand All @@ -659,7 +665,7 @@ mod test {
assert_eq!(block_height, block_height_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_tip_hash() {
let (blocking_client, async_client) = setup_clients().await;
Expand All @@ -668,7 +674,7 @@ mod test {
assert_eq!(tip_hash, tip_hash_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_block_hash() {
let (blocking_client, async_client) = setup_clients().await;
Expand All @@ -681,7 +687,7 @@ mod test {
assert_eq!(block_hash, block_hash_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_txid_at_block_index() {
let (blocking_client, async_client) = setup_clients().await;
Expand All @@ -700,7 +706,7 @@ mod test {
assert_eq!(txid_at_block_index, txid_at_block_index_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_fee_estimates() {
let (blocking_client, async_client) = setup_clients().await;
Expand All @@ -709,7 +715,7 @@ mod test {
assert_eq!(fee_estimates.len(), fee_estimates_async.len());
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_scripthash_txs() {
let (blocking_client, async_client) = setup_clients().await;
Expand Down Expand Up @@ -757,7 +763,7 @@ mod test {
assert_eq!(scripthash_txs_txids, scripthash_txs_txids_async);
}

#[cfg(all(feature = "blocking", any(feature = "async", feature = "async-https")))]
#[cfg(all(feature = "blocking", feature = "async"))]
#[tokio::test]
async fn test_get_blocks() {
let (blocking_client, async_client) = setup_clients().await;
Expand Down