1pub use clightningrpc::responses::*;
3
4use serde::{de, Deserialize, Deserializer};
5use std::str::FromStr;
6
7#[derive(Clone, Copy, Debug)]
10pub struct MSat(pub u64);
11
12struct MSatVisitor;
13impl<'d> de::Visitor<'d> for MSatVisitor {
14 type Value = MSat;
15
16 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
17 where
18 E: de::Error,
19 {
20 if !s.ends_with("msat") {
21 return Err(E::custom("missing msat suffix"));
22 }
23
24 let numpart = s
25 .get(0..(s.len() - 4))
26 .ok_or_else(|| E::custom("missing msat suffix"))?;
27
28 let res = u64::from_str(numpart).map_err(|_| E::custom("not a number"))?;
29 Ok(MSat(res))
30 }
31
32 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
33 where
34 E: de::Error,
35 {
36 Ok(MSat(v as u64))
37 }
38
39 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
40 write!(formatter, "a bare integer or a string ending with \"msat\"")
41 }
42}
43
44impl<'d> Deserialize<'d> for MSat {
45 fn deserialize<D>(deserializer: D) -> Result<MSat, D::Error>
46 where
47 D: Deserializer<'d>,
48 {
49 deserializer.deserialize_any(MSatVisitor)
50 }
51}
52
53impl std::fmt::Display for MSat {
54 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
55 write!(f, "{}msat", self.0)
56 }
57}
58
59#[derive(Debug, Clone, Deserialize)]
60pub struct Withdraw {
61 pub tx: String,
62 pub txid: String,
63}
64
65#[derive(Debug, Clone, Deserialize)]
66pub struct FundChannel {
67 pub tx: String,
68 pub txid: String,
69
70 #[serde(rename = "outnum")]
71 pub outpoint: u32,
72 pub channel_id: String,
73 pub close_to: Option<String>,
74}
75
76#[derive(Debug, Clone, Deserialize)]
77pub struct GetInfo {
78 pub id: String,
79 pub alias: String,
80 pub color: String,
81 pub num_peers: u64,
82 pub num_pending_channels: u64,
83 pub num_active_channels: u64,
84 pub num_inactive_channels: u64,
85 pub version: String,
86 pub blockheight: u32,
87 pub network: String,
88 #[serde(rename = "lightning-dir")]
89 pub ligthning_dir: String,
90 pub warning_bitcoind_sync: Option<String>,
91 pub warning_lightningd_sync: Option<String>,
92}
93
94#[derive(Debug, Clone, Deserialize)]
95pub struct CloseChannel {
96 #[serde(rename = "type")]
97 pub close_type: String,
98 pub tx: String,
99 pub txid: String,
100}
101
102#[derive(Debug, Clone, Deserialize)]
103pub struct Invoice {
104 #[serde(rename = "expires_at")]
105 pub expiry_time: u32,
106 pub bolt11: String,
107 pub payment_hash: String,
108 pub payment_secret: Option<String>,
109}
110
111#[derive(Debug, Clone, Deserialize)]
112pub struct Pay {
113 pub destination: String,
114 pub payment_hash: String,
115 pub created_at: f64,
116 pub completed_at: Option<u64>,
117 pub parts: u32,
118 pub msatoshi: u64,
119 pub msatoshi_sent: u64,
120 pub preimage: Option<String>,
121 pub status: String,
122 pub bolt11: Option<String>,
123}
124
125#[derive(Debug, Clone, Deserialize)]
128pub struct ListPaysPay {
129 pub bolt11: Option<String>,
130 pub destination: String,
131 pub payment_hash: String,
132 pub created_at: f64,
133 pub completed_at: Option<u64>,
134 pub amount_msat: Option<MSat>,
137 pub amount_sent_msat: MSat,
138
139 #[serde(rename = "preimage")]
140 pub payment_preimage: Option<String>,
141
142 pub status: String,
143}
144
145#[derive(Debug, Clone, Deserialize)]
146pub struct ListPays {
147 pub pays: Vec<ListPaysPay>,
148}
149
150#[derive(Debug, Clone, Deserialize)]
152pub struct ListInvoiceInvoice {
153 pub label: String,
154 pub description: String,
155 pub payment_preimage: Option<String>,
156
157 #[serde(rename = "amount_msat")]
158 pub amount: Option<MSat>,
159
160 #[serde(rename = "amount_received_msat")]
161 pub received: Option<MSat>,
162
163 #[serde(rename = "paid_at")]
164 pub payment_time: Option<u32>,
165 pub status: String,
166
167 #[serde(rename = "expires_at")]
168 pub expiry_time: u32,
169 pub bolt11: String,
170 pub payment_hash: String,
171}
172
173#[derive(Debug, Clone, Deserialize)]
174pub struct ListInvoices {
175 pub invoices: Vec<ListInvoiceInvoice>,
176}
177
178#[derive(Debug, Clone, Deserialize)]
179pub struct Keysend {
180 pub destination: String,
181 pub status: String,
182 pub payment_preimage: Option<String>,
183 pub payment_hash: String,
184 pub msatoshi: Option<u64>,
185 pub msatoshi_sent: Option<u64>,
186 pub amount_sent_msat: Option<MSat>,
187 pub amount_msat: Option<MSat>,
188}
189
190#[derive(Debug, Clone, Deserialize)]
191pub struct ListIncoming {
192 pub incoming: Vec<IncomingChannel>,
193}
194
195#[derive(Debug, Clone, Deserialize)]
196pub struct IncomingChannel {
197 pub id: String,
198 pub short_channel_id: String,
199 pub fee_base_msat: String,
200 pub fee_proportional_millionths: u32,
201 pub cltv_expiry_delta: u32,
202 pub incoming_capacity_msat: String,
203}
204
205#[derive(Debug, Clone, Deserialize)]
206pub struct GetChainInfo {
207 pub chain: String,
208 pub headercount: u32,
209 pub blockcount: u32,
210 pub ibd: bool,
211}
212
213#[derive(Debug, Clone, Deserialize)]
215pub struct LogEntry {
216 #[serde(rename = "type")]
217 pub type_: String,
218 pub num_skipped: Option<u64>,
219 pub time: Option<String>,
220 pub node_id: Option<String>,
221 pub source: Option<String>,
222 pub log: Option<String>,
223 pub data: Option<String>,
224}
225
226#[derive(Debug, Clone, Deserialize)]
228pub struct GetLog {
229 pub created_at: String,
230 pub bytes_used: u64,
231 pub bytes_max: u64,
232 pub log: Vec<LogEntry>,
233}
234
235#[derive(Debug, Clone, Deserialize)]
237pub struct Htlc {
238 pub direction: String,
239 pub id: u64,
240 pub amount_msat: MSat,
241 pub expiry: u64,
242 pub payment_hash: String,
243 pub state: String,
244 pub local_trimmed: Option<bool>,
245}
246
247#[derive(Debug, Clone, Deserialize)]
248pub struct Channel {
249 pub state: String,
250 pub scratch_txid: Option<String>,
251 pub owner: Option<String>,
252 pub short_channel_id: Option<String>,
253 pub alias: Option<Aliases>,
254 pub direction: Option<u64>,
255 pub channel_id: String,
256 pub funding_txid: String,
257 pub close_to_addr: Option<String>,
258 pub close_to: Option<String>,
259 pub private: bool,
260 pub to_us_msat: MSat,
261 pub min_to_us_msat: MSat,
262 pub max_to_us_msat: MSat,
263 pub total_msat: MSat,
264 pub dust_limit_msat: MSat,
265 pub max_total_htlc_in_msat: MSat,
266 pub their_reserve_msat: MSat,
267 pub our_reserve_msat: MSat,
268 pub spendable_msat: MSat,
269 pub receivable_msat: MSat,
270 pub minimum_htlc_in_msat: MSat,
271 pub their_to_self_delay: u64,
272 pub our_to_self_delay: u64,
273 pub max_accepted_htlcs: u64,
274 pub status: Vec<String>,
275 pub in_payments_offered: u64,
276 pub in_offered_msat: MSat,
277 pub in_payments_fulfilled: u64,
278 pub in_fulfilled_msat: MSat,
279 pub out_payments_offered: u64,
280 pub out_offered_msat: MSat,
281 pub out_payments_fulfilled: u64,
282 pub out_fulfilled_msat: MSat,
283 pub htlcs: Vec<Htlc>,
284}
285
286#[derive(Debug, Clone, Deserialize)]
287pub struct Aliases {
288 pub local: Option<String>,
289 pub remote: Option<String>,
290}
291
292#[derive(Debug, Clone, Deserialize)]
293pub struct Peer {
294 pub id: String,
295 pub connected: bool,
296 pub netaddr: Option<Vec<String>>,
297 pub features: Option<String>,
298 pub channels: Vec<Channel>,
299 pub log: Option<Vec<LogEntry>>,
300}
301
302#[derive(Debug, Clone, Deserialize)]
303pub struct ListPeers {
304 pub peers: Vec<Peer>,
305}
306
307#[derive(Debug, Clone, Deserialize)]
309pub struct ListFundsOutput {
310 pub txid: String,
311 pub output: u64,
312 pub amount_msat: MSat,
313 pub address: String,
314 pub status: String,
315 pub reserved: bool,
316 pub reserved_to_block: Option<u32>,
317}
318
319#[derive(Debug, Clone, Deserialize)]
320pub struct ListFundsChannel {
321 pub peer_id: String,
322 pub connected: bool,
323 pub short_channel_id: Option<String>,
324 pub our_amount_msat: MSat,
325 pub amount_msat: MSat,
326 pub funding_txid: String,
327 pub funding_output: u64,
328}
329
330#[derive(Debug, Clone, Deserialize)]
332pub struct ListFunds {
333 pub outputs: Vec<ListFundsOutput>,
334 pub channels: Vec<ListFundsChannel>,
335}
336
337#[cfg(test)]
338mod test {
339 use super::*;
340
341 #[test]
342 fn test_msat_parsing() {
343 #[derive(Deserialize)]
344 struct V {
345 value: MSat,
346 }
347
348 struct T {
349 input: &'static str,
350 output: u64,
351 }
352
353 let tests: Vec<T> = vec![
354 T {
355 input: "{\"value\": \"1234msat\"}",
356 output: 1234,
357 },
358 T {
359 input: "{\"value\": 100000000000}",
360 output: 100000000000,
361 },
362 ];
363
364 for t in tests {
365 let v: V = serde_json::from_str(t.input).unwrap();
366 assert_eq!(v.value.0, t.output);
367 }
368 }
369}