ethers_etherscan/
blocks.rs

1use crate::{Client, EtherscanError, Response, Result};
2use ethers_core::types::BlockNumber;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Clone, Debug, Deserialize, Serialize)]
7pub struct BlockNumberByTimestamp {
8    pub timestamp: u64,
9    pub block_number: BlockNumber,
10}
11
12impl Client {
13    /// Returns either (1) the oldest block since a particular timestamp occurred or (2) the newest
14    /// block that occurred prior to that timestamp
15    ///
16    /// # Examples
17    ///
18    /// ```no_run
19    /// # async fn foo(client: ethers_etherscan::Client) -> Result<(), Box<dyn std::error::Error>> {
20    /// // The newest block that occurred prior to 1 January 2020
21    /// let block_number_before = client.get_block_by_timestamp(1577836800, "before");
22    /// // The oldest block that occurred after 1 January 2020
23    /// let block_number_after = client.get_block_by_timestamp(1577836800, "after");
24    /// # Ok(()) }
25    /// ```
26    pub async fn get_block_by_timestamp(
27        &self,
28        timestamp: u64,
29        closest: &str,
30    ) -> Result<BlockNumberByTimestamp> {
31        let query = self.create_query(
32            "block",
33            "getblocknobytime",
34            HashMap::from([("timestamp", timestamp.to_string()), ("closest", closest.to_string())]),
35        );
36        let response: Response<String> = self.get_json(&query).await?;
37
38        match response.status.as_str() {
39            "0" => Err(EtherscanError::BlockNumberByTimestampFailed),
40            "1" => Ok(BlockNumberByTimestamp {
41                timestamp,
42                block_number: response.result.parse::<BlockNumber>().unwrap(),
43            }),
44            err => Err(EtherscanError::BadStatusCode(err.to_string())),
45        }
46    }
47}