otx_pool_client/
lib.rs

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(&params)?,
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}