Merge pull request #131 from tnull/2024-02-align-rustfmt
[ldk-sample] / src / convert.rs
1 use bitcoin::{Address, BlockHash, Txid};
2 use lightning_block_sync::http::JsonResponse;
3 use std::convert::TryInto;
4 use std::str::FromStr;
5
6 pub struct FundedTx {
7         pub changepos: i64,
8         pub hex: String,
9 }
10
11 impl TryInto<FundedTx> for JsonResponse {
12         type Error = std::io::Error;
13         fn try_into(self) -> std::io::Result<FundedTx> {
14                 Ok(FundedTx {
15                         changepos: self.0["changepos"].as_i64().unwrap(),
16                         hex: self.0["hex"].as_str().unwrap().to_string(),
17                 })
18         }
19 }
20
21 pub struct RawTx(pub String);
22
23 impl TryInto<RawTx> for JsonResponse {
24         type Error = std::io::Error;
25         fn try_into(self) -> std::io::Result<RawTx> {
26                 Ok(RawTx(self.0.as_str().unwrap().to_string()))
27         }
28 }
29
30 pub struct SignedTx {
31         pub complete: bool,
32         pub hex: String,
33 }
34
35 impl TryInto<SignedTx> for JsonResponse {
36         type Error = std::io::Error;
37         fn try_into(self) -> std::io::Result<SignedTx> {
38                 Ok(SignedTx {
39                         hex: self.0["hex"].as_str().unwrap().to_string(),
40                         complete: self.0["complete"].as_bool().unwrap(),
41                 })
42         }
43 }
44
45 pub struct NewAddress(pub String);
46 impl TryInto<NewAddress> for JsonResponse {
47         type Error = std::io::Error;
48         fn try_into(self) -> std::io::Result<NewAddress> {
49                 Ok(NewAddress(self.0.as_str().unwrap().to_string()))
50         }
51 }
52
53 pub struct FeeResponse {
54         pub feerate_sat_per_kw: Option<u32>,
55         pub errored: bool,
56 }
57
58 impl TryInto<FeeResponse> for JsonResponse {
59         type Error = std::io::Error;
60         fn try_into(self) -> std::io::Result<FeeResponse> {
61                 let errored = !self.0["errors"].is_null();
62                 Ok(FeeResponse {
63                         errored,
64                         feerate_sat_per_kw: match self.0["feerate"].as_f64() {
65                                 // Bitcoin Core gives us a feerate in BTC/KvB, which we need to convert to
66                                 // satoshis/KW. Thus, we first multiply by 10^8 to get satoshis, then divide by 4
67                                 // to convert virtual-bytes into weight units.
68                                 Some(feerate_btc_per_kvbyte) => {
69                                         Some((feerate_btc_per_kvbyte * 100_000_000.0 / 4.0).round() as u32)
70                                 },
71                                 None => None,
72                         },
73                 })
74         }
75 }
76
77 pub struct MempoolMinFeeResponse {
78         pub feerate_sat_per_kw: Option<u32>,
79         pub errored: bool,
80 }
81
82 impl TryInto<MempoolMinFeeResponse> for JsonResponse {
83         type Error = std::io::Error;
84         fn try_into(self) -> std::io::Result<MempoolMinFeeResponse> {
85                 let errored = !self.0["errors"].is_null();
86                 assert_eq!(self.0["maxmempool"].as_u64(), Some(300000000));
87                 Ok(MempoolMinFeeResponse {
88                         errored,
89                         feerate_sat_per_kw: match self.0["mempoolminfee"].as_f64() {
90                                 // Bitcoin Core gives us a feerate in BTC/KvB, which we need to convert to
91                                 // satoshis/KW. Thus, we first multiply by 10^8 to get satoshis, then divide by 4
92                                 // to convert virtual-bytes into weight units.
93                                 Some(feerate_btc_per_kvbyte) => {
94                                         Some((feerate_btc_per_kvbyte * 100_000_000.0 / 4.0).round() as u32)
95                                 },
96                                 None => None,
97                         },
98                 })
99         }
100 }
101
102 pub struct BlockchainInfo {
103         pub latest_height: usize,
104         pub latest_blockhash: BlockHash,
105         pub chain: String,
106 }
107
108 impl TryInto<BlockchainInfo> for JsonResponse {
109         type Error = std::io::Error;
110         fn try_into(self) -> std::io::Result<BlockchainInfo> {
111                 Ok(BlockchainInfo {
112                         latest_height: self.0["blocks"].as_u64().unwrap() as usize,
113                         latest_blockhash: BlockHash::from_str(self.0["bestblockhash"].as_str().unwrap())
114                                 .unwrap(),
115                         chain: self.0["chain"].as_str().unwrap().to_string(),
116                 })
117         }
118 }
119
120 pub struct ListUnspentUtxo {
121         pub txid: Txid,
122         pub vout: u32,
123         pub amount: u64,
124         pub address: Address,
125 }
126
127 pub struct ListUnspentResponse(pub Vec<ListUnspentUtxo>);
128
129 impl TryInto<ListUnspentResponse> for JsonResponse {
130         type Error = std::io::Error;
131         fn try_into(self) -> Result<ListUnspentResponse, Self::Error> {
132                 let utxos = self
133                         .0
134                         .as_array()
135                         .unwrap()
136                         .iter()
137                         .map(|utxo| ListUnspentUtxo {
138                                 txid: Txid::from_str(&utxo["txid"].as_str().unwrap().to_string()).unwrap(),
139                                 vout: utxo["vout"].as_u64().unwrap() as u32,
140                                 amount: bitcoin::Amount::from_btc(utxo["amount"].as_f64().unwrap())
141                                         .unwrap()
142                                         .to_sat(),
143                                 address: Address::from_str(&utxo["address"].as_str().unwrap().to_string())
144                                         .unwrap()
145                                         .assume_checked(), // the expected network is not known at this point
146                         })
147                         .collect();
148                 Ok(ListUnspentResponse(utxos))
149         }
150 }