kabu_node_reth_api/
lib.rs1mod provider_wrapper;
2mod traits;
3
4use alloy_provider::Provider;
5use alloy_transport::TransportResult;
6use async_trait::async_trait;
7use futures_util::StreamExt;
8use reth_chain_state::CanonStateNotification;
9use reth_ethereum_primitives::EthPrimitives;
10use reth_node_types::NodeTypes;
11use reth_storage_rpc_provider::RpcBlockchainProvider;
12use reth_tasks::TaskExecutor;
13use tracing::{error, info, warn};
14
15pub use provider_wrapper::KabuRethProviderWrapper;
16pub use traits::KabuRethFullProvider;
17
18#[async_trait]
19pub trait RethApi: Send + Sync {
20 async fn subscribe_chain_notifications(&self) -> TransportResult<alloy_pubsub::Subscription<CanonStateNotification<EthPrimitives>>>;
21}
22
23#[async_trait]
24impl<P> RethApi for P
25where
26 P: Provider,
27{
28 async fn subscribe_chain_notifications(&self) -> TransportResult<alloy_pubsub::Subscription<CanonStateNotification<EthPrimitives>>> {
29 self.root().client().pubsub_frontend().ok_or_else(alloy_transport::TransportErrorKind::pubsub_unavailable)?;
30
31 let mut call = self.client().request("reth_subscribeChainNotifications", ());
32 call.set_is_subscription();
33 let id = call.await?;
34 self.root().get_subscription(id).await
35 }
36}
37
38pub async fn chain_notifications_forwarder<P, Node, N>(
39 executor: &TaskExecutor,
40 provider: P,
41 reth_provider: RpcBlockchainProvider<P, Node, N>,
42) -> eyre::Result<()>
43where
44 P: RethApi + Send + Sync + 'static,
45 Node: NodeTypes<Primitives = EthPrimitives>,
46 N: alloy_network::Network,
47{
48 match provider.subscribe_chain_notifications().await {
50 Ok(chain_notifications) => {
51 info!("Successfully subscribed to Reth chain notifications");
52
53 executor.spawn_critical("chain-notifications-forwarder", async move {
55 let mut stream = chain_notifications.into_stream();
56 while let Some(canon_state_notification) = stream.next().await {
57 if let Err(err) = reth_provider.canon_state_notification().send(canon_state_notification) {
58 error!(?err, "Failed to send canon state notification");
59 }
60 }
61 warn!("Chain notifications stream ended");
62 });
63
64 Ok(())
65 }
66 Err(err) => {
67 warn!(
69 ?err,
70 "Failed to subscribe to Reth chain notifications. This is expected for non-Reth nodes. The node will continue without Reth-specific features."
71 );
72
73 Ok(())
76 }
77 }
78}