ethrex_rpc/clients/beacon/
mod.rs1use errors::BeaconClientError;
2use ethrex_common::{H256, U256};
3use reqwest::{Client, Url};
4use serde::Deserialize;
5use serde_json::Value;
6use types::{BlobSidecar, GetBlockResponseData};
7
8pub mod errors;
9pub mod types;
10
11#[derive(Deserialize, Debug)]
12#[serde(untagged)]
13pub enum BeaconResponse {
14 Success(BeaconResponseSuccess),
15 Error(BeaconResponseError),
16}
17
18#[derive(Deserialize, Debug)]
19pub struct BeaconResponseSuccess {
20 data: Value,
21}
22
23#[derive(Deserialize, Debug)]
24pub struct BeaconResponseError {
25 code: u64,
26 message: String,
27}
28
29pub struct BeaconClient {
30 client: Client,
31 url: Url,
32}
33
34impl BeaconClient {
35 pub fn new(url: Url) -> Self {
36 Self {
37 client: Client::new(),
38 url,
39 }
40 }
41
42 async fn send_request<T>(&self, endpoint: &str) -> Result<T, BeaconClientError>
43 where
44 T: serde::de::DeserializeOwned,
45 {
46 println!("Sending request: {endpoint}");
47 let response = self
48 .client
49 .get(self.url.clone().join(endpoint).map_err(|error| {
50 BeaconClientError::FailedToSetURLEndpointError(error.to_string())
51 })?)
52 .header("content-type", "application/json")
53 .header("accept", "application/json")
54 .send()
55 .await?
56 .json::<BeaconResponse>()
57 .await
58 .map_err(BeaconClientError::from)?;
59
60 match response {
61 BeaconResponse::Success(res) => {
62 serde_json::from_value::<T>(res.data).map_err(BeaconClientError::DeserializeError)
63 }
64 BeaconResponse::Error(err) => Err(BeaconClientError::RpcError(err.code, err.message)),
65 }
66 }
67
68 pub async fn get_block_by_hash(
69 &self,
70 block_hash: H256,
71 ) -> Result<GetBlockResponseData, BeaconClientError> {
72 self.send_request(&format!("/eth/v2/beacon/blocks/{block_hash:#x}"))
73 .await
74 }
75
76 pub async fn get_blobs_by_slot(
77 &self,
78 slot: U256,
79 ) -> Result<Vec<BlobSidecar>, BeaconClientError> {
80 self.send_request(&format!("/eth/v1/beacon/blob_sidecars/{slot}"))
81 .await
82 }
83}