1mod otx_pool_client;
2
3pub use otx_pool_client::OtxPoolRpcClient;
4
5use anyhow::{anyhow, Result};
6use jsonrpc_core::types::{
7 Call, Id, MethodCall, Output, Params, Request, Response, Value, Version,
8};
9use reqwest::blocking::Client;
10use serde::{de::DeserializeOwned, Serialize};
11
12#[derive(Clone, Debug)]
13pub struct RpcClient {
14 client: Client,
15 uri: String,
16}
17
18impl RpcClient {
19 pub fn new(uri: String) -> Self {
20 RpcClient {
21 client: Client::new(),
22 uri,
23 }
24 }
25
26 pub(crate) fn rpc_exec(&self, request: &Request) -> Result<Response> {
27 let http_response = self.client.post(self.uri.as_str()).json(request).send()?;
28
29 if !http_response.status().is_success() {
30 return Err(anyhow!("http response"));
31 }
32
33 http_response.json().map_err(anyhow::Error::new)
34 }
35}
36
37pub fn request<T: Serialize, U: DeserializeOwned>(
38 client: &RpcClient,
39 method: &str,
40 params: T,
41) -> Result<U> {
42 let request = build_request(method, params)?;
43 let response = client.rpc_exec(&request)?;
44 handle_response(response)
45}
46
47fn build_request<T: Serialize>(method: &str, params: T) -> Result<Request> {
48 let request = Request::Single(Call::MethodCall(MethodCall {
49 jsonrpc: Some(Version::V2),
50 method: method.to_string(),
51 params: parse_params(¶ms)?,
52 id: Id::Num(42),
53 }));
54 Ok(request)
55}
56
57fn parse_params<T: Serialize>(params: &T) -> Result<Params> {
58 let json = serde_json::to_value(params)?;
59
60 match json {
61 Value::Array(vec) => Ok(Params::Array(vec)),
62 Value::Object(map) => Ok(Params::Map(map)),
63 Value::Null => Ok(Params::None),
64 _ => Err(anyhow!("parse params")),
65 }
66}
67
68fn handle_response<T: DeserializeOwned>(response: Response) -> Result<T> {
69 match response {
70 Response::Single(output) => handle_output(output),
71 _ => unreachable!(),
72 }
73}
74
75fn handle_output<T: DeserializeOwned>(output: Output) -> Result<T> {
76 let value = match output {
77 Output::Success(succ) => succ.result,
78 Output::Failure(_) => return Err(anyhow!("handle output: {:?}", output)),
79 };
80
81 serde_json::from_value(value).map_err(anyhow::Error::new)
82}