1use core::str::FromStr;
2use std::fmt::{Display, Formatter};
3
4use anyhow::{anyhow, Context, Result};
5use bitcoin::address::Address;
6pub use bitcoin::address::{NetworkChecked, NetworkUnchecked, NetworkValidation};
7pub use bitcoin::network::Network;
8
9use serde::de::Error as SeError;
10use serde::ser::Error as DeError;
11use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
12
13use time::format_description::FormatItem;
14use time::macros::{format_description, offset};
15use time::{OffsetDateTime, PrimitiveDateTime};
16
17use crate::secp256k1::PublicKey as _PublicKey;
18
19#[derive(Serialize, Clone, Debug)]
20#[serde(transparent)]
21pub struct OnchainAddress {
22 pub address: Address,
23}
24
25impl<'de> Deserialize<'de> for OnchainAddress {
26 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
27 where
28 D: Deserializer<'de>,
29 {
30 let address_unchecked = Address::<NetworkUnchecked>::deserialize(deserializer)?;
31 Ok(OnchainAddress {
32 address: address_unchecked.assume_checked(),
33 })
34 }
35}
36
37pub trait NetworkCheckable {
38 fn require_network(&self, network: &bitcoin::Network) -> Result<()>;
39}
40
41impl NetworkCheckable for OnchainAddress {
42 fn require_network(&self, network: &bitcoin::Network) -> Result<()> {
43 if network != self.address.network() {
44 Err(anyhow!(
45 "Network mismatch: Expected {} but got {}",
46 network,
47 self.address.network()
48 ))
49 } else {
50 Ok(())
51 }
52 }
53}
54
55impl NetworkCheckable for Option<OnchainAddress> {
56 fn require_network(&self, network: &bitcoin::Network) -> Result<()> {
57 match self {
58 Some(x) => x.require_network(network),
59 None => Ok(()),
60 }
61 }
62}
63
64impl FromStr for OnchainAddress {
65 type Err = anyhow::Error;
66
67 fn from_str(s: &str) -> Result<Self, Self::Err> {
68 let address = Address::<NetworkUnchecked>::from_str(s)?;
69 Ok(Self {
70 address: address.assume_checked(),
71 })
72 }
73}
74
75impl Display for OnchainAddress {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(f, "{}", self.address)
78 }
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub struct PublicKey(_PublicKey);
83
84impl std::hash::Hash for PublicKey {
85 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
86 let x = self.inner().serialize();
87 x.hash(state);
88 }
89}
90
91impl From<_PublicKey> for PublicKey {
92 fn from(public_key: _PublicKey) -> Self {
93 Self(public_key)
94 }
95}
96
97impl Serialize for PublicKey {
98 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
99 where
100 S: Serializer,
101 {
102 let s = hex::encode(self.0.serialize());
103 serializer.serialize_str(&s)
104 }
105}
106
107impl<'de> Deserialize<'de> for PublicKey {
108 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
109 where
110 D: Deserializer<'de>,
111 {
112 struct PublicKeyVisitor;
113
114 impl Visitor<'_> for PublicKeyVisitor {
115 type Value = PublicKey;
116
117 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
118 write!(formatter, "A compressed public-key that is hex-encoded")
119 }
120
121 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
122 where
123 E: serde::de::Error,
124 {
125 let data =
126 hex::decode(v).map_err(|_| serde::de::Error::custom("Expected valid hex"))?;
127 let pubkey = _PublicKey::from_slice(&data).map_err(|err| {
128 serde::de::Error::custom(format!("Invalid public-key: {}", err))
129 })?;
130 Ok(pubkey.into())
131 }
132 }
133
134 let visitor = PublicKeyVisitor;
135 deserializer.deserialize_str(visitor)
136 }
137}
138
139impl PublicKey {
140 pub fn from_hex(hex: &str) -> Result<Self> {
141 let data = hex::decode(hex).context("Invalid hex")?;
142 let publickey =
143 _PublicKey::from_slice(&data).map_err(|m| anyhow!("Error parsing PublicKey: {}", m))?;
144 Ok(PublicKey(publickey))
145 }
146
147 pub fn to_hex(&self) -> String {
148 let data = self.0.serialize();
149 hex::encode(data)
150 }
151
152 pub fn inner(self) -> _PublicKey {
153 self.0
154 }
155}
156
157#[derive(Debug, Clone, PartialEq, PartialOrd, Copy)]
172pub struct IsoDatetime {
173 pub datetime: PrimitiveDateTime,
174}
175
176const DATETIME_FORMAT: &[FormatItem] =
177 format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:3]Z");
178
179impl IsoDatetime {
180 pub fn now() -> Self {
181 Self::from_offset_date_time(time::OffsetDateTime::now_utc())
182 }
183
184 pub fn from_offset_date_time(datetime: OffsetDateTime) -> Self {
185 let offset = time::UtcOffset::from_whole_seconds(0).unwrap();
186 let datetime_utc = datetime.to_offset(offset);
187 let primitive = PrimitiveDateTime::new(datetime_utc.date(), datetime.time());
188 Self {
189 datetime: primitive,
190 }
191 }
192
193 pub fn from_unix_timestamp(value: i64) -> Result<Self> {
194 let offset =
195 OffsetDateTime::from_unix_timestamp(value).context("Failed to construct datetime")?;
196 Ok(Self::from_offset_date_time(offset))
197 }
198
199 pub fn unix_timestamp(&self) -> i64 {
200 self.datetime.assume_offset(offset!(UTC)).unix_timestamp()
201 }
202
203 pub fn from_primitive_date_time(datetime: PrimitiveDateTime) -> Self {
204 Self { datetime }
205 }
206
207 pub fn datetime(&self) -> OffsetDateTime {
208 self.datetime.assume_utc()
209 }
210}
211
212impl Serialize for IsoDatetime {
213 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
214 where
215 S: serde::Serializer,
216 {
217 let datetime_str = self
218 .datetime
219 .format(&DATETIME_FORMAT)
220 .map_err(|err| S::Error::custom(format!("Failed to format datetime {:?}", err)))?;
221
222 serializer.serialize_str(&datetime_str)
223 }
224}
225
226impl<'de> Deserialize<'de> for IsoDatetime {
227 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
228 where
229 D: serde::Deserializer<'de>,
230 {
231 let str_repr = <String as serde::de::Deserialize>::deserialize(deserializer)?;
232 time::PrimitiveDateTime::parse(&str_repr, DATETIME_FORMAT)
233 .map_err(|err| D::Error::custom(format!("Failed to parse Datetime. {:?}", err)))
234 .map(Self::from_primitive_date_time)
235 }
236}
237
238#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Copy, Default)]
239pub struct SatAmount(u64);
240#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Copy, Default)]
241pub struct MsatAmount(u64);
242
243impl std::fmt::Display for SatAmount {
244 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
245 write!(fmt, "{} sat", self.0)
246 }
247}
248
249impl std::fmt::Display for MsatAmount {
250 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
251 write!(fmt, "{} msat", self.0)
252 }
253}
254
255impl SatAmount {
256 pub fn sat_value(&self) -> u64 {
257 self.0
258 }
259
260 pub fn new(value: u64) -> Self {
261 SatAmount(value)
262 }
263}
264
265impl MsatAmount {
266 pub fn msat_value(&self) -> u64 {
267 self.0
268 }
269
270 pub fn new(value: u64) -> Self {
271 MsatAmount(value)
272 }
273}
274
275impl Serialize for SatAmount {
276 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
277 where
278 S: serde::Serializer,
279 {
280 let amount_str = self.0.to_string();
281 serializer.serialize_str(&amount_str)
282 }
283}
284
285impl Serialize for MsatAmount {
286 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
287 where
288 S: serde::Serializer,
289 {
290 let amount_str = self.0.to_string();
291 serializer.serialize_str(&amount_str)
292 }
293}
294
295impl<'de> Deserialize<'de> for SatAmount {
296 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
297 where
298 D: serde::Deserializer<'de>,
299 {
300 let str_repr = <String as serde::de::Deserialize>::deserialize(deserializer)?;
301 let u64_repr: Result<u64, _> = str_repr
302 .parse()
303 .map_err(|_| D::Error::custom(String::from("Failed to parse sat_amount")));
304 Ok(Self(u64_repr.unwrap()))
305 }
306}
307
308impl<'de> Deserialize<'de> for MsatAmount {
309 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
310 where
311 D: serde::Deserializer<'de>,
312 {
313 let str_repr = <String as serde::de::Deserialize>::deserialize(deserializer)?;
314 let u64_repr: Result<u64, _> = str_repr
315 .parse()
316 .map_err(|_| D::Error::custom(String::from("Failed to parse sat_amount")));
317 Ok(Self(u64_repr.unwrap()))
318 }
319}
320
321impl SatAmount {
322 pub fn checked_add(&self, other: &Self) -> Option<Self> {
323 let sat_value = self.0.checked_add(other.0)?;
324 Some(SatAmount::new(sat_value))
325 }
326}
327
328impl MsatAmount {
329 pub fn checked_add(&self, other: &Self) -> Option<Self> {
330 let sat_value = self.0.checked_add(other.0)?;
331 Some(MsatAmount::new(sat_value))
332 }
333}
334
335#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
336pub struct ShortChannelId(u64);
337
338impl Serialize for ShortChannelId {
339 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
340 where
341 S: Serializer,
342 {
343 serializer.serialize_str(&self.to_string())
344 }
345}
346
347impl<'de> Deserialize<'de> for ShortChannelId {
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 Self::from_str(&s).map_err(|e| Error::custom(e.to_string()))
355 }
356}
357
358impl FromStr for ShortChannelId {
359 type Err = anyhow::Error;
360 fn from_str(s: &str) -> Result<Self, Self::Err> {
361 let parts: Result<Vec<u64>, _> = s.split('x').map(|p| p.parse()).collect();
362 let parts = parts.with_context(|| format!("Malformed short_channel_id: {}", s))?;
363 if parts.len() != 3 {
364 return Err(anyhow!(
365 "Malformed short_channel_id: element count mismatch"
366 ));
367 }
368
369 Ok(ShortChannelId(
370 (parts[0] << 40) | (parts[1] << 16) | parts[2],
371 ))
372 }
373}
374impl Display for ShortChannelId {
375 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
376 write!(f, "{}x{}x{}", self.block(), self.txindex(), self.outnum())
377 }
378}
379impl ShortChannelId {
380 pub fn block(&self) -> u32 {
381 (self.0 >> 40) as u32 & 0xFFFFFF
382 }
383 pub fn txindex(&self) -> u32 {
384 (self.0 >> 16) as u32 & 0xFFFFFF
385 }
386 pub fn outnum(&self) -> u16 {
387 self.0 as u16
388 }
389}
390
391#[derive(Debug, Clone, Serialize, Deserialize)]
392#[serde(transparent)]
393pub struct FeeRate {
394 fee_rate: u64,
395}
396
397impl FeeRate {
398 pub fn from_sats_per_kwu(sats_kwu: u64) -> Self {
399 Self { fee_rate: sats_kwu }
400 }
401
402 pub fn to_sats_per_kwu(&self) -> u64 {
403 self.fee_rate
404 }
405}
406
407#[derive(Debug, Clone, PartialEq, Eq)]
408pub struct TransactionId([u8; 32]);
409
410impl TransactionId {
411 pub fn from_slice(data: &[u8]) -> Result<Self> {
412 let txid: [u8; 32] = data.try_into().context("Invalid transaction Id")?;
413 Ok(Self(txid))
414 }
415}
416
417impl Serialize for TransactionId {
418 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
419 where
420 S: Serializer,
421 {
422 let str_value = self.to_string();
423 serializer.serialize_str(&str_value)
424 }
425}
426
427impl<'de> Deserialize<'de> for TransactionId {
428 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
429 where
430 D: Deserializer<'de>,
431 {
432 struct TransactionIdVisitor;
433
434 impl<'de> Visitor<'de> for TransactionIdVisitor {
435 type Value = TransactionId;
436
437 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
438 write!(formatter, "Valid TransactionId")
439 }
440
441 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
442 where
443 E: SeError,
444 {
445 Self::Value::from_str(v).map_err(|e| E::custom(e.to_string()))
446 }
447 }
448
449 let visitor = TransactionIdVisitor;
450 deserializer.deserialize_str(visitor)
451 }
452}
453
454impl FromStr for TransactionId {
455 type Err = anyhow::Error;
456
457 fn from_str(txid: &str) -> Result<Self> {
458 let txid = hex::decode(txid).context("txid is not valid hex")?;
459 Self::from_slice(&txid)
460 }
461}
462
463impl Display for TransactionId {
464 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
465 let txid_hex = hex::encode(self.0);
466 write!(f, "{}", txid_hex)
467 }
468}
469
470#[derive(Debug, Clone, PartialEq, Eq)]
471pub struct Outpoint {
472 pub txid: TransactionId,
473 pub outnum: u32,
474}
475
476impl Display for Outpoint {
477 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
478 write!(f, "{}:{}", self.txid, self.outnum)
479 }
480}
481
482impl FromStr for Outpoint {
483 type Err = anyhow::Error;
484
485 fn from_str(v: &str) -> Result<Self, Self::Err> {
486 let split: Vec<&str> = v.split(":").collect();
487
488 if split.len() != 2 {
489 return Err(anyhow!("Invalid outpoint. Should be a txid and outnum. e.g: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0'"));
490 }
491
492 let txid = split[0];
493 let outnum = split[1];
494
495 let txid = TransactionId::from_str(txid).context("Invalid outpoint (txid)")?;
496 let outnum = u32::from_str(outnum).context("Invalid outpoint (outnum)")?;
497
498 Ok(Self { txid, outnum })
499 }
500}
501
502impl Serialize for Outpoint {
503 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
504 where
505 S: Serializer,
506 {
507 let outnum_str = self.to_string();
508 serializer.serialize_str(&outnum_str)
509 }
510}
511
512impl<'de> Deserialize<'de> for Outpoint {
513 fn deserialize<D>(deserializer: D) -> std::prelude::v1::Result<Self, D::Error>
514 where
515 D: Deserializer<'de>,
516 {
517 struct OutnumVisitor;
518
519 impl<'de> Visitor<'de> for OutnumVisitor {
520 type Value = Outpoint;
521
522 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
523 write!(formatter, "A valid outpoint")
524 }
525
526 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
527 where
528 E: SeError,
529 {
530 Self::Value::from_str(v).map_err(|e| E::custom(e.to_string()))
531 }
532 }
533
534 let visitor = OutnumVisitor;
535 deserializer.deserialize_str(visitor)
536 }
537}
538
539#[cfg(test)]
540mod test {
541 use super::*;
542
543 #[test]
544 fn parsing_amount_sats() {
545 let json_str_number = "\"10000000001\"";
547
548 let int_number: u64 = 10000000001;
549
550 let x = serde_json::from_str::<SatAmount>(json_str_number).unwrap();
551 assert_eq!(x.sat_value(), int_number);
552 }
553
554 #[test]
555 fn serializing_amount_sats() {
556 let json_str_number = "\"10000000001\"";
559 let int_number: u64 = 10000000001;
560
561 let sat_amount = SatAmount::new(int_number);
562
563 let json_str = serde_json::to_string::<SatAmount>(&sat_amount).unwrap();
564 assert_eq!(json_str, json_str_number);
565 }
566
567 #[test]
568 fn parse_and_serialize_datetime() {
569 let datetime_str = "\"2023-01-01T23:59:59.999Z\"";
570
571 let dt = serde_json::from_str::<IsoDatetime>(datetime_str).unwrap();
572
573 assert_eq!(dt.datetime.year(), 2023);
574 assert_eq!(dt.datetime.month(), time::Month::January);
575 assert_eq!(dt.datetime.day(), 1);
576 assert_eq!(dt.datetime.hour(), 23);
577 assert_eq!(dt.datetime.minute(), 59);
578 assert_eq!(dt.datetime.second(), 59);
579
580 assert_eq!(
581 serde_json::to_string(&dt).expect("Can be serialized"),
582 datetime_str
583 )
584 }
585
586 #[test]
587 fn parse_datetime_that_doesnt_follow_spec() {
588 let datetime_str = "\"2023-01-01T23:59:59.99Z\"";
591
592 let result = serde_json::from_str::<IsoDatetime>(datetime_str);
593 result.expect_err("datetime_str should not be parsed if it doesn't follow spec");
594 }
595
596 #[test]
597 #[allow(clippy::unusual_byte_groupings)]
598 fn parse_scid_from_string() {
599 let scid_str = "16777215x16777215x65535";
609
610 let scid = ShortChannelId::from_str(scid_str).expect("The scid is parseable");
611 assert_eq!(scid.to_string(), scid_str);
612
613 let scid_str = "0x0x0";
615
616 let scid = ShortChannelId::from_str(scid_str).expect("The scid is parseable");
617 assert_eq!(scid.to_string(), scid_str);
618
619 let scid_str = "1x2x3";
620
621 let scid = ShortChannelId::from_str(scid_str).expect("The scid is parseable");
622 assert_eq!(scid.to_string(), scid_str);
623 assert!(ShortChannelId::from_str("xx").is_err());
625 assert!(ShortChannelId::from_str("0x0").is_err());
626 assert!(ShortChannelId::from_str("-2x-12x14").is_err());
627 }
628
629 #[test]
630 fn short_channel_id_is_serialized_as_str() {
631 let scid: ShortChannelId = ShortChannelId::from_str("10x5x8").unwrap();
632 let scid_json_obj = serde_json::to_string(&scid).expect("Can be serialized");
633 assert_eq!("\"10x5x8\"", scid_json_obj);
634 }
635
636 #[test]
637 fn short_channel_id_can_be_deserialized_from_str() {
638 let scid_json = "\"11x12x13\"";
639
640 let scid = serde_json::from_str::<ShortChannelId>(scid_json).expect("scid can be parsed");
641
642 assert_eq!(scid, ShortChannelId::from_str("11x12x13").unwrap());
643 }
644
645 use secp256k1::Secp256k1;
646 use secp256k1::SecretKey;
647
648 #[test]
649 fn pubkey_is_serialized_as_hex() {
650 let mut rng = rand::thread_rng();
652 let s = Secp256k1::signing_only();
653 let secret_key = SecretKey::new(&mut rng);
654
655 let public_key = _PublicKey::from_secret_key(&s, &secret_key);
656 let pub_key_hex = hex::encode(public_key.serialize());
657
658 let public_key = PublicKey::from(public_key);
660
661 let json_value = serde_json::json!(public_key);
663
664 assert_eq!(
667 pub_key_hex, json_value,
668 "The key should be serialized as a compressed hex"
669 );
670 }
671
672 #[test]
673 fn deserialize_onchain_address() {
674 let regtest_address_json = "\"bcrt1qkm08480v79rzjp7tx2pjrly423ncv85k65nsmu\"";
675 let parsed = serde_json::from_str::<OnchainAddress>(regtest_address_json).unwrap();
676 parsed
677 .clone()
678 .require_network(&Network::Regtest)
679 .expect("Is okay because it is a regtest address");
680 parsed
681 .clone()
682 .require_network(&Network::Bitcoin)
683 .expect_err("Should fail because the address is not a mainnet address");
684
685 }
692
693 #[test]
694 fn serialize_onchain_address() {
695 let address_unchecked: Address<NetworkUnchecked> =
697 "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap();
698
699 let json_value = serde_json::to_value(address_unchecked.clone()).unwrap();
701 assert_eq!(json_value, "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf");
702
703 let address_checked = address_unchecked.require_network(Network::Bitcoin).unwrap();
705 let json_value = serde_json::to_value(address_checked).unwrap();
706 assert_eq!(json_value, "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf");
707 }
708
709 #[test]
710 fn serialize_fee_rate() {
711 let min_fee = FeeRate::from_sats_per_kwu(253);
712 let json_value = serde_json::to_value(min_fee).unwrap();
713
714 assert_eq!(json_value, serde_json::json!(253));
715 }
716
717 #[test]
718 fn serialize_txid_type() {
719 let txid_str = "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b";
720 let tx = TransactionId::from_str(txid_str).unwrap();
721 assert_eq!(tx.to_string(), txid_str);
722
723 let tx_deserialized: TransactionId =
724 serde_json::from_value(serde_json::json!(txid_str)).unwrap();
725 assert_eq!(
726 tx, tx_deserialized,
727 "Failed to deserialize transaction correctly"
728 );
729
730 let tx_serialized = serde_json::to_value(&tx).unwrap();
731 assert_eq!(tx_serialized, serde_json::json!(txid_str));
732 }
733
734 #[test]
735 fn serialize_outpoint() {
736 let outpoint_str = "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0";
737 let outpoint = Outpoint::from_str(outpoint_str).unwrap();
738 assert_eq!(outpoint.to_string(), outpoint_str);
739
740 let outpoint_deserialized: Outpoint =
741 serde_json::from_value(serde_json::json!(outpoint_str)).unwrap();
742 assert_eq!(
743 outpoint, outpoint_deserialized,
744 "Failed to deserialize transaction correctly"
745 );
746
747 let outpoint_serialized = serde_json::to_value(&outpoint).unwrap();
748 assert_eq!(outpoint_serialized, serde_json::json!(outpoint_str));
749 }
750}