openzeppelin_monitor/services/blockchain/transports/midnight/
ws.rs

1//! Midnight transport implementation for blockchain interactions.
2//!
3//! This module provides a client implementation for interacting with Midnight-compatible nodes
4//! by wrapping the WsTransportClient. This allows for consistent behavior with other
5//! transport implementations while providing specific Midnight-focused functionality.
6
7use reqwest_middleware::ClientWithMiddleware;
8use serde::Serialize;
9use serde_json::Value;
10
11use crate::{
12	models::Network,
13	services::blockchain::{
14		transports::{BlockchainTransport, RotatingTransport, WsTransportClient},
15		TransportError, WsConfig,
16	},
17};
18
19/// A client for interacting with Midnight-compatible blockchain nodes via WebSocket
20///
21/// This implementation wraps the WsTransportClient to provide consistent
22/// behavior with other transport implementations while offering Midnight-specific
23/// functionality. It handles WebSocket connection management, message handling,
24/// and endpoint rotation for Midnight-based networks.
25#[derive(Clone, Debug)]
26pub struct MidnightTransportClient {
27	/// The underlying WebSocket transport client that handles actual RPC communications
28	ws_client: WsTransportClient,
29}
30
31impl MidnightTransportClient {
32	/// Creates a new Midnight transport client by initializing a WebSocket transport client
33	///
34	/// # Arguments
35	/// * `network` - Network configuration containing RPC URLs and other network details
36	///
37	/// # Returns
38	/// * `Result<Self, anyhow::Error>` - A new client instance or connection error
39	pub async fn new(network: &Network, config: Option<WsConfig>) -> Result<Self, anyhow::Error> {
40		let ws_client = WsTransportClient::new(network, config).await?;
41		Ok(Self { ws_client })
42	}
43}
44
45#[async_trait::async_trait]
46impl BlockchainTransport for MidnightTransportClient {
47	/// Gets the current active RPC URL
48	///
49	/// # Returns
50	/// * `String` - The currently active RPC endpoint URL
51	async fn get_current_url(&self) -> String {
52		self.ws_client.get_current_url().await
53	}
54
55	/// Sends a raw JSON-RPC request to the Midnight node via WebSocket
56	///
57	/// # Arguments
58	/// * `method` - The JSON-RPC method to call
59	/// * `params` - Optional parameters to pass with the request
60	///
61	/// # Returns
62	/// * `Result<Value, TransportError>` - The JSON response or error
63	async fn send_raw_request<P>(
64		&self,
65		method: &str,
66		params: Option<P>,
67	) -> Result<Value, TransportError>
68	where
69		P: Into<Value> + Send + Clone + Serialize,
70	{
71		self.ws_client.send_raw_request(method, params).await
72	}
73
74	/// Update endpoint manager with a new client
75	///
76	/// Note: Not applicable for WebSocket transport
77	fn update_endpoint_manager_client(
78		&mut self,
79		_client: ClientWithMiddleware,
80	) -> Result<(), anyhow::Error> {
81		Err(anyhow::anyhow!(
82			"`update_endpoint_manager_client` not implemented for WebSocket transport"
83		))
84	}
85}
86
87#[async_trait::async_trait]
88impl RotatingTransport for MidnightTransportClient {
89	/// Tests connection to a specific WebSocket URL
90	///
91	/// # Arguments
92	/// * `url` - The WebSocket URL to test connection with
93	///
94	/// # Returns
95	/// * `Result<(), anyhow::Error>` - Success or error status
96	async fn try_connect(&self, url: &str) -> Result<(), anyhow::Error> {
97		self.ws_client.try_connect(url).await
98	}
99
100	/// Updates the client to use a new WebSocket URL
101	///
102	/// # Arguments
103	/// * `url` - The new WebSocket URL to use for subsequent requests
104	///
105	/// # Returns
106	/// * `Result<(), anyhow::Error>` - Success or error status
107	async fn update_client(&self, url: &str) -> Result<(), anyhow::Error> {
108		self.ws_client.update_client(url).await
109	}
110}