Skip to content

Commit 9f50261

Browse files
authored
Prioritise 'already paid' over expiry when checking a Bolt11 invoice (#800)
1 parent 13c8ddb commit 9f50261

2 files changed

Lines changed: 11 additions & 9 deletions

File tree

phoenix-android/src/main/res/values/important_strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@
177177

178178
<string name="send_error_invoice_expired">This invoice is expired.</string>
179179
<string name="send_error_payment_pending">This payment is already being processed. Please wait for it to complete.</string>
180-
<string name="send_error_already_paid">This payment has already been paid.</string>
180+
<string name="send_error_already_paid">This invoice has already been paid.</string>
181181
<string name="send_error_invalid_chain">This payment does not use the same blockchain as your wallet.</string>
182182
<string name="send_error_lnurl_invalid">Failed to process this LNURL link. Make sure it is valid.</string>
183183
<string name="send_error_lnurl_unsupported">This type of LNURL is not supported yet.</string>

phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/SendManager.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -214,22 +214,24 @@ class SendManager(
214214
return BadRequestReason.ChainMismatch(expected = chain)
215215
}
216216

217-
if (invoice.isExpired(currentTimestampSeconds())) {
218-
return BadRequestReason.Expired(invoice.timestampSeconds, invoice.expirySeconds ?: Bolt11Invoice.DEFAULT_EXPIRY_SECONDS.toLong())
219-
}
220-
221217
val db = databaseManager.databases.filterNotNull().first()
222218
val similarPayments = db.payments.listLightningOutgoingPayments(invoice.paymentHash)
223219
// we MUST raise an error if this payment hash has already been paid, or is being paid.
224220
// parallel pending payments on the same payment hash can trigger force-closes
225221
// FIXME: this check should be done in lightning-kmp, not in Phoenix
226-
return when {
222+
// Note: check payment history before expiry so that "already paid" takes priority over "expired".
223+
when {
227224
similarPayments.any { it.status is LightningOutgoingPayment.Status.Succeeded || it.parts.any { part -> part.status is LightningOutgoingPayment.Part.Status.Succeeded } } ->
228-
BadRequestReason.AlreadyPaidInvoice
225+
return BadRequestReason.AlreadyPaidInvoice
229226
similarPayments.any { it.status is LightningOutgoingPayment.Status.Pending || it.parts.any { part -> part.status is LightningOutgoingPayment.Part.Status.Pending } } ->
230-
BadRequestReason.PaymentPending
231-
else -> null
227+
return BadRequestReason.PaymentPending
232228
}
229+
230+
if (invoice.isExpired(currentTimestampSeconds())) {
231+
return BadRequestReason.Expired(invoice.timestampSeconds, invoice.expirySeconds ?: Bolt11Invoice.DEFAULT_EXPIRY_SECONDS.toLong())
232+
}
233+
234+
return null
233235
}
234236

235237
private fun processOffer(

0 commit comments

Comments
 (0)