1use corepc_client::client_sync::{v28::Client, Auth};
2use corepc_client::types::v28::{
3 EstimateSmartFee, GetBlockStats, GetBlockchainInfo, GetChainTips, GetMempoolInfo, GetNetTotals,
4 GetNetworkInfo, GetPeerInfo,
5};
6use serde::Deserialize;
7
8use crate::Error;
9use crate::config::NodeConfig;
10
11#[derive(Clone, Debug, Deserialize)]
17pub struct MiningInfo {
18 pub blocks: u64,
19 #[serde(rename = "currentblockweight")]
20 pub current_block_weight: Option<u64>,
21 #[serde(rename = "currentblocktx")]
22 pub current_block_tx: Option<i64>,
23 pub difficulty: f64,
24 #[serde(rename = "networkhashps")]
25 pub network_hash_ps: f64,
26 #[serde(rename = "pooledtx")]
27 pub pooled_tx: i64,
28 pub chain: String,
29 pub warnings: Vec<String>,
30}
31
32#[derive(Clone, Debug, Deserialize)]
38pub struct ChainTxStats {
39 pub time: i64,
40 #[serde(rename = "txcount")]
41 pub tx_count: i64,
42 pub window_final_block_hash: String,
43 pub window_final_block_height: i64,
44 pub window_block_count: i64,
45 pub window_tx_count: Option<i64>,
46 pub window_interval: Option<i64>,
47 #[serde(rename = "txrate")]
48 pub tx_rate: Option<f64>,
49}
50
51pub trait NodeClient: Send + Sync {
52 fn get_blockchain_info(&self) -> Result<GetBlockchainInfo, Error>;
53 fn get_mempool_info(&self) -> Result<GetMempoolInfo, Error>;
54 fn get_network_info(&self) -> Result<GetNetworkInfo, Error>;
55 fn get_peer_info(&self) -> Result<GetPeerInfo, Error>;
56 fn get_mining_info(&self) -> Result<MiningInfo, Error>;
57 fn get_chain_tx_stats(&self) -> Result<ChainTxStats, Error>;
58 fn get_net_totals(&self) -> Result<GetNetTotals, Error>;
59 fn estimate_smart_fee(&self, conf_target: u32) -> Result<EstimateSmartFee, Error>;
60 fn get_chain_tips(&self) -> Result<GetChainTips, Error>;
61 fn uptime(&self) -> Result<u32, Error>;
62 fn get_block_stats_by_height(&self, height: u32) -> Result<GetBlockStats, Error>;
63}
64
65pub struct BitcoinNode {
66 client: Client,
67}
68
69impl BitcoinNode {
70 pub fn new(config: &NodeConfig) -> Result<Self, Error> {
71 let auth = Auth::UserPass(config.rpc_user.clone(), config.rpc_password.clone());
72 let client = Client::new_with_auth(&config.rpc_url, auth)
73 .map_err(|e| Error::Config(format!("failed to create RPC client: {e}")))?;
74 Ok(Self { client })
75 }
76}
77
78impl NodeClient for BitcoinNode {
79 fn get_blockchain_info(&self) -> Result<GetBlockchainInfo, Error> {
80 Ok(self.client.get_blockchain_info()?)
81 }
82
83 fn get_mempool_info(&self) -> Result<GetMempoolInfo, Error> {
84 Ok(self.client.get_mempool_info()?)
85 }
86
87 fn get_network_info(&self) -> Result<GetNetworkInfo, Error> {
88 Ok(self.client.get_network_info()?)
89 }
90
91 fn get_peer_info(&self) -> Result<GetPeerInfo, Error> {
92 Ok(self.client.get_peer_info()?)
93 }
94
95 fn get_mining_info(&self) -> Result<MiningInfo, Error> {
96 Ok(self.client.call::<MiningInfo>("getmininginfo", &[])?)
99 }
100
101 fn get_chain_tx_stats(&self) -> Result<ChainTxStats, Error> {
102 Ok(self.client.call::<ChainTxStats>("getchaintxstats", &[])?)
105 }
106
107 fn get_net_totals(&self) -> Result<GetNetTotals, Error> {
108 Ok(self.client.get_net_totals()?)
109 }
110
111 fn estimate_smart_fee(&self, conf_target: u32) -> Result<EstimateSmartFee, Error> {
112 Ok(self.client.estimate_smart_fee(conf_target)?)
113 }
114
115 fn get_chain_tips(&self) -> Result<GetChainTips, Error> {
116 Ok(self.client.get_chain_tips()?)
117 }
118
119 fn uptime(&self) -> Result<u32, Error> {
120 Ok(self.client.uptime()?)
121 }
122
123 fn get_block_stats_by_height(&self, height: u32) -> Result<GetBlockStats, Error> {
124 Ok(self.client.get_block_stats_by_height(height)?)
125 }
126}