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}