use std::net::SocketAddr;
use reqwest::Client;
use crate::BoxError;
#[derive(Clone, Debug)]
pub struct RpcRequestClient {
client: Client,
rpc_address: SocketAddr,
}
impl RpcRequestClient {
pub fn new(rpc_address: SocketAddr) -> Self {
Self {
client: Client::new(),
rpc_address,
}
}
pub async fn call(
&self,
method: impl AsRef<str>,
params: impl AsRef<str>,
) -> reqwest::Result<reqwest::Response> {
let method = method.as_ref();
let params = params.as_ref();
self.client
.post(format!("http://{}", &self.rpc_address))
.body(format!(
r#"{{"jsonrpc": "2.0", "method": "{method}", "params": {params}, "id":123 }}"#
))
.header("Content-Type", "application/json")
.send()
.await
}
pub async fn call_with_content_type(
&self,
method: impl AsRef<str>,
params: impl AsRef<str>,
content_type: String,
) -> reqwest::Result<reqwest::Response> {
let method = method.as_ref();
let params = params.as_ref();
self.client
.post(format!("http://{}", &self.rpc_address))
.body(format!(
r#"{{"jsonrpc": "2.0", "method": "{method}", "params": {params}, "id":123 }}"#
))
.header("Content-Type", content_type)
.send()
.await
}
pub async fn call_with_no_content_type(
&self,
method: impl AsRef<str>,
params: impl AsRef<str>,
) -> reqwest::Result<reqwest::Response> {
let method = method.as_ref();
let params = params.as_ref();
self.client
.post(format!("http://{}", &self.rpc_address))
.body(format!(
r#"{{"jsonrpc": "2.0", "method": "{method}", "params": {params}, "id":123 }}"#
))
.send()
.await
}
pub async fn text_from_call(
&self,
method: impl AsRef<str>,
params: impl AsRef<str>,
) -> reqwest::Result<String> {
self.call(method, params).await?.text().await
}
pub async fn json_result_from_call<T: serde::de::DeserializeOwned>(
&self,
method: impl AsRef<str>,
params: impl AsRef<str>,
) -> std::result::Result<T, BoxError> {
Self::json_result_from_response_text(&self.text_from_call(method, params).await?)
}
fn json_result_from_response_text<T: serde::de::DeserializeOwned>(
response_text: &str,
) -> std::result::Result<T, BoxError> {
use jsonrpc_core::Output;
let output: Output = serde_json::from_str(response_text)?;
match output {
Output::Success(success) => Ok(serde_json::from_value(success.result)?),
Output::Failure(failure) => Err(failure.error.into()),
}
}
}