openzeppelin_monitor/services/blockchain/transports/
mod.rsmod evm {
pub mod http;
}
mod stellar {
pub mod http;
}
mod endpoint_manager;
mod http;
pub use endpoint_manager::EndpointManager;
pub use evm::http::EVMTransportClient;
pub use http::HttpTransportClient;
pub use stellar::http::StellarTransportClient;
use reqwest_middleware::ClientWithMiddleware;
use reqwest_retry::{
default_on_request_failure, default_on_request_success, policies::ExponentialBackoff,
Retryable, RetryableStrategy,
};
use serde::Serialize;
use serde_json::{json, Value};
pub const ROTATE_ON_ERROR_CODES: [u16; 1] = [429];
#[async_trait::async_trait]
pub trait BlockchainTransport: Send + Sync {
async fn get_current_url(&self) -> String;
async fn send_raw_request<P>(
&self,
method: &str,
params: Option<P>,
) -> Result<Value, anyhow::Error>
where
P: Into<Value> + Send + Clone + Serialize;
async fn customize_request<P>(&self, method: &str, params: Option<P>) -> Value
where
P: Into<Value> + Send + Clone + Serialize,
{
json!({
"jsonrpc": "2.0",
"id": 1,
"method": method,
"params": params.map(|p| p.into())
})
}
fn set_retry_policy(
&mut self,
retry_policy: ExponentialBackoff,
retry_strategy: Option<TransientErrorRetryStrategy>,
) -> Result<(), anyhow::Error>;
fn update_endpoint_manager_client(
&mut self,
client: ClientWithMiddleware,
) -> Result<(), anyhow::Error>;
}
#[async_trait::async_trait]
pub trait RotatingTransport: BlockchainTransport {
async fn try_connect(&self, url: &str) -> Result<(), anyhow::Error>;
async fn update_client(&self, url: &str) -> Result<(), anyhow::Error>;
}
pub struct TransientErrorRetryStrategy;
impl RetryableStrategy for TransientErrorRetryStrategy {
fn handle(
&self,
res: &Result<reqwest::Response, reqwest_middleware::Error>,
) -> Option<Retryable> {
match res {
Ok(success) => default_on_request_success(success),
Err(error) => default_on_request_failure(error),
}
}
}