Skip to content
This repository was archived by the owner on Feb 3, 2025. It is now read-only.

Commit 493dfc1

Browse files
committed
Filter out paid invoices from NWC on startup
1 parent dd3de02 commit 493dfc1

3 files changed

Lines changed: 57 additions & 13 deletions

File tree

mutiny-core/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,8 +1156,8 @@ impl<S: MutinyStorage> MutinyWallet<S> {
11561156
log_warn!(logger, "Failed to clear in-active NWC profiles: {e}");
11571157
}
11581158

1159-
if let Err(e) = nostr.clear_expired_nwc_invoices().await {
1160-
log_warn!(logger, "Failed to clear expired NWC invoices: {e}");
1159+
if let Err(e) = nostr.clear_invalid_nwc_invoices(&self_clone).await {
1160+
log_warn!(logger, "Failed to clear invalid NWC invoices: {e}");
11611161
}
11621162

11631163
let client = Client::new(nostr.primary_key.clone());

mutiny-core/src/nostr/mod.rs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,23 +1112,45 @@ impl<S: MutinyStorage> NostrManager<S> {
11121112
Ok(())
11131113
}
11141114

1115-
/// Goes through all pending NWC invoices and removes the expired ones
1116-
pub async fn clear_expired_nwc_invoices(&self) -> Result<(), MutinyError> {
1115+
/// Goes through all pending NWC invoices and removes invoices that are
1116+
/// expired or have been paid
1117+
pub async fn clear_invalid_nwc_invoices(
1118+
&self,
1119+
invoice_handler: &impl InvoiceHandler,
1120+
) -> Result<(), MutinyError> {
11171121
self.pending_nwc_lock.lock().await;
1118-
let mut invoices: Vec<PendingNwcInvoice> = self
1122+
let invoices: Vec<PendingNwcInvoice> = self
11191123
.storage
11201124
.get_data(PENDING_NWC_EVENTS_KEY)?
11211125
.unwrap_or_default();
11221126

1123-
// remove expired invoices
1124-
invoices.retain(|x| !x.is_expired());
1127+
let mut new_invoices = Vec::with_capacity(invoices.len());
1128+
1129+
for inv in invoices {
1130+
// remove expired invoices
1131+
if inv.is_expired() {
1132+
continue;
1133+
}
1134+
1135+
// remove paid invoices
1136+
if invoice_handler
1137+
.lookup_payment(&inv.invoice.payment_hash().into_32())
1138+
.await
1139+
.is_some_and(|p| p.status == HTLCStatus::Succeeded)
1140+
{
1141+
continue;
1142+
}
1143+
1144+
// keep the invoice if it is still valid
1145+
new_invoices.push(inv);
1146+
}
11251147

11261148
// sort and dedup
1127-
invoices.sort();
1128-
invoices.dedup();
1149+
new_invoices.sort();
1150+
new_invoices.dedup();
11291151

11301152
self.storage
1131-
.set_data(PENDING_NWC_EVENTS_KEY.to_string(), invoices, None)?;
1153+
.set_data(PENDING_NWC_EVENTS_KEY.to_string(), new_invoices, None)?;
11321154

11331155
Ok(())
11341156
}

mutiny-core/src/nostr/nwc.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,7 +1795,7 @@ mod wasm_test {
17951795
}
17961796

17971797
#[test]
1798-
async fn test_clear_expired_pending_invoices() {
1798+
async fn test_clear_invalid_pending_invoices() {
17991799
let storage = MemoryStorage::default();
18001800
let xprivkey = ExtendedPrivKey::new_master(Network::Regtest, &[0; 64]).unwrap();
18011801
let stop = Arc::new(AtomicBool::new(false));
@@ -1822,9 +1822,10 @@ mod wasm_test {
18221822
identifier: None,
18231823
};
18241824
// add an unexpired invoice
1825+
let dummy_invoice = create_dummy_invoice(Some(1_000), Network::Regtest, None).0;
18251826
let unexpired = PendingNwcInvoice {
18261827
index: Some(0),
1827-
invoice: create_dummy_invoice(Some(1_000), Network::Regtest, None).0,
1828+
invoice: dummy_invoice.clone(),
18281829
event_id: EventId::all_zeros(),
18291830
pubkey: nostr_manager.public_key,
18301831
identifier: None,
@@ -1841,10 +1842,31 @@ mod wasm_test {
18411842
assert_eq!(pending.len(), 2);
18421843

18431844
// check that the expired invoice is cleared
1844-
nostr_manager.clear_expired_nwc_invoices().await.unwrap();
1845+
let mut node = MockInvoiceHandler::new();
1846+
node.expect_lookup_payment().return_const(None);
1847+
nostr_manager
1848+
.clear_invalid_nwc_invoices(&node)
1849+
.await
1850+
.unwrap();
18451851
let pending = nostr_manager.get_pending_nwc_invoices().unwrap();
18461852
assert_eq!(pending.len(), 1);
18471853
assert_eq!(pending[0], unexpired);
1854+
1855+
let mut node = MockInvoiceHandler::new();
1856+
node.expect_lookup_payment()
1857+
.with(eq(dummy_invoice.payment_hash().into_32()))
1858+
.returning(move |_| {
1859+
Some(MutinyInvoice {
1860+
status: HTLCStatus::Succeeded,
1861+
..Default::default()
1862+
})
1863+
});
1864+
nostr_manager
1865+
.clear_invalid_nwc_invoices(&node)
1866+
.await
1867+
.unwrap();
1868+
let pending = nostr_manager.get_pending_nwc_invoices().unwrap();
1869+
assert!(pending.is_empty());
18481870
}
18491871

18501872
#[test]

0 commit comments

Comments
 (0)