1use anyhow::Context;
3use anyhow::{anyhow, Error, Result};
4use bitcoin::hashes::Hash as BitcoinHash;
5use serde::{Deserialize, Serialize};
6use serde::{Deserializer, Serializer};
7use serde_json::Value;
8use std::fmt::{Display, Formatter};
9use std::str::FromStr;
10use std::string::ToString;
11
12pub use bitcoin::hashes::sha256::Hash as Sha256;
13pub use bitcoin::secp256k1::PublicKey;
14
15#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq)]
16#[allow(non_camel_case_types)]
17pub enum ChannelState {
18 OPENINGD = 0,
19 CHANNELD_AWAITING_LOCKIN = 1,
20 CHANNELD_NORMAL = 2,
21 CHANNELD_SHUTTING_DOWN = 3,
22 CLOSINGD_SIGEXCHANGE = 4,
23 CLOSINGD_COMPLETE = 5,
24 AWAITING_UNILATERAL = 6,
25 FUNDING_SPEND_SEEN = 7,
26 ONCHAIN = 8,
27 DUALOPEND_OPEN_INIT = 9,
28 DUALOPEND_AWAITING_LOCKIN = 10,
29 CHANNELD_AWAITING_SPLICE = 11,
30}
31
32#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
33#[allow(non_camel_case_types)]
34pub enum HtlcState {
35 SENT_ADD_HTLC = 0,
36 SENT_ADD_COMMIT = 1,
37 RCVD_ADD_REVOCATION = 2,
38 RCVD_ADD_ACK_COMMIT = 3,
39 SENT_ADD_ACK_REVOCATION = 4,
40 RCVD_ADD_ACK_REVOCATION = 5,
41 RCVD_REMOVE_HTLC = 6,
42 RCVD_REMOVE_COMMIT = 7,
43 SENT_REMOVE_REVOCATION = 8,
44 SENT_REMOVE_ACK_COMMIT = 9,
45 RCVD_REMOVE_ACK_REVOCATION = 10,
46 RCVD_ADD_HTLC = 11,
47 RCVD_ADD_COMMIT = 12,
48 SENT_ADD_REVOCATION = 13,
49 SENT_ADD_ACK_COMMIT = 14,
50 SENT_REMOVE_HTLC = 15,
51 SENT_REMOVE_COMMIT = 16,
52 RCVD_REMOVE_REVOCATION = 17,
53 RCVD_REMOVE_ACK_COMMIT = 18,
54 SENT_REMOVE_ACK_REVOCATION = 19,
55}
56
57#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
58#[allow(non_camel_case_types)]
59pub enum ChannelTypeName {
60 #[serde(rename = "static_remotekey/even")]
61 STATIC_REMOTEKEY_EVEN = 0,
62 #[serde(rename = "anchor_outputs/even")]
63 ANCHOR_OUTPUTS_EVEN = 1,
64 #[serde(rename = "anchors_zero_fee_htlc_tx/even")]
65 ANCHORS_ZERO_FEE_HTLC_TX_EVEN = 2,
66 #[serde(rename = "scid_alias/even")]
67 SCID_ALIAS_EVEN = 3,
68 #[serde(rename = "zeroconf/even")]
69 ZEROCONF_EVEN = 4,
70 #[serde(rename = "anchors/even")]
71 ANCHORS_EVEN = 5,
72}
73
74#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
75#[allow(non_camel_case_types)]
76#[serde(rename_all = "lowercase")]
77pub enum ChannelStateChangeCause {
78 UNKNOWN,
79 LOCAL,
80 USER,
81 REMOTE,
82 PROTOCOL,
83 ONCHAIN,
84}
85
86#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
87#[allow(non_camel_case_types)]
88pub enum AutocleanSubsystem {
89 #[serde(rename = "succeededforwards")]
90 SUCCEEDEDFORWARDS = 0,
91 #[serde(rename = "failedforwards")]
92 FAILEDFORWARDS = 1,
93 #[serde(rename = "succeededpays")]
94 SUCCEEDEDPAYS = 2,
95 #[serde(rename = "failedpays")]
96 FAILEDPAYS = 3,
97 #[serde(rename = "paidinvoices")]
98 PAIDINVOICES = 4,
99 #[serde(rename = "expiredinvoices")]
100 EXPIREDINVOICES = 5,
101}
102
103impl TryFrom<i32> for AutocleanSubsystem {
104 type Error = crate::Error;
105
106 fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
107 match value {
108 0 => Ok(AutocleanSubsystem::SUCCEEDEDFORWARDS),
109 1 => Ok(AutocleanSubsystem::FAILEDFORWARDS),
110 2 => Ok(AutocleanSubsystem::SUCCEEDEDPAYS),
111 3 => Ok(AutocleanSubsystem::FAILEDPAYS),
112 4 => Ok(AutocleanSubsystem::PAIDINVOICES),
113 5 => Ok(AutocleanSubsystem::EXPIREDINVOICES),
114 _ => Err(anyhow!("Invalid AutocleanSubsystem {}", value)),
115 }
116 }
117}
118
119#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
120#[allow(non_camel_case_types)]
121pub enum PluginSubcommand {
122 #[serde(rename = "start")]
123 START = 0,
124 #[serde(rename = "stop")]
125 STOP = 1,
126 #[serde(rename = "rescan")]
127 RESCAN = 2,
128 #[serde(rename = "startdir")]
129 STARTDIR = 3,
130 #[serde(rename = "list")]
131 LIST = 4,
132}
133
134impl TryFrom<i32> for PluginSubcommand {
135 type Error = crate::Error;
136
137 fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
138 match value {
139 0 => Ok(PluginSubcommand::START),
140 1 => Ok(PluginSubcommand::STOP),
141 2 => Ok(PluginSubcommand::RESCAN),
142 3 => Ok(PluginSubcommand::STARTDIR),
143 4 => Ok(PluginSubcommand::LIST),
144 _ => Err(anyhow!("Invalid PluginSubcommand mapping!")),
145 }
146 }
147}
148
149#[derive(Debug, Copy, Clone, PartialEq)]
153pub enum AmountOrAny {
154 Amount(Amount),
155 Any,
156}
157
158#[derive(Debug, Copy, Clone, PartialEq)]
161pub enum AmountOrAll {
162 Amount(Amount),
163 All,
164}
165
166#[derive(Copy, Clone, Debug, PartialEq)]
167pub struct Amount {
168 msat: u64,
169}
170
171impl Amount {
172 pub fn from_msat(msat: u64) -> Amount {
173 Amount { msat }
174 }
175
176 pub fn from_sat(sat: u64) -> Amount {
177 Amount { msat: 1_000 * sat }
178 }
179
180 pub fn from_btc(btc: u64) -> Amount {
181 Amount {
182 msat: 100_000_000_000 * btc,
183 }
184 }
185
186 pub fn msat(&self) -> u64 {
187 self.msat
188 }
189}
190
191impl std::ops::Add for Amount {
192 type Output = Amount;
193
194 fn add(self, rhs: Self) -> Self::Output {
195 Amount {
196 msat: self.msat + rhs.msat,
197 }
198 }
199}
200
201impl std::ops::Sub for Amount {
202 type Output = Amount;
203
204 fn sub(self, rhs: Self) -> Self::Output {
205 Amount {
206 msat: self.msat - rhs.msat,
207 }
208 }
209}
210
211#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
212pub struct ShortChannelId(u64);
213
214impl Serialize for ShortChannelId {
215 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
216 where
217 S: Serializer,
218 {
219 serializer.serialize_str(&self.to_string())
220 }
221}
222
223impl<'de> Deserialize<'de> for ShortChannelId {
224 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
225 where
226 D: Deserializer<'de>,
227 {
228 use serde::de::Error;
229 let s: String = Deserialize::deserialize(deserializer)?;
230 Ok(Self::from_str(&s).map_err(|e| Error::custom(e.to_string()))?)
231 }
232}
233
234impl FromStr for ShortChannelId {
235 type Err = crate::Error;
236 fn from_str(s: &str) -> Result<Self, Self::Err> {
237 let parts: Result<Vec<u64>, _> = s.split('x').map(|p| p.parse()).collect();
238 let parts = parts.with_context(|| format!("Malformed short_channel_id: {}", s))?;
239 if parts.len() != 3 {
240 return Err(anyhow!(
241 "Malformed short_channel_id: element count mismatch"
242 ));
243 }
244
245 Ok(ShortChannelId(
246 (parts[0] << 40) | (parts[1] << 16) | (parts[2] << 0),
247 ))
248 }
249}
250impl Display for ShortChannelId {
251 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
252 write!(f, "{}x{}x{}", self.block(), self.txindex(), self.outnum())
253 }
254}
255impl ShortChannelId {
256 pub fn block(&self) -> u32 {
257 (self.0 >> 40) as u32 & 0xFFFFFF
258 }
259 pub fn txindex(&self) -> u32 {
260 (self.0 >> 16) as u32 & 0xFFFFFF
261 }
262 pub fn outnum(&self) -> u16 {
263 self.0 as u16 & 0xFFFF
264 }
265 pub fn to_u64(&self) -> u64 {
266 self.0
267 }
268}
269
270#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
271pub struct ShortChannelIdDir {
272 pub short_channel_id: ShortChannelId,
273 pub direction: u32,
274}
275impl Serialize for ShortChannelIdDir {
276 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
277 where
278 S: Serializer,
279 {
280 serializer.serialize_str(&self.to_string())
281 }
282}
283
284impl<'de> Deserialize<'de> for ShortChannelIdDir {
285 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
286 where
287 D: Deserializer<'de>,
288 {
289 use serde::de::Error;
290 let s: String = Deserialize::deserialize(deserializer)?;
291 Ok(Self::from_str(&s).map_err(|e| Error::custom(e.to_string()))?)
292 }
293}
294impl FromStr for ShortChannelIdDir {
295 type Err = crate::Error;
296 fn from_str(s: &str) -> Result<Self, Self::Err> {
297 let parts: Result<Vec<String>, _> = s.split('/').map(|p| p.parse()).collect();
298 let parts = parts.with_context(|| format!("Malformed short_channel_id_dir: {}", s))?;
299 if parts.len() != 2 {
300 return Err(anyhow!(
301 "Malformed short_channel_id_dir: element count mismatch"
302 ));
303 }
304
305 Ok(ShortChannelIdDir {
306 short_channel_id: ShortChannelId::from_str(&parts[0])?,
307 direction: parts[1].parse::<u32>()?,
308 })
309 }
310}
311impl Display for ShortChannelIdDir {
312 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
313 write!(
314 f,
315 "{}x{}x{}/{}",
316 self.short_channel_id.block(),
317 self.short_channel_id.txindex(),
318 self.short_channel_id.outnum(),
319 self.direction
320 )
321 }
322}
323
324#[derive(Clone, Copy, Debug)]
325pub struct Secret([u8; 32]);
326
327impl TryFrom<Vec<u8>> for Secret {
328 type Error = crate::Error;
329 fn try_from(v: Vec<u8>) -> Result<Self, crate::Error> {
330 if v.len() != 32 {
331 Err(anyhow!("Unexpected secret length: {}", hex::encode(v)))
332 } else {
333 Ok(Secret(v.try_into().unwrap()))
334 }
335 }
336}
337
338impl Serialize for Secret {
339 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
340 where
341 S: Serializer,
342 {
343 serializer.serialize_str(&hex::encode(&self.0))
344 }
345}
346
347impl<'de> Deserialize<'de> for Secret {
348 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
349 where
350 D: Deserializer<'de>,
351 {
352 use serde::de::Error;
353 let s: String = Deserialize::deserialize(deserializer)?;
354 let h = hex::decode(s).map_err(|_| Error::custom("not a valid hex string"))?;
355 Ok(Secret(h.try_into().map_err(|_| {
356 Error::custom("not a valid hex-encoded hash")
357 })?))
358 }
359}
360
361impl Secret {
362 pub fn to_vec(self) -> Vec<u8> {
363 self.0.to_vec()
364 }
365}
366
367impl From<Secret> for [u8; 32] {
368 fn from(s: Secret) -> [u8; 32] {
369 s.0
370 }
371}
372
373#[derive(Clone, Copy, Debug, PartialEq)]
374pub struct Outpoint {
375 pub txid: Sha256,
376 pub outnum: u32,
377}
378
379impl Serialize for Outpoint {
380 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
381 where
382 S: Serializer,
383 {
384 serializer.serialize_str(&format!("{}:{}", hex::encode(&self.txid), self.outnum))
385 }
386}
387
388impl<'de> Deserialize<'de> for Outpoint {
389 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
390 where
391 D: Deserializer<'de>,
392 {
393 use serde::de::Error;
394 let s: String = Deserialize::deserialize(deserializer)?;
395
396 let splits: Vec<&str> = s.split(':').collect();
397 if splits.len() != 2 {
398 return Err(Error::custom("not a valid txid:output tuple"));
399 }
400
401 let txid_bytes =
402 hex::decode(splits[0]).map_err(|_| Error::custom("not a valid hex encoded txid"))?;
403
404 let txid = Sha256::from_slice(&txid_bytes)
405 .map_err(|e| Error::custom(format!("Invalid TxId: {}", e)))?;
406
407 let outnum: u32 = splits[1]
408 .parse()
409 .map_err(|e| Error::custom(format!("{} is not a valid number: {}", s, e)))?;
410
411 Ok(Outpoint { txid, outnum })
412 }
413}
414
415#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq)]
416#[serde(rename_all = "lowercase")]
417pub enum ChannelSide {
418 LOCAL,
419 REMOTE,
420}
421
422impl TryFrom<i32> for ChannelSide {
423 type Error = crate::Error;
424
425 fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
426 match value {
427 0 => Ok(ChannelSide::LOCAL),
428 1 => Ok(ChannelSide::REMOTE),
429 _ => Err(anyhow!(
430 "Invalid ChannelSide mapping, only 0 or 1 are allowed"
431 )),
432 }
433 }
434}
435
436impl TryFrom<i32> for ChannelState {
437 type Error = crate::Error;
438
439 fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
440 match value {
441 0 => Ok(ChannelState::OPENINGD),
442 1 => Ok(ChannelState::CHANNELD_AWAITING_LOCKIN),
443 2 => Ok(ChannelState::CHANNELD_NORMAL),
444 3 => Ok(ChannelState::CHANNELD_SHUTTING_DOWN),
445 4 => Ok(ChannelState::CLOSINGD_SIGEXCHANGE),
446 5 => Ok(ChannelState::CLOSINGD_COMPLETE),
447 6 => Ok(ChannelState::AWAITING_UNILATERAL),
448 7 => Ok(ChannelState::FUNDING_SPEND_SEEN),
449 8 => Ok(ChannelState::ONCHAIN),
450 9 => Ok(ChannelState::DUALOPEND_OPEN_INIT),
451 10 => Ok(ChannelState::DUALOPEND_AWAITING_LOCKIN),
452 11 => Ok(ChannelState::CHANNELD_AWAITING_SPLICE),
453 _ => Err(anyhow!("Invalid channel state {}", value)),
454 }
455 }
456}
457
458impl From<i32> for ChannelTypeName {
459 fn from(value: i32) -> Self {
460 match value {
461 0 => ChannelTypeName::STATIC_REMOTEKEY_EVEN,
462 1 => ChannelTypeName::ANCHOR_OUTPUTS_EVEN,
463 2 => ChannelTypeName::ANCHORS_ZERO_FEE_HTLC_TX_EVEN,
464 3 => ChannelTypeName::SCID_ALIAS_EVEN,
465 4 => ChannelTypeName::ZEROCONF_EVEN,
466 5 => ChannelTypeName::ANCHORS_EVEN,
467 o => panic!("Unmapped ChannelTypeName {}", o),
468 }
469 }
470}
471
472impl From<ChannelTypeName> for i32 {
473 fn from(value: ChannelTypeName) -> Self {
474 match value {
475 ChannelTypeName::STATIC_REMOTEKEY_EVEN => 0,
476 ChannelTypeName::ANCHOR_OUTPUTS_EVEN => 1,
477 ChannelTypeName::ANCHORS_ZERO_FEE_HTLC_TX_EVEN => 2,
478 ChannelTypeName::SCID_ALIAS_EVEN => 3,
479 ChannelTypeName::ZEROCONF_EVEN => 4,
480 ChannelTypeName::ANCHORS_EVEN => 5,
481 }
482 }
483}
484
485impl From<i32> for HtlcState {
486 fn from(value: i32) -> Self {
487 match value {
488 0 => HtlcState::SENT_ADD_HTLC,
489 1 => HtlcState::SENT_ADD_COMMIT,
490 2 => HtlcState::RCVD_ADD_REVOCATION,
491 3 => HtlcState::RCVD_ADD_ACK_COMMIT,
492 4 => HtlcState::SENT_ADD_ACK_REVOCATION,
493 5 => HtlcState::RCVD_ADD_ACK_REVOCATION,
494 6 => HtlcState::RCVD_REMOVE_HTLC,
495 7 => HtlcState::RCVD_REMOVE_COMMIT,
496 8 => HtlcState::SENT_REMOVE_REVOCATION,
497 9 => HtlcState::SENT_REMOVE_ACK_COMMIT,
498 10 => HtlcState::RCVD_REMOVE_ACK_REVOCATION,
499 11 => HtlcState::RCVD_ADD_HTLC,
500 12 => HtlcState::RCVD_ADD_COMMIT,
501 13 => HtlcState::SENT_ADD_REVOCATION,
502 14 => HtlcState::SENT_ADD_ACK_COMMIT,
503 15 => HtlcState::SENT_REMOVE_HTLC,
504 16 => HtlcState::SENT_REMOVE_COMMIT,
505 17 => HtlcState::RCVD_REMOVE_REVOCATION,
506 18 => HtlcState::RCVD_REMOVE_ACK_COMMIT,
507 19 => HtlcState::SENT_REMOVE_ACK_REVOCATION,
508
509 n => panic!("Unmapped HtlcState variant: {}", n),
510 }
511 }
512}
513
514impl<'de> Deserialize<'de> for Amount {
515 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
516 where
517 D: Deserializer<'de>,
518 {
519 use serde::de::Error;
520
521 let any: serde_json::Value = Deserialize::deserialize(deserializer)?;
522
523 let ires: Option<u64> = any.as_u64();
528 let sres: Option<&str> = any.as_str();
530
531 match (ires, sres) {
532 (Some(i), _) => {
533 Ok(Amount::from_msat(i))
535 }
536 (_, Some(s)) => s
537 .try_into()
538 .map_err(|_e| Error::custom("could not parse amount")),
539 (None, _) => {
540 Err(Error::custom("could not parse amount"))
543 }
544 }
545 }
546}
547
548impl Serialize for Amount {
549 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
550 where
551 S: Serializer,
552 {
553 serializer.serialize_str(&format!("{}msat", self.msat))
554 }
555}
556
557impl Serialize for AmountOrAll {
558 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
559 where
560 S: Serializer,
561 {
562 match self {
563 AmountOrAll::Amount(a) => serializer.serialize_str(&format!("{}msat", a.msat)),
564 AmountOrAll::All => serializer.serialize_str("all"),
565 }
566 }
567}
568
569impl Serialize for AmountOrAny {
570 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
571 where
572 S: Serializer,
573 {
574 match self {
575 AmountOrAny::Amount(a) => serializer.serialize_str(&format!("{}msat", a.msat)),
576 AmountOrAny::Any => serializer.serialize_str("any"),
577 }
578 }
579}
580
581impl<'de> Deserialize<'de> for AmountOrAny {
582 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
583 where
584 D: Deserializer<'de>,
585 {
586 let s: String = Deserialize::deserialize(deserializer)?;
587 Ok(match s.to_lowercase().as_ref() {
588 "any" => AmountOrAny::Any,
589 v => AmountOrAny::Amount(
590 v.try_into()
591 .map_err(|_e| serde::de::Error::custom("could not parse amount"))?,
592 ),
593 })
594 }
595}
596
597impl<'de> Deserialize<'de> for AmountOrAll {
598 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
599 where
600 D: Deserializer<'de>,
601 {
602 let s: String = Deserialize::deserialize(deserializer)?;
603 Ok(match s.to_lowercase().as_ref() {
604 "all" => AmountOrAll::All,
605 v => AmountOrAll::Amount(
606 v.try_into()
607 .map_err(|_e| serde::de::Error::custom("could not parse amount"))?,
608 ),
609 })
610 }
611}
612
613impl TryFrom<&str> for Amount {
614 type Error = Error;
615 fn try_from(s: &str) -> Result<Amount> {
616 let number: u64 = s
617 .chars()
618 .map(|c| c.to_digit(10))
619 .take_while(|opt| opt.is_some())
620 .fold(0, |acc, digit| acc * 10 + (digit.unwrap() as u64));
621
622 let s = s.to_lowercase();
623 if s.ends_with("msat") {
624 Ok(Amount::from_msat(number))
625 } else if s.ends_with("sat") {
626 Ok(Amount::from_sat(number))
627 } else if s.ends_with("btc") {
628 Ok(Amount::from_btc(number))
629 } else {
630 Err(anyhow!("Unable to parse amount from string: {}", s))
631 }
632 }
633}
634
635impl From<Amount> for String {
636 fn from(a: Amount) -> String {
637 if a.msat % 1000 == 0 {
640 format!("{}sat", a.msat / 1000)
641 } else {
642 format!("{}msat", a.msat)
643 }
644 }
645}
646
647#[derive(Copy, Clone, Debug, PartialEq)]
648pub enum Feerate {
649 Slow,
650 Normal,
651 Urgent,
652 PerKb(u32),
653 PerKw(u32),
654}
655
656impl TryFrom<&str> for Feerate {
657 type Error = Error;
658 fn try_from(s: &str) -> Result<Feerate> {
659 let number: u32 = s
660 .chars()
661 .map(|c| c.to_digit(10))
662 .take_while(|opt| opt.is_some())
663 .fold(0, |acc, digit| acc * 10 + (digit.unwrap() as u32));
664
665 let s = s.to_lowercase();
666 if s.ends_with("perkw") {
667 Ok(Feerate::PerKw(number))
668 } else if s.ends_with("perkb") {
669 Ok(Feerate::PerKb(number))
670 } else if s == "slow" {
671 Ok(Feerate::Slow)
672 } else if s == "normal" {
673 Ok(Feerate::Normal)
674 } else if s == "urgent" {
675 Ok(Feerate::Urgent)
676 } else {
677 Err(anyhow!("Unable to parse feerate from string: {}", s))
678 }
679 }
680}
681
682impl From<&Feerate> for String {
683 fn from(f: &Feerate) -> String {
684 match f {
685 Feerate::Slow => "slow".to_string(),
686 Feerate::Normal => "normal".to_string(),
687 Feerate::Urgent => "urgent".to_string(),
688 Feerate::PerKb(v) => format!("{}perkb", v),
689 Feerate::PerKw(v) => format!("{}perkw", v),
690 }
691 }
692}
693
694impl<'de> Deserialize<'de> for Feerate {
695 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
696 where
697 D: Deserializer<'de>,
698 {
699 let s: String = Deserialize::deserialize(deserializer)?;
700 let res: Feerate = s
701 .as_str()
702 .try_into()
703 .map_err(|e| serde::de::Error::custom(format!("{}", e)))?;
704 Ok(res)
705 }
706}
707
708impl Serialize for Feerate {
709 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
710 where
711 S: Serializer,
712 {
713 let s: String = self.into();
714 serializer.serialize_str(&s)
715 }
716}
717
718#[cfg(test)]
719mod test {
720 use crate::model::responses::FundchannelResponse;
721
722 use super::*;
723
724 #[test]
725 fn test_amount_serde() {
726 #[derive(Serialize, PartialEq, Debug, Deserialize)]
727 struct T {
728 amount: Amount,
729 }
730
731 let tests = vec![
732 ("{\"amount\": \"10msat\"}", Amount { msat: 10 }, "10msat"),
733 ("{\"amount\": \"42sat\"}", Amount { msat: 42_000 }, "42sat"),
734 (
735 "{\"amount\": \"31337btc\"}",
736 Amount {
737 msat: 3_133_700_000_000_000,
738 },
739 "3133700000000sat",
740 ),
741 ];
742
743 for (req, res, s) in tests.into_iter() {
744 println!("{:?} {:?}", req, res);
745 let parsed: T = serde_json::from_str(req).unwrap();
746 assert_eq!(res, parsed.amount);
747
748 let serialized: String = parsed.amount.into();
749 assert_eq!(s, serialized);
750 }
751 }
752
753 #[test]
754 fn test_amount_all_any() {
755 let t = r#"{"any": "any", "all": "all", "not_any": "42msat", "not_all": "31337msat"}"#;
756
757 #[derive(Serialize, Deserialize, Debug, PartialEq)]
758 struct T {
759 all: AmountOrAll,
760 not_all: AmountOrAll,
761 any: AmountOrAny,
762 not_any: AmountOrAny,
763 }
764
765 let parsed: T = serde_json::from_str(t).unwrap();
766
767 let expected = T {
768 all: AmountOrAll::All,
769 any: AmountOrAny::Any,
770 not_all: AmountOrAll::Amount(Amount { msat: 31337 }),
771 not_any: AmountOrAny::Amount(Amount { msat: 42 }),
772 };
773 assert_eq!(expected, parsed);
774
775 let serialized: String = serde_json::to_string(&parsed).unwrap();
776 assert_eq!(
777 serialized,
778 r#"{"all":"all","not_all":"31337msat","any":"any","not_any":"42msat"}"#
779 );
780 }
781
782 #[test]
783 fn test_parse_feerate() {
784 let tests = vec![
785 ("slow", Feerate::Slow),
786 ("normal", Feerate::Normal),
787 ("urgent", Feerate::Urgent),
788 ("12345perkb", Feerate::PerKb(12345)),
789 ("54321perkw", Feerate::PerKw(54321)),
790 ];
791
792 for (input, output) in tests.into_iter() {
793 let parsed: Feerate = input.try_into().unwrap();
794 assert_eq!(parsed, output);
795 let serialized: String = (&parsed).into();
796 assert_eq!(serialized, input);
797 }
798 }
799
800 #[test]
801 fn test_parse_output_desc() {
802 let a = r#"{"address":"1234msat"}"#;
803 let od = serde_json::from_str(a).unwrap();
804
805 assert_eq!(
806 OutputDesc {
807 address: "address".to_string(),
808 amount: Amount { msat: 1234 }
809 },
810 od
811 );
812 let serialized: String = serde_json::to_string(&od).unwrap();
813 assert_eq!(a, serialized);
814 }
815
816 #[test]
817 fn tlvstream() {
818 let stream = TlvStream {
819 entries: vec![
820 TlvEntry {
821 typ: 31337,
822 value: vec![1, 2, 3, 4, 5],
823 },
824 TlvEntry {
825 typ: 42,
826 value: vec![],
827 },
828 ],
829 };
830
831 let res = serde_json::to_string(&stream).unwrap();
832 assert_eq!(res, "{\"31337\":\"0102030405\",\"42\":\"\"}");
833 }
834
835 #[test]
836 fn test_fundchannel() {
837 let r = serde_json::json!({
838 "tx": "0000000000000000000000000000000000000000000000000000000000000000",
839 "txid": "0000000000000000000000000000000000000000000000000000000000000000",
840 "outnum": 0,
841 "channel_id": "0000000000000000000000000000000000000000000000000000000000000000",
842 "channel_type": {
843 "bits": [1, 3, 5],
844 "names": [
845 "static_remotekey/even",
846 "anchor_outputs/even",
847 "anchors_zero_fee_htlc_tx/even",
848 "scid_alias/even",
849 "zeroconf/even"
850 ]
851 },
852 "close_to": "bc1qd23gerv2mn0qdecrmulsjsmkv8lz6t6m0770tg",
853 "mindepth": 1,
854 });
855
856 let p: FundchannelResponse = serde_json::from_value(r).unwrap();
857 assert_eq!(p.channel_type.unwrap().bits, vec![1, 3, 5]);
858 }
859}
860
861#[derive(Clone, Debug, PartialEq)]
862pub struct OutputDesc {
863 pub address: String,
864 pub amount: Amount,
865}
866
867impl<'de> Deserialize<'de> for OutputDesc {
868 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
869 where
870 D: Deserializer<'de>,
871 {
872 let map: std::collections::HashMap<String, Amount> =
873 Deserialize::deserialize(deserializer)?;
874
875 let (address, amount) = map.iter().next().unwrap();
876
877 Ok(OutputDesc {
878 address: address.to_string(),
879 amount: *amount,
880 })
881 }
882}
883
884impl Serialize for OutputDesc {
885 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
886 where
887 S: Serializer,
888 {
889 use serde::ser::SerializeMap;
890 let mut map = serializer.serialize_map(Some(1))?;
891 map.serialize_key(&self.address)?;
892 map.serialize_value(&self.amount)?;
893 map.end()
894 }
895}
896
897#[derive(Clone, Debug, Serialize, Deserialize)]
898pub struct Routehop {
899 pub id: PublicKey,
900 pub scid: ShortChannelId,
901 pub feebase: Amount,
902 pub feeprop: u32,
903 pub expirydelta: u16,
904}
905
906#[derive(Clone, Debug)]
907pub struct Routehint {
908 pub hops: Vec<Routehop>,
909}
910
911#[derive(Clone, Debug)]
912pub struct RoutehintList {
913 pub hints: Vec<Routehint>,
914}
915
916use serde::ser::SerializeSeq;
917
918impl Serialize for Routehint {
919 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
920 where
921 S: Serializer,
922 {
923 let mut seq = serializer.serialize_seq(Some(self.hops.len()))?;
924 for e in self.hops.iter() {
925 seq.serialize_element(e)?;
926 }
927 seq.end()
928 }
929}
930
931impl Serialize for RoutehintList {
932 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
933 where
934 S: Serializer,
935 {
936 let mut seq = serializer.serialize_seq(Some(self.hints.len()))?;
937 for e in self.hints.iter() {
938 seq.serialize_element(e)?;
939 }
940 seq.end()
941 }
942}
943
944impl<'de> Deserialize<'de> for RoutehintList {
945 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
946 where
947 D: Deserializer<'de>,
948 {
949 let hints: Vec<Routehint> = Vec::deserialize(deserializer)?;
950
951 Ok(RoutehintList { hints })
952 }
953}
954
955impl<'de> Deserialize<'de> for Routehint {
956 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
957 where
958 D: Deserializer<'de>,
959 {
960 let hops: Vec<Routehop> = Vec::deserialize(deserializer)?;
961
962 Ok(Routehint { hops })
963 }
964}
965
966#[derive(Clone, Debug, Serialize, Deserialize)]
967pub struct DecodeRoutehop {
968 pub pubkey: PublicKey,
969 pub short_channel_id: ShortChannelId,
970 pub fee_base_msat: Amount,
971 pub fee_proportional_millionths: u32,
972 pub cltv_expiry_delta: u16,
973}
974
975#[derive(Clone, Debug)]
976pub struct DecodeRoutehint {
977 pub hops: Vec<DecodeRoutehop>,
978}
979
980#[derive(Clone, Debug)]
981pub struct DecodeRoutehintList {
982 pub hints: Vec<DecodeRoutehint>,
983}
984
985impl Serialize for DecodeRoutehint {
986 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
987 where
988 S: Serializer,
989 {
990 let mut seq = serializer.serialize_seq(Some(self.hops.len()))?;
991 for e in self.hops.iter() {
992 seq.serialize_element(e)?;
993 }
994 seq.end()
995 }
996}
997
998impl Serialize for DecodeRoutehintList {
999 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1000 where
1001 S: Serializer,
1002 {
1003 let mut seq = serializer.serialize_seq(Some(self.hints.len()))?;
1004 for e in self.hints.iter() {
1005 seq.serialize_element(e)?;
1006 }
1007 seq.end()
1008 }
1009}
1010
1011impl<'de> Deserialize<'de> for DecodeRoutehintList {
1012 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1013 where
1014 D: Deserializer<'de>,
1015 {
1016 let hints: Vec<DecodeRoutehint> = Vec::deserialize(deserializer)?;
1017
1018 Ok(DecodeRoutehintList { hints })
1019 }
1020}
1021
1022impl<'de> Deserialize<'de> for DecodeRoutehint {
1023 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1024 where
1025 D: Deserializer<'de>,
1026 {
1027 let hops: Vec<DecodeRoutehop> = Vec::deserialize(deserializer)?;
1028
1029 Ok(DecodeRoutehint { hops })
1030 }
1031}
1032
1033#[derive(Clone, Serialize, Deserialize, Debug)]
1036pub struct RpcError {
1037 pub code: Option<i32>,
1038 pub message: String,
1039 pub data: Option<Value>,
1040}
1041
1042impl Display for RpcError {
1043 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1044 if let Some(code) = self.code {
1045 write!(f, "Error code {}: {}", code, self.message)
1046 } else {
1047 write!(f, "Error: {}", self.message)
1048 }
1049 }
1050}
1051
1052impl std::error::Error for RpcError {}
1053
1054#[derive(Clone, Debug)]
1055pub struct TlvEntry {
1056 pub typ: u64,
1057 pub value: Vec<u8>,
1058}
1059
1060#[derive(Clone, Debug)]
1061pub struct TlvStream {
1062 pub entries: Vec<TlvEntry>,
1063}
1064
1065impl<'de> Deserialize<'de> for TlvStream {
1066 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1067 where
1068 D: Deserializer<'de>,
1069 {
1070 let map: std::collections::HashMap<u64, String> = Deserialize::deserialize(deserializer)?;
1071
1072 let entries = map
1073 .iter()
1074 .map(|(k, v)| TlvEntry {
1075 typ: *k,
1076 value: hex::decode(v).unwrap(),
1077 })
1078 .collect();
1079
1080 Ok(TlvStream { entries })
1081 }
1082}
1083
1084impl Serialize for TlvStream {
1085 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1086 where
1087 S: Serializer,
1088 {
1089 use serde::ser::SerializeMap;
1090
1091 let mut map = serializer.serialize_map(Some(self.entries.len()))?;
1092 for e in &self.entries {
1093 map.serialize_key(&e.typ)?;
1094 map.serialize_value(&hex::encode(&e.value))?;
1095 }
1096 map.end()
1097 }
1098}