fix(lightning): never report a slow in-flight payment as failed

Slow multi-hop payments (>15s routing) surfaced as "Payment failed"
while LND settled them in the background: the shared LND REST client's
15s total timeout aborted the synchronous /v1/channels/transactions
wait, and every UI path treated that abort as a definitive failure. The
payment then succeeded anyway and only appeared in history on the next
background poll.

Backend: lnd.payinvoice now decodes the invoice up front for its payment
hash, pays on a dedicated 120s client, and answers status:"pending" with
the hash (never an error) when the wait elapses after the payment was
handed to LND — only a pre-connect failure is still a hard error. New
lnd.paymentstatus RPC reports succeeded/failed/in_flight (with humanized
failure reasons) from /v1/payments.

Frontend: new rpcClient.payLightningInvoice() pays then polls
lnd.paymentstatus to a real terminal state (3s interval, up to 2 min);
all five call sites (send modal, scan modal, web5 unified send, peer-file
purchase, app-launcher payments) migrated. Failure is only shown when LND
itself declares FAILED; a still-settling payment shows an in-flight state
and success fires the transaction refresh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-27 05:33:02 -04:00
co-authored by Claude Fable 5
parent aa272bfcf4
commit 9cd507269c
8 changed files with 264 additions and 36 deletions
@@ -132,6 +132,7 @@ impl RpcHandler {
"lnd.estimatefee" => self.handle_lnd_estimatefee(params).await,
"lnd.createinvoice" => self.handle_lnd_createinvoice(params).await,
"lnd.payinvoice" => self.handle_lnd_payinvoice(params).await,
"lnd.paymentstatus" => self.handle_lnd_paymentstatus(params).await,
"lnd.create-psbt" => self.handle_lnd_create_psbt(params).await,
"lnd.finalize-psbt" => self.handle_lnd_finalize_psbt(params).await,
"lnd.create-raw-tx" => self.handle_lnd_create_raw_tx(params).await,