accumulate_client/runtime/
rpc.rs1#![allow(clippy::unwrap_used)]
3
4use serde::{Serialize, de::DeserializeOwned};
5use serde_json::json;
6use std::time::Duration;
7use crate::errors::Error;
8use async_trait::async_trait;
9
10#[derive(Debug, Clone)]
11pub struct HttpTransport {
12 pub base_url: String,
13 pub client: reqwest::Client,
14 pub timeout: Duration,
15}
16
17impl HttpTransport {
18 pub fn new(base_url: impl Into<String>) -> Self {
19 Self {
20 base_url: base_url.into(),
21 client: reqwest::Client::builder()
22 .timeout(Duration::from_secs(30))
23 .build()
24 .unwrap(),
25 timeout: Duration::from_secs(30),
26 }
27 }
28
29 pub fn with_timeout(base_url: impl Into<String>, timeout: Duration) -> Self {
30 Self {
31 base_url: base_url.into(),
32 client: reqwest::Client::builder()
33 .timeout(timeout)
34 .build()
35 .unwrap(),
36 timeout,
37 }
38 }
39}
40
41#[async_trait]
42impl crate::generated::api_methods::AccumulateRpc for HttpTransport {
43 async fn rpc_call<TP: Serialize + Send + Sync, TR: DeserializeOwned>(
44 &self, method: &str, params: &TP
45 ) -> Result<TR, Error> {
46 let payload = json!({
47 "jsonrpc": "2.0",
48 "id": 1,
49 "method": method,
50 "params": params
51 });
52
53 let res = self.client.post(&self.base_url)
54 .json(&payload)
55 .send().await
56 .map_err(|e| Error::General(format!("Transport error: {}", e)))?;
57
58 if !res.status().is_success() {
59 return Err(Error::General(format!("HTTP status error: {}", res.status().as_u16())));
60 }
61
62 let v: serde_json::Value = res.json().await
63 .map_err(|e| Error::General(format!("Failed to parse JSON response: {}", e)))?;
64
65 if let Some(e) = v.get("error") {
66 let code = e.get("code").and_then(|c| c.as_i64()).unwrap_or(0) as i32;
67 let message = e.get("message").and_then(|m| m.as_str()).unwrap_or("rpc error").to_string();
68 return Err(Error::General(format!("RPC error {}: {}", code, message)));
69 }
70
71 let result = v.get("result").ok_or_else(|| Error::General("missing result".into()))?;
72 let typed: TR = serde_json::from_value(result.clone())
73 .map_err(|e| Error::General(format!("Failed to deserialize result: {}", e)))?;
74 Ok(typed)
75 }
76}