Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

feat: support Etherscan beacon withdrawal transactions #2621

Merged
merged 3 commits into from
Oct 18, 2023
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
39 changes: 39 additions & 0 deletions ethers-etherscan/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,21 @@ pub struct MinedBlock {
pub block_reward: String,
}

/// The raw response from the beacon wihtdrawal transaction list API endpoint
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BeaconWithdrawalTransaction {
#[serde(deserialize_with = "deserialize_stringified_block_number")]
pub block_number: BlockNumber,
pub timestamp: String,
#[serde(deserialize_with = "deserialize_stringified_u64")]
pub withdrawal_index: u64,
#[serde(deserialize_with = "deserialize_stringified_u64")]
pub validator_index: u64,
pub address: Address,
pub amount: String,
}

/// The pre-defined block parameter for balance API endpoints
#[derive(Clone, Copy, Debug, Default)]
pub enum Tag {
Expand Down Expand Up @@ -673,6 +688,30 @@ impl Client {

Ok(response.result)
}

/// Returns the list of beacon withdrawal transactions performed by an address, with optional
/// pagination.
///
/// # Examples
///
/// ```no_run
/// # async fn foo(client: ethers_etherscan::Client) -> Result<(), Box<dyn std::error::Error>> {
/// let address = "0xB9D7934878B5FB9610B3fE8A5e441e8fad7E293f".parse()?;
/// let beacon_withdrawal_transactions = client.get_beacon_withdrawal_transactions(&address, None).await?;
/// # Ok(()) }
/// ```
pub async fn get_beacon_withdrawal_transactions(
&self,
address: &Address,
params: Option<TxListParams>,
) -> Result<Vec<BeaconWithdrawalTransaction>> {
let mut tx_params: HashMap<&str, String> = params.unwrap_or_default().into();
tx_params.insert("address", format!("{address:?}"));
let query = self.create_query("account", "txsBeaconWithdrawal", tx_params);
let response: Response<Vec<BeaconWithdrawalTransaction>> = self.get_json(&query).await?;

Ok(response.result)
}
}

#[cfg(test)]
Expand Down
14 changes: 14 additions & 0 deletions ethers-etherscan/tests/it/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,20 @@ async fn get_mined_blocks_success() {
.await
}

#[tokio::test]
#[serial]
async fn get_beacon_withdrawal_transactions_success() {
run_with_client(Chain::Mainnet, |client| async move {
let txs = client
.get_beacon_withdrawal_transactions(
&"0xB9D7934878B5FB9610B3fE8A5e441e8fad7E293f".parse().unwrap(),
None,
)
.await;
txs.unwrap();
})
.await
}
#[tokio::test]
#[serial]
async fn get_avalanche_transactions() {
Expand Down