openzeppelin_monitor/services/blockchain/transports/stellar/
http.rs

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