polymesh_api_client/
rpc.rs1use jsonrpsee::core::{
2 client::{BatchResponse, ClientT, Subscription, SubscriptionClientT},
3 params::{ArrayParams, BatchRequestBuilder},
4};
5#[cfg(target_arch = "wasm32")]
6use jsonrpsee::wasm_client::{Client as WasmClient, WasmClientBuilder};
7#[cfg(not(target_arch = "wasm32"))]
8use jsonrpsee::{
9 http_client::{HttpClient, HttpClientBuilder},
10 ws_client::{WsClient, WsClientBuilder},
11};
12
13use sp_std::prelude::*;
14
15#[cfg(feature = "serde")]
16use serde::de::DeserializeOwned;
17
18use crate::error::*;
19
20#[derive(Debug)]
21enum InnerRpcClient {
22 #[cfg(not(target_arch = "wasm32"))]
23 Ws(WsClient),
24 #[cfg(not(target_arch = "wasm32"))]
25 Http(HttpClient),
26 #[cfg(target_arch = "wasm32")]
27 Wasm(WasmClient),
28}
29
30#[derive(Debug)]
31pub struct RpcClient {
32 client: InnerRpcClient,
33}
34
35impl RpcClient {
36 pub async fn new(url: &str) -> Result<Self> {
37 #[cfg(not(target_arch = "wasm32"))]
38 {
39 if url.starts_with("http") {
40 Self::new_http(url)
41 } else if url.starts_with("ws") {
42 Self::new_ws(url).await
43 } else {
44 Err(Error::RpcClient(format!("Unsupported url: {url}")))
45 }
46 }
47 #[cfg(target_arch = "wasm32")]
48 Self::new_wasm(url).await
49 }
50
51 #[cfg(not(target_arch = "wasm32"))]
52 async fn new_ws(url: &str) -> Result<Self> {
53 let url = url.parse::<http::Uri>()?;
55 let url = if url.port().is_none() {
56 let (scheme, port) = match url.scheme().map(|s| s.as_str()) {
58 Some("wss") => ("wss", 443),
59 _ => ("ws", 80),
60 };
61 let host = url.authority().map(|a| a.as_str()).unwrap_or_else(|| "");
62 let authority = format!("{}:{}", host, port);
63 let path = url
64 .path_and_query()
65 .map(|p| p.as_str())
66 .unwrap_or_else(|| "");
67 let url = http::Uri::builder()
68 .scheme(scheme)
69 .authority(authority)
70 .path_and_query(path)
71 .build()?;
72 url.to_string()
73 } else {
74 url.to_string()
75 };
76 let client = WsClientBuilder::default()
77 .max_concurrent_requests(16 * 1024)
78 .max_request_size(1024 * 1024 * 1024)
79 .build(&url)
80 .await?;
81 Ok(Self {
82 client: InnerRpcClient::Ws(client),
83 })
84 }
85
86 #[cfg(not(target_arch = "wasm32"))]
87 fn new_http(url: &str) -> Result<Self> {
88 let client = HttpClientBuilder::default()
89 .max_request_size(1024 * 1024 * 1024)
90 .build(&url)?;
91 Ok(Self {
92 client: InnerRpcClient::Http(client),
93 })
94 }
95
96 #[cfg(target_arch = "wasm32")]
97 async fn new_wasm(url: &str) -> Result<Self> {
98 let client = WasmClientBuilder::default().build(&url).await?;
99 Ok(Self {
100 client: InnerRpcClient::Wasm(client),
101 })
102 }
103
104 #[cfg(feature = "serde")]
105 pub async fn subscribe<'a, Notif>(
106 &self,
107 subscribe_method: &'a str,
108 params: ArrayParams,
109 unsubscribe_method: &'a str,
110 ) -> Result<Subscription<Notif>>
111 where
112 Notif: DeserializeOwned,
113 {
114 Ok(match &self.client {
115 #[cfg(not(target_arch = "wasm32"))]
116 InnerRpcClient::Ws(ws) => {
117 ws.subscribe(subscribe_method, params, unsubscribe_method)
118 .await
119 }
120 #[cfg(not(target_arch = "wasm32"))]
121 InnerRpcClient::Http(http) => {
122 http
123 .subscribe(subscribe_method, params, unsubscribe_method)
124 .await
125 }
126 #[cfg(target_arch = "wasm32")]
127 InnerRpcClient::Wasm(http) => {
128 http
129 .subscribe(subscribe_method, params, unsubscribe_method)
130 .await
131 }
132 }?)
133 }
134
135 #[cfg(feature = "serde")]
136 pub async fn request<'a, R>(&self, method: &'a str, params: ArrayParams) -> Result<R>
137 where
138 R: DeserializeOwned,
139 {
140 Ok(match &self.client {
141 #[cfg(not(target_arch = "wasm32"))]
142 InnerRpcClient::Ws(ws) => ws.request(method, params).await,
143 #[cfg(not(target_arch = "wasm32"))]
144 InnerRpcClient::Http(http) => http.request(method, params).await,
145 #[cfg(target_arch = "wasm32")]
146 InnerRpcClient::Wasm(http) => http.request(method, params).await,
147 }?)
148 }
149
150 #[cfg(feature = "serde")]
151 pub async fn batch_request<'a, R>(
152 &self,
153 batch: BatchRequestBuilder<'a>,
154 ) -> Result<BatchResponse<'a, R>>
155 where
156 R: DeserializeOwned + Default + Clone + alloc::fmt::Debug + 'a,
157 {
158 Ok(match &self.client {
159 #[cfg(not(target_arch = "wasm32"))]
160 InnerRpcClient::Ws(ws) => ws.batch_request(batch).await,
161 #[cfg(not(target_arch = "wasm32"))]
162 InnerRpcClient::Http(http) => http.batch_request(batch).await,
163 #[cfg(target_arch = "wasm32")]
164 InnerRpcClient::Wasm(http) => http.batch_request(batch).await,
165 }?)
166 }
167}