jsonrpc_utils/
client.rs

1#[cfg(feature = "client")]
2#[derive(Clone)]
3pub struct HttpClient {
4    client: reqwest::Client,
5    url: String,
6}
7
8#[cfg(feature = "client")]
9impl HttpClient {
10    pub fn new(url: String) -> Self {
11        Self {
12            client: reqwest::Client::new(),
13            url,
14        }
15    }
16
17    pub fn url(&self) -> &str {
18        &self.url
19    }
20
21    pub fn with_client(url: String, client: reqwest::Client) -> Self {
22        Self { client, url }
23    }
24
25    pub async fn rpc(
26        &self,
27        method: &str,
28        params: &serde_json::value::RawValue,
29    ) -> anyhow::Result<serde_json::Value> {
30        let response_body = self
31            .client
32            .post(&self.url)
33            .header("content-type", "application/json")
34            .body(serde_json::to_string(&serde_json::json!({
35                "jsonrpc": "2.0",
36                "id": 0,
37                "method": method,
38                "params": params,
39            }))?)
40            .send()
41            .await?
42            .error_for_status()?
43            .bytes()
44            .await?;
45        let result = serde_json::from_slice::<jsonrpc_core::Response>(&response_body[..])?;
46        let result = match result {
47            jsonrpc_core::Response::Single(o) => match o {
48                jsonrpc_core::Output::Success(s) => s.result,
49                jsonrpc_core::Output::Failure(f) => return Err(f.error.into()),
50            },
51            _ => anyhow::bail!("unexpected batch response"),
52        };
53        Ok(result)
54    }
55}
56
57#[cfg(feature = "blocking-client")]
58#[derive(Clone)]
59pub struct BlockingHttpClient {
60    client: reqwest::blocking::Client,
61    url: String,
62}
63
64#[cfg(feature = "blocking-client")]
65impl BlockingHttpClient {
66    pub fn new(url: String) -> Self {
67        Self {
68            client: reqwest::blocking::Client::new(),
69            url,
70        }
71    }
72
73    pub fn url(&self) -> &str {
74        &self.url
75    }
76
77    pub fn with_client(url: String, client: reqwest::blocking::Client) -> Self {
78        Self { client, url }
79    }
80
81    pub fn rpc(
82        &self,
83        method: &str,
84        params: &serde_json::value::RawValue,
85    ) -> anyhow::Result<serde_json::Value> {
86        let response_body = self
87            .client
88            .post(&self.url)
89            .header("content-type", "application/json")
90            .body(serde_json::to_string(&serde_json::json!({
91                "jsonrpc": "2.0",
92                "id": 0,
93                "method": method,
94                "params": params,
95            }))?)
96            .send()?
97            .error_for_status()?
98            .bytes()?;
99        let result = serde_json::from_slice::<jsonrpc_core::Response>(&response_body[..])?;
100        let result = match result {
101            jsonrpc_core::Response::Single(o) => match o {
102                jsonrpc_core::Output::Success(s) => s.result,
103                jsonrpc_core::Output::Failure(f) => return Err(f.error.into()),
104            },
105            _ => anyhow::bail!("unexpected batch response"),
106        };
107        Ok(result)
108    }
109}