1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use jsonrpsee::core::client::{ClientT, Subscription, SubscriptionClientT};
use jsonrpsee::http_client::{HttpClient, HttpClientBuilder};
use jsonrpsee::types::ParamsSer;
use jsonrpsee::ws_client::{WsClient, WsClientBuilder};
use serde::de::DeserializeOwned;
use crate::error::*;
#[derive(Debug)]
enum InnerRpcClient {
Ws(WsClient),
Http(HttpClient),
}
#[derive(Debug)]
pub struct RpcClient {
client: InnerRpcClient,
}
impl RpcClient {
pub async fn new(url: &str) -> Result<Self> {
if url.starts_with("Http") {
Self::new_http(url)
} else if url.starts_with("ws") {
Self::new_ws(url).await
} else {
Err(Error::RpcClient(format!("Unsupported url: {url}")))
}
}
async fn new_ws(url: &str) -> Result<Self> {
let client = WsClientBuilder::default().build(&url).await?;
Ok(Self {
client: InnerRpcClient::Ws(client),
})
}
fn new_http(url: &str) -> Result<Self> {
let client = HttpClientBuilder::default().build(&url)?;
Ok(Self {
client: InnerRpcClient::Http(client),
})
}
pub async fn subscribe<'a, Notif>(
&self,
subscribe_method: &'a str,
params: Option<ParamsSer<'a>>,
unsubscribe_method: &'a str,
) -> Result<Subscription<Notif>>
where
Notif: DeserializeOwned,
{
Ok(match &self.client {
InnerRpcClient::Ws(ws) => {
ws.subscribe(subscribe_method, params, unsubscribe_method)
.await
}
InnerRpcClient::Http(http) => {
http
.subscribe(subscribe_method, params, unsubscribe_method)
.await
}
}?)
}
pub async fn request<'a, R>(&self, method: &'a str, params: Option<ParamsSer<'a>>) -> Result<R>
where
R: DeserializeOwned,
{
Ok(match &self.client {
InnerRpcClient::Ws(ws) => ws.request(method, params).await,
InnerRpcClient::Http(http) => http.request(method, params).await,
}?)
}
pub async fn batch_request<'a, R>(
&self,
batch: Vec<(&'a str, Option<ParamsSer<'a>>)>,
) -> Result<Vec<R>>
where
R: DeserializeOwned + Default + Clone,
{
Ok(match &self.client {
InnerRpcClient::Ws(ws) => ws.batch_request(batch).await,
InnerRpcClient::Http(http) => http.batch_request(batch).await,
}?)
}
}