|
| 1 | +// This file is Copyright its original authors, visible in version control history. |
| 2 | +// |
| 3 | +// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 4 | +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or |
| 5 | +// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in |
| 6 | +// accordance with one or both of these licenses. |
| 7 | + |
| 8 | +use bitcoin::Txid; |
| 9 | +use lightning::{impl_writeable_tlv_based, ln::channelmanager::PaymentId}; |
| 10 | + |
| 11 | +use crate::{ |
| 12 | + data_store::{StorableObject, StorableObjectUpdate}, |
| 13 | + payment::{store::PaymentDetailsUpdate, PaymentDetails}, |
| 14 | +}; |
| 15 | + |
| 16 | +/// Represents a pending payment |
| 17 | +#[derive(Clone, Debug, PartialEq, Eq)] |
| 18 | +pub struct PendingPaymentDetails { |
| 19 | + /// The full payment details |
| 20 | + pub details: PaymentDetails, |
| 21 | + /// Cached timestamp for efficient cleanup queries |
| 22 | + pub created_at: u64, |
| 23 | + /// Transaction IDs that have replaced or conflict with this payment. |
| 24 | + pub conflicting_txids: Vec<Txid>, |
| 25 | +} |
| 26 | + |
| 27 | +impl PendingPaymentDetails { |
| 28 | + pub(crate) fn new(details: PaymentDetails, conflicting_txids: Vec<Txid>) -> Self { |
| 29 | + Self { created_at: details.latest_update_timestamp, details, conflicting_txids } |
| 30 | + } |
| 31 | + |
| 32 | + /// Convert to finalized payment for the main payment store |
| 33 | + pub fn into_payment_details(self) -> PaymentDetails { |
| 34 | + self.details |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +impl_writeable_tlv_based!(PendingPaymentDetails, { |
| 39 | + (0, details, required), |
| 40 | + (2, created_at, required), |
| 41 | + (4, conflicting_txids, optional_vec), |
| 42 | +}); |
| 43 | + |
| 44 | +#[derive(Clone, Debug, PartialEq, Eq)] |
| 45 | +pub(crate) struct PendingPaymentDetailsUpdate { |
| 46 | + pub id: PaymentId, |
| 47 | + pub payment_update: Option<PaymentDetailsUpdate>, |
| 48 | + pub conflicting_txids: Option<Vec<Txid>>, |
| 49 | +} |
| 50 | + |
| 51 | +impl StorableObject for PendingPaymentDetails { |
| 52 | + type Id = PaymentId; |
| 53 | + type Update = PendingPaymentDetailsUpdate; |
| 54 | + |
| 55 | + fn id(&self) -> Self::Id { |
| 56 | + self.details.id |
| 57 | + } |
| 58 | + |
| 59 | + fn update(&mut self, update: &Self::Update) -> bool { |
| 60 | + let mut updated = false; |
| 61 | + |
| 62 | + // Update the underlying payment details if present |
| 63 | + if let Some(payment_update) = &update.payment_update { |
| 64 | + updated |= self.details.update(payment_update); |
| 65 | + } |
| 66 | + |
| 67 | + if let Some(new_conflicting_txids) = &update.conflicting_txids { |
| 68 | + if &self.conflicting_txids != new_conflicting_txids { |
| 69 | + self.conflicting_txids = new_conflicting_txids.clone(); |
| 70 | + updated = true; |
| 71 | + } |
| 72 | + } |
| 73 | + |
| 74 | + updated |
| 75 | + } |
| 76 | + |
| 77 | + fn to_update(&self) -> Self::Update { |
| 78 | + self.into() |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +impl StorableObjectUpdate<PendingPaymentDetails> for PendingPaymentDetailsUpdate { |
| 83 | + fn id(&self) -> <PendingPaymentDetails as StorableObject>::Id { |
| 84 | + self.id |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +impl From<&PendingPaymentDetails> for PendingPaymentDetailsUpdate { |
| 89 | + fn from(value: &PendingPaymentDetails) -> Self { |
| 90 | + Self { |
| 91 | + id: value.id(), |
| 92 | + payment_update: Some(value.details.to_update()), |
| 93 | + conflicting_txids: Some(value.conflicting_txids.clone()), |
| 94 | + } |
| 95 | + } |
| 96 | +} |
0 commit comments