blockchain_client/
client.rs1use serde::{Deserialize, Serialize};
2use std::time::Duration;
3
4#[derive(Debug, Clone)]
5pub struct RpcConfig {
6 pub url: String,
7 pub username: String,
8 pub password: String,
9 pub timeout_secs: u64,
10 pub pool_max_idle_per_host: usize,
11 pub pool_idle_timeout_secs: u64,
12 pub tcp_keepalive_secs: u64,
13}
14
15impl RpcConfig {
16 pub fn new(url: String, username: String, password: String) -> Self {
17 Self {
18 url,
19 username,
20 password,
21 timeout_secs: 30,
22 pool_max_idle_per_host: 4,
23 pool_idle_timeout_secs: 300,
24 tcp_keepalive_secs: 60,
25 }
26 }
27
28 pub fn with_timeout(mut self, timeout_secs: u64) -> Self {
29 self.timeout_secs = timeout_secs;
30 self
31 }
32
33 pub fn with_pool_max_idle_per_host(mut self, pool_max_idle_per_host: usize) -> Self {
34 self.pool_max_idle_per_host = pool_max_idle_per_host.max(1);
35 self
36 }
37
38 pub fn with_pool_idle_timeout(mut self, pool_idle_timeout_secs: u64) -> Self {
39 self.pool_idle_timeout_secs = pool_idle_timeout_secs;
40 self
41 }
42
43 pub fn with_tcp_keepalive(mut self, tcp_keepalive_secs: u64) -> Self {
44 self.tcp_keepalive_secs = tcp_keepalive_secs;
45 self
46 }
47
48 pub fn with_connection_pool(
49 mut self,
50 pool_max_idle_per_host: usize,
51 pool_idle_timeout_secs: u64,
52 tcp_keepalive_secs: u64,
53 ) -> Self {
54 self.pool_max_idle_per_host = pool_max_idle_per_host.max(1);
55 self.pool_idle_timeout_secs = pool_idle_timeout_secs;
56 self.tcp_keepalive_secs = tcp_keepalive_secs;
57 self
58 }
59
60 pub fn timeout(&self) -> Duration {
61 Duration::from_secs(self.timeout_secs)
62 }
63
64 pub fn pool_idle_timeout(&self) -> Duration {
65 Duration::from_secs(self.pool_idle_timeout_secs)
66 }
67
68 pub fn tcp_keepalive(&self) -> Duration {
69 Duration::from_secs(self.tcp_keepalive_secs)
70 }
71}
72
73#[derive(Debug, Serialize)]
74pub struct JsonRpcRequest {
75 pub jsonrpc: String,
76 pub id: String,
77 pub method: String,
78 pub params: serde_json::Value,
79}
80
81impl JsonRpcRequest {
82 pub fn new(method: String, params: serde_json::Value) -> Self {
83 Self {
84 jsonrpc: "1.0".to_string(),
85 id: "blockchain-client".to_string(),
86 method,
87 params,
88 }
89 }
90}
91
92#[derive(Debug, Deserialize)]
93pub struct JsonRpcResponse<T> {
94 pub result: Option<T>,
95 pub error: Option<JsonRpcError>,
96 pub id: String,
97}
98
99#[derive(Debug, Deserialize)]
100pub struct JsonRpcError {
101 pub code: i32,
102 pub message: String,
103}
104
105#[cfg(test)]
106mod tests {
107 use super::RpcConfig;
108 use std::time::Duration;
109
110 #[test]
111 fn rpc_config_uses_pooling_defaults() {
112 let config = RpcConfig::new(
113 "http://localhost:9332".to_string(),
114 "user".to_string(),
115 "pass".to_string(),
116 );
117
118 assert_eq!(config.timeout(), Duration::from_secs(30));
119 assert_eq!(config.pool_max_idle_per_host, 4);
120 assert_eq!(config.pool_idle_timeout(), Duration::from_secs(300));
121 assert_eq!(config.tcp_keepalive(), Duration::from_secs(60));
122 }
123
124 #[test]
125 fn rpc_config_allows_pooling_overrides() {
126 let config = RpcConfig::new(
127 "http://localhost:9332".to_string(),
128 "user".to_string(),
129 "pass".to_string(),
130 )
131 .with_connection_pool(8, 600, 120)
132 .with_timeout(45);
133
134 assert_eq!(config.timeout(), Duration::from_secs(45));
135 assert_eq!(config.pool_max_idle_per_host, 8);
136 assert_eq!(config.pool_idle_timeout(), Duration::from_secs(600));
137 assert_eq!(config.tcp_keepalive(), Duration::from_secs(120));
138 }
139}