ogmios_client/
jsonrpsee.rs1use crate::{OgmiosClient, OgmiosClientError, OgmiosParams, query_ledger_state::QueryLedgerState};
5use jsonrpsee::{
6 core::{ClientError, client::ClientT, traits::ToRpcParams},
7 http_client::{HttpClient, HttpClientBuilder},
8 ws_client::{WsClient, WsClientBuilder},
9};
10use serde::de::DeserializeOwned;
11use serde_json::json;
12use std::time::Duration;
13
14fn request_to_json(method: &str, params: impl ToRpcParams) -> Result<String, OgmiosClientError> {
16 let params = params
17 .to_rpc_params()
18 .map_err(|err| OgmiosClientError::ParametersError(err.to_string()))?
19 .unwrap_or_default();
20
21 let req = json!({
22 "method": method,
23 "params": params
24 });
25
26 serde_json::to_string(&req).map_err(|err| OgmiosClientError::ParametersError(err.to_string()))
27}
28
29fn response_to_json(resp: &Result<serde_json::Value, ClientError>) -> String {
31 match &resp {
32 Ok(resp) => serde_json::to_string(&resp).unwrap(),
33 Err(jsonrpsee::core::ClientError::Call(err)) => serde_json::to_string(&err).unwrap(),
34 Err(err) => err.to_string(),
35 }
36}
37
38pub enum OgmiosClients {
40 HttpClient(HttpClient),
41 WsClient(WsClient),
42}
43
44pub async fn client_for_url(addr: &str, timeout: Duration) -> Result<OgmiosClients, String> {
47 if addr.starts_with("http") || addr.starts_with("https") {
48 let client = HttpClientBuilder::default()
49 .request_timeout(timeout)
50 .build(addr)
51 .map_err(|e| format!("Couldn't create HTTP client: {}", e))?;
52
53 let http_client = OgmiosClients::HttpClient(client);
54
55 http_client
57 .get_tip()
58 .await
59 .map_err(|e| format!("Failed to test HTTP connection: {}", e))?;
60
61 Ok(http_client)
62 } else if addr.starts_with("ws") || addr.starts_with("wss") {
63 let client = WsClientBuilder::default()
64 .request_timeout(timeout)
65 .build(addr.to_owned())
66 .await
67 .map_err(|e| format!("Couldn't create WebSockets client: {}", e))?;
68 Ok(OgmiosClients::WsClient(client))
69 } else {
70 Err(format!("Invalid Schema of URL: '{}'. Expected http, https, ws or wss.", addr))
71 }
72}
73
74impl OgmiosClient for OgmiosClients {
75 async fn request<T: DeserializeOwned>(
77 &self,
78 method: &str,
79 params: OgmiosParams,
80 ) -> Result<T, OgmiosClientError> {
81 log::debug!("request: {}", request_to_json(method, params.clone())?);
82 let response = match self {
83 OgmiosClients::HttpClient(client) => {
84 ClientT::request::<serde_json::Value, _>(client, method, params).await
85 },
86 OgmiosClients::WsClient(client) => {
87 ClientT::request::<serde_json::Value, _>(client, method, params).await
88 },
89 };
90 log::debug!("response: {}", response_to_json(&response));
91
92 serde_json::from_value(response?)
93 .map_err(|err| OgmiosClientError::ResponseError(err.to_string()))
94 }
95}
96
97impl From<jsonrpsee::core::ClientError> for OgmiosClientError {
98 fn from(e: jsonrpsee::core::ClientError) -> Self {
99 match e {
100 jsonrpsee::core::ClientError::ParseError(e) => {
101 OgmiosClientError::ResponseError(e.to_string())
102 },
103 e => OgmiosClientError::RequestError(e.to_string()),
104 }
105 }
106}