diff --git a/crates/provider/src/ext/admin.rs b/crates/provider/src/ext/admin.rs index 2165481cc34..158f9598d37 100644 --- a/crates/provider/src/ext/admin.rs +++ b/crates/provider/src/ext/admin.rs @@ -31,6 +31,12 @@ pub trait AdminApi: Send + Sync { /// Returns general information about the node as well as information about the running p2p /// protocols (e.g. `eth`, `snap`). async fn node_info(&self) -> TransportResult; + + /// Subscribe to events received by peers over the network. + #[cfg(feature = "pubsub")] + async fn subscribe_peer_events( + &self, + ) -> TransportResult>; } #[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))] @@ -64,6 +70,17 @@ where async fn node_info(&self) -> TransportResult { self.client().request("admin_nodeInfo", ()).await } + + #[cfg(feature = "pubsub")] + async fn subscribe_peer_events( + &self, + ) -> TransportResult> { + self.root().pubsub_frontend()?; + let mut call = self.client().request("admin_peerEvents_subscribe", ()); + call.set_is_subscription(); + let id = call.await?; + self.root().get_subscription(id).await + } } #[cfg(test)] diff --git a/crates/rpc-types-admin/src/admin.rs b/crates/rpc-types-admin/src/admin.rs index 4ef48287bc0..2814f16160e 100644 --- a/crates/rpc-types-admin/src/admin.rs +++ b/crates/rpc-types-admin/src/admin.rs @@ -185,6 +185,51 @@ pub struct PeerNetworkInfo { pub static_node: bool, } +/// The type of a peer event. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum PeerEventType { + /// A peer was added to the server. + Add, + /// A peer was dropped from the server. + Drop, + /// A message was successfully sent to the peer. + MsgSend, + /// A message was successfully received by the peer. + MsgRecv, +} + +/// An event emitted when peers are either added or dropped from a p2p server or when a message is +/// sent or received on a peer connection. +/// +/// See [geth's `PeerEvent` struct](https://github.com/ethereum/go-ethereum/blob/94579932b18931115f28aa7f87f02450bda084c9/p2p/peer.go#L94-L103) for the source of each field. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct PeerEvent { + /// The type of the event. + #[serde(rename = "type")] + pub kind: PeerEventType, + /// The peer's enode ID. + pub peer: String, + /// An error ocurred on the peer. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub error: Option, + /// The protocol of the peer. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub protocol: Option, + /// The message code. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub msg_code: Option, + /// The message size. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub msg_size: Option, + /// The local endpoint of the TCP connection. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub local_address: Option, + /// The remote endpoint of the TCP connection. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub remote_address: Option, +} + mod handshake { use super::*;