97e5556e971c0152b4cc52b0615bc001f9f75950
[ldk-sample] / src / bitcoind_client.rs
1 use base64;
2 use serde_json;
3
4 use bitcoin::blockdata::transaction::Transaction;
5 use bitcoin::consensus::encode;
6 use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
7 use lightning_block_sync::http::HttpEndpoint;
8 use lightning_block_sync::rpc::RpcClient;
9
10 use std::sync::Mutex;
11
12 pub struct BitcoindClient {
13     pub bitcoind_rpc_client: Mutex<RpcClient>,
14 }
15
16 impl BitcoindClient {
17     pub fn new(host: String, port: u16, path: Option<String>, rpc_user: String, rpc_password: String) ->
18         std::io::Result<Self>
19     {
20         let mut http_endpoint = HttpEndpoint::for_host(host).with_port(port);
21         if let Some(p) = path {
22             http_endpoint = http_endpoint.with_path(p);
23         }
24         let rpc_credentials = base64::encode(format!("{}:{}", rpc_user, rpc_password));
25         let bitcoind_rpc_client = RpcClient::new(&rpc_credentials, http_endpoint)?;
26         Ok(Self {
27             bitcoind_rpc_client: Mutex::new(bitcoind_rpc_client)
28         })
29     }
30 }
31
32 impl FeeEstimator for BitcoindClient {
33     fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
34         let mut rpc_client_guard = self.bitcoind_rpc_client.lock().unwrap();
35         match confirmation_target {
36             ConfirmationTarget::Background => {
37                 let conf_target = serde_json::json!(144);
38                 let estimate_mode = serde_json::json!("ECONOMICAL");
39                 let resp = rpc_client_guard.call_method("estimatesmartfee",
40                                                         &vec![conf_target, estimate_mode]).unwrap();
41                 if !resp["errors"].is_null() && resp["errors"].as_array().unwrap().len() > 0 {
42                     return 253
43                 }
44                 resp["feerate"].as_u64().unwrap() as u32
45             },
46             ConfirmationTarget::Normal => {
47                 let conf_target = serde_json::json!(18);
48                 let estimate_mode = serde_json::json!("ECONOMICAL");
49                 let resp = rpc_client_guard.call_method("estimatesmartfee",
50                                                         &vec![conf_target, estimate_mode]).unwrap();
51                 if !resp["errors"].is_null() && resp["errors"].as_array().unwrap().len() > 0 {
52                     return 253
53                 }
54                 resp["feerate"].as_u64().unwrap() as u32
55             },
56             ConfirmationTarget::HighPriority => {
57                 let conf_target = serde_json::json!(6);
58                 let estimate_mode = serde_json::json!("CONSERVATIVE");
59                 let resp = rpc_client_guard.call_method("estimatesmartfee",
60                                                         &vec![conf_target, estimate_mode]).unwrap();
61                 if !resp["errors"].is_null() && resp["errors"].as_array().unwrap().len() > 0 {
62                     return 253
63                 }
64                 resp["feerate"].as_u64().unwrap() as u32
65             },
66         }
67     }
68 }
69
70 impl BroadcasterInterface for BitcoindClient {
71           fn broadcast_transaction(&self, tx: &Transaction) {
72         let mut rpc_client_guard = self.bitcoind_rpc_client.lock().unwrap();
73         let tx_serialized = serde_json::json!(encode::serialize_hex(tx));
74         rpc_client_guard.call_method("sendrawtransaction", &vec![tx_serialized]).unwrap();
75     }
76 }