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