//! Run with //! //! ```not_rust //! cargo run -p beacon-api-beacon-sidecar-fetcher --node -- full //! ``` //! //! This launches a regular reth instance and subscribes to payload attributes event stream. //! //! **NOTE**: This expects that the CL client is running an http server on `localhost:5052` and is //! configured to emit payload attributes events. //! //! See beacon Node API: #![cfg_attr(not(test), warn(unused_crate_dependencies))] use std::{ collections::VecDeque, net::{IpAddr, Ipv4Addr}, }; use clap::Parser; use futures_util::{stream::FuturesUnordered, StreamExt}; use mined_sidecar::MinedSidecarStream; use reth::{builder::NodeHandle, cli::Cli, primitives::B256, providers::CanonStateSubscriptions}; use reth_node_ethereum::EthereumNode; pub mod mined_sidecar; fn main() { Cli::::parse() .run(|builder, beacon_config| async move { // launch the node let NodeHandle { node, node_exit_future } = builder.node(EthereumNode::default()).launch().await?; let notifications: reth::providers::CanonStateNotificationStream = node.provider.canonical_state_stream(); let pool = node.pool.clone(); node.task_executor.spawn(async move { let mut sidecar_stream = MinedSidecarStream { events: notifications, pool, beacon_config, client: reqwest::Client::new(), pending_requests: FuturesUnordered::new(), queued_actions: VecDeque::new(), }; while let Some(result) = sidecar_stream.next().await { match result { Ok(blob_transaction) => { // Handle successful transaction println!("Processed BlobTransaction: {:?}", blob_transaction); } Err(e) => { // Handle errors specifically eprintln!("Failed to process transaction: {:?}", e); } } } }); node_exit_future.await }) .unwrap(); } /// Our custom cli args extension that adds one flag to reth default CLI. #[derive(Debug, Clone, clap::Parser)] pub struct BeaconSidecarConfig { /// Beacon Node http server address #[arg(long = "cl.addr", default_value_t = IpAddr::V4(Ipv4Addr::LOCALHOST))] pub cl_addr: IpAddr, /// Beacon Node http server port to listen on #[arg(long = "cl.port", default_value_t = 5052)] pub cl_port: u16, } impl Default for BeaconSidecarConfig { /// Default setup for lighthouse client fn default() -> Self { Self { cl_addr: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), // Equivalent to Ipv4Addr::LOCALHOST cl_port: 5052, } } } impl BeaconSidecarConfig { /// Returns the http url of the beacon node pub fn http_base_url(&self) -> String { format!("http://{}:{}", self.cl_addr, self.cl_port) } /// Returns the URL to the beacon sidecars endpoint pub fn sidecar_url(&self, block_root: B256) -> String { format!("{}/eth/v1/beacon/blob_sidecars/{}", self.http_base_url(), block_root) } }