1use crate::error::{CirclesRpcError, Result};
2use alloy_json_rpc::{RpcRecv, RpcSend};
3#[cfg(feature = "ws")]
4use alloy_provider::GetSubscription;
5use alloy_provider::{Identity, Provider, ProviderBuilder, RootProvider};
6#[cfg(feature = "ws")]
7use alloy_transport_ws::WsConnect;
8use serde::de::DeserializeOwned;
9use std::borrow::Cow;
10
11#[derive(Clone, Debug)]
14pub struct RpcClient {
15 provider: RootProvider,
16}
17
18impl RpcClient {
19 pub fn new(provider: RootProvider) -> Self {
21 Self { provider }
22 }
23
24 pub fn http(url: reqwest::Url) -> Self {
26 let provider: RootProvider =
27 ProviderBuilder::<Identity, Identity>::default().connect_http(url);
28 Self { provider }
29 }
30
31 #[cfg(feature = "ws")]
33 pub async fn ws(url: reqwest::Url) -> Result<Self> {
34 let provider: RootProvider = ProviderBuilder::<Identity, Identity>::default()
35 .connect_ws(WsConnect::new(url.to_string()))
36 .await?;
37 Ok(Self { provider })
38 }
39
40 pub async fn call<Req, Resp>(&self, method: &str, params: Req) -> Result<Resp>
42 where
43 Req: RpcSend,
44 Resp: RpcRecv + DeserializeOwned,
45 {
46 let method: Cow<'static, str> = Cow::Owned(method.to_string());
47 self.provider
48 .raw_request(method, params)
49 .await
50 .map_err(CirclesRpcError::from)
51 }
52
53 pub fn provider(&self) -> &RootProvider {
55 &self.provider
56 }
57}
58
59#[cfg(feature = "ws")]
60impl RpcClient {
61 pub fn subscribe<P, R>(&self, params: P) -> Result<GetSubscription<P, R>>
63 where
64 P: RpcSend,
65 R: RpcRecv,
66 {
67 Ok(self.provider.subscribe(params))
68 }
69}