diff --git a/src/async.rs b/src/async.rs index 80d5936..6bb5154 100644 --- a/src/async.rs +++ b/src/async.rs @@ -602,6 +602,23 @@ impl AsyncClient { Ok(blocks) } + /// 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_block_infos(&self, height: Option) -> Result, Error> { + let path = match height { + Some(height) => format!("/blocks/{height}"), + None => "/blocks".to_string(), + }; + let blocks: Vec = self.get_response_json(&path).await?; + if blocks.is_empty() { + return Err(Error::InvalidResponse); + } + Ok(blocks) + } + /// Get all UTXOs locked to an address. pub async fn get_address_utxos(&self, address: &Address) -> Result, Error> { let path = format!("/address/{address}/utxo"); diff --git a/src/blocking.rs b/src/blocking.rs index 81252a1..391981a 100644 --- a/src/blocking.rs +++ b/src/blocking.rs @@ -566,6 +566,23 @@ impl BlockingClient { Ok(blocks) } + /// 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 fn get_block_infos(&self, height: Option) -> Result, Error> { + let path = match height { + Some(height) => format!("/blocks/{height}"), + None => "/blocks".to_string(), + }; + let blocks: Vec = self.get_response_json(&path)?; + if blocks.is_empty() { + return Err(Error::InvalidResponse); + } + Ok(blocks) + } + /// Get all UTXOs locked to an address. pub fn get_address_utxos(&self, address: &Address) -> Result, Error> { let path = format!("/address/{address}/utxo"); diff --git a/tests/block.rs b/tests/block.rs index 6de58a9..73b767d 100644 --- a/tests/block.rs +++ b/tests/block.rs @@ -257,6 +257,37 @@ async fn test_get_block_info() { assert_eq!(block_info_async.previousblockhash, None); } +#[tokio::test] +async fn test_get_block_infos() { + let env = TestEnv::new(); + let (blocking_client, async_client) = env.setup_clients(); + + let start_height = env.bitcoind_client().get_block_count().unwrap().0 as u32; + let blocks1 = blocking_client.get_block_infos(None).unwrap(); + let blocks_async1 = async_client.get_block_infos(None).await.unwrap(); + assert_eq!(blocks1[0].height, start_height); + assert_eq!(blocks1, blocks_async1); + env.mine_and_wait(1); + + let blocks2 = blocking_client.get_block_infos(None).unwrap(); + let blocks_async2 = async_client.get_block_infos(None).await.unwrap(); + assert_eq!(blocks2, blocks_async2); + assert_ne!(blocks2, blocks1); + + let blocks3 = blocking_client.get_block_infos(Some(start_height)).unwrap(); + let blocks_async3 = async_client + .get_block_infos(Some(start_height)) + .await + .unwrap(); + assert_eq!(blocks3, blocks_async3); + assert_eq!(blocks3[0].height, start_height); + assert_eq!(blocks3, blocks1); + + let blocks_genesis = blocking_client.get_block_infos(Some(0)).unwrap(); + let blocks_genesis_async = async_client.get_block_infos(Some(0)).await.unwrap(); + assert_eq!(blocks_genesis, blocks_genesis_async); +} + #[tokio::test] async fn test_get_txid_at_block_index() { let env = TestEnv::new();