Skip to content

Commit 6e4d70d

Browse files
committed
feat: add accessor methods for common PaymentKind fields
Added payment_hash(), preimage(), and secret() helper methods to PaymentKind. Refactored PaymentDetailsUpdate to use them and added unit tests.
1 parent bbefa73 commit 6e4d70d

File tree

1 file changed

+138
-8
lines changed

1 file changed

+138
-8
lines changed

src/payment/store.rs

Lines changed: 138 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,52 @@ impl_writeable_tlv_based_enum!(PaymentKind,
483483
}
484484
);
485485

486+
impl PaymentKind {
487+
/// Returns the payment hash if this payment kind has one.
488+
///
489+
/// Returns `None` for on-chain payments or when the hash hasn't been set yet (e.g., for
490+
/// outbound BOLT 12 payments before receiving an invoice).
491+
pub fn payment_hash(&self) -> Option<PaymentHash> {
492+
match self {
493+
PaymentKind::Onchain { .. } => None,
494+
PaymentKind::Bolt11 { hash, .. } => Some(*hash),
495+
PaymentKind::Bolt11Jit { hash, .. } => Some(*hash),
496+
PaymentKind::Bolt12Offer { hash, .. } => *hash,
497+
PaymentKind::Bolt12Refund { hash, .. } => *hash,
498+
PaymentKind::Spontaneous { hash, .. } => Some(*hash),
499+
}
500+
}
501+
502+
/// Returns the payment preimage if this payment kind has one.
503+
///
504+
/// Returns `None` for on-chain payments or when the preimage hasn't been set yet.
505+
pub fn preimage(&self) -> Option<PaymentPreimage> {
506+
match self {
507+
PaymentKind::Onchain { .. } => None,
508+
PaymentKind::Bolt11 { preimage, .. } => *preimage,
509+
PaymentKind::Bolt11Jit { preimage, .. } => *preimage,
510+
PaymentKind::Bolt12Offer { preimage, .. } => *preimage,
511+
PaymentKind::Bolt12Refund { preimage, .. } => *preimage,
512+
PaymentKind::Spontaneous { preimage, .. } => *preimage,
513+
}
514+
}
515+
516+
/// Returns the payment secret if this payment kind has one.
517+
///
518+
/// Returns `None` for on-chain payments, spontaneous payments, or when the secret hasn't been
519+
/// set yet.
520+
pub fn secret(&self) -> Option<PaymentSecret> {
521+
match self {
522+
PaymentKind::Onchain { .. } => None,
523+
PaymentKind::Bolt11 { secret, .. } => *secret,
524+
PaymentKind::Bolt11Jit { secret, .. } => *secret,
525+
PaymentKind::Bolt12Offer { secret, .. } => *secret,
526+
PaymentKind::Bolt12Refund { secret, .. } => *secret,
527+
PaymentKind::Spontaneous { .. } => None,
528+
}
529+
}
530+
}
531+
486532
/// Represents the confirmation status of a transaction.
487533
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
488534
pub enum ConfirmationStatus {
@@ -561,14 +607,9 @@ impl PaymentDetailsUpdate {
561607

562608
impl From<&PaymentDetails> for PaymentDetailsUpdate {
563609
fn from(value: &PaymentDetails) -> Self {
564-
let (hash, preimage, secret) = match value.kind {
565-
PaymentKind::Bolt11 { hash, preimage, secret, .. } => (Some(hash), preimage, secret),
566-
PaymentKind::Bolt11Jit { hash, preimage, secret, .. } => (Some(hash), preimage, secret),
567-
PaymentKind::Bolt12Offer { hash, preimage, secret, .. } => (hash, preimage, secret),
568-
PaymentKind::Bolt12Refund { hash, preimage, secret, .. } => (hash, preimage, secret),
569-
PaymentKind::Spontaneous { hash, preimage, .. } => (Some(hash), preimage, None),
570-
_ => (None, None, None),
571-
};
610+
let hash = value.kind.payment_hash();
611+
let preimage = value.kind.preimage();
612+
let secret = value.kind.secret();
572613

573614
let confirmation_status = match value.kind {
574615
PaymentKind::Onchain { status, .. } => Some(status),
@@ -768,4 +809,93 @@ mod tests {
768809
}
769810
}
770811
}
812+
813+
#[test]
814+
fn payment_kind_accessor_methods() {
815+
use bitcoin::hashes::Hash;
816+
817+
let hash = PaymentHash([42u8; 32]);
818+
let preimage = Some(PaymentPreimage([43u8; 32]));
819+
let secret = Some(PaymentSecret([44u8; 32]));
820+
let txid = bitcoin::Txid::from_byte_array([1u8; 32]);
821+
let offer_id = OfferId([2u8; 32]);
822+
823+
// Test Onchain variant
824+
let onchain_kind = PaymentKind::Onchain { txid, status: ConfirmationStatus::Unconfirmed };
825+
assert_eq!(onchain_kind.payment_hash(), None);
826+
assert_eq!(onchain_kind.preimage(), None);
827+
assert_eq!(onchain_kind.secret(), None);
828+
829+
// Test Bolt11 variant
830+
let bolt11_kind = PaymentKind::Bolt11 { hash, preimage, secret };
831+
assert_eq!(bolt11_kind.payment_hash(), Some(hash));
832+
assert_eq!(bolt11_kind.preimage(), preimage);
833+
assert_eq!(bolt11_kind.secret(), secret);
834+
835+
// Test Bolt11 variant without preimage/secret
836+
let bolt11_kind_empty = PaymentKind::Bolt11 { hash, preimage: None, secret: None };
837+
assert_eq!(bolt11_kind_empty.payment_hash(), Some(hash));
838+
assert_eq!(bolt11_kind_empty.preimage(), None);
839+
assert_eq!(bolt11_kind_empty.secret(), None);
840+
841+
// Test Bolt11Jit variant
842+
let lsp_fee_limits = LSPFeeLimits {
843+
max_total_opening_fee_msat: Some(1000),
844+
max_proportional_opening_fee_ppm_msat: Some(100),
845+
};
846+
let bolt11_jit_kind = PaymentKind::Bolt11Jit {
847+
hash,
848+
preimage,
849+
secret,
850+
counterparty_skimmed_fee_msat: Some(500),
851+
lsp_fee_limits,
852+
};
853+
assert_eq!(bolt11_jit_kind.payment_hash(), Some(hash));
854+
assert_eq!(bolt11_jit_kind.preimage(), preimage);
855+
assert_eq!(bolt11_jit_kind.secret(), secret);
856+
857+
// Test Bolt12Offer variant with hash
858+
let bolt12_offer_kind = PaymentKind::Bolt12Offer {
859+
hash: Some(hash),
860+
preimage,
861+
secret,
862+
offer_id,
863+
payer_note: None,
864+
quantity: None,
865+
};
866+
assert_eq!(bolt12_offer_kind.payment_hash(), Some(hash));
867+
assert_eq!(bolt12_offer_kind.preimage(), preimage);
868+
assert_eq!(bolt12_offer_kind.secret(), secret);
869+
870+
// Test Bolt12Offer variant without hash (e.g., before invoice received)
871+
let bolt12_offer_kind_no_hash = PaymentKind::Bolt12Offer {
872+
hash: None,
873+
preimage: None,
874+
secret: None,
875+
offer_id,
876+
payer_note: None,
877+
quantity: None,
878+
};
879+
assert_eq!(bolt12_offer_kind_no_hash.payment_hash(), None);
880+
assert_eq!(bolt12_offer_kind_no_hash.preimage(), None);
881+
assert_eq!(bolt12_offer_kind_no_hash.secret(), None);
882+
883+
// Test Bolt12Refund variant
884+
let bolt12_refund_kind = PaymentKind::Bolt12Refund {
885+
hash: Some(hash),
886+
preimage,
887+
secret,
888+
payer_note: None,
889+
quantity: None,
890+
};
891+
assert_eq!(bolt12_refund_kind.payment_hash(), Some(hash));
892+
assert_eq!(bolt12_refund_kind.preimage(), preimage);
893+
assert_eq!(bolt12_refund_kind.secret(), secret);
894+
895+
// Test Spontaneous variant (no secret)
896+
let spontaneous_kind = PaymentKind::Spontaneous { hash, preimage };
897+
assert_eq!(spontaneous_kind.payment_hash(), Some(hash));
898+
assert_eq!(spontaneous_kind.preimage(), preimage);
899+
assert_eq!(spontaneous_kind.secret(), None);
900+
}
771901
}

0 commit comments

Comments
 (0)