Recover failed Lightning file attempts without blocking other payment methods
This commit is contained in:
@@ -637,4 +637,20 @@ describe('RPCClient convenience methods', () => {
|
||||
await rpcClient.diskCleanup()
|
||||
expect(getLastMethod()).toBe('system.disk-cleanup')
|
||||
})
|
||||
it.each([
|
||||
[{ status: 'failed', payment_hash: 'a'.repeat(64), failure_reason: 'No route' }, 'failed'],
|
||||
[{ status: 'unknown', payment_hash: 'a'.repeat(64) }, 'pending'],
|
||||
[{ status: 'new-status', payment_hash: 'a'.repeat(64) }, 'pending'],
|
||||
[{ status: '', payment_hash: 'a'.repeat(64) }, 'pending'],
|
||||
[{}, 'pending'],
|
||||
[{ status: 'succeeded', payment_hash: 'a'.repeat(64) }, 'succeeded'],
|
||||
[{ payment_hash: 'a'.repeat(64), amount_sats: 5 }, 'succeeded'],
|
||||
])('keeps terminal, uncertain and legacy payment states distinct: %j', async (response, expected) => {
|
||||
mockFetch.mockResolvedValueOnce(jsonResponse({ result: response }))
|
||||
const result = await rpcClient.payLightningInvoice({ payment_request: 'ln-test' })
|
||||
expect(result.status).toBe(expected)
|
||||
if (expected === 'failed') expect(result.failure_reason).toBe('No route')
|
||||
expect(mockFetch).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
@@ -490,19 +490,28 @@ class RPCClient {
|
||||
status?: string
|
||||
payment_hash?: string
|
||||
amount_sats?: number
|
||||
failure_reason?: string
|
||||
}>({
|
||||
method: 'lnd.payinvoice',
|
||||
params,
|
||||
// Above the backend's 120s wait so the backend always answers first.
|
||||
timeout: 130000,
|
||||
maxRetries: 1,
|
||||
})
|
||||
|
||||
const hash = res.payment_hash || ''
|
||||
const amount = res.amount_sats || 0
|
||||
// Older backends have no status field — a plain response was a success.
|
||||
if (res.status !== 'pending') {
|
||||
if (res.status === 'failed') {
|
||||
return { status: 'failed', payment_hash: hash, amount_sats: amount, failure_reason: res.failure_reason || 'Payment failed' }
|
||||
}
|
||||
// Legacy success must include the canonical payment hash. An unknown,
|
||||
// malformed or newly introduced status must never become invented success.
|
||||
if (res.status === 'succeeded' || (res.status === undefined && /^[a-f0-9]{64}$/i.test(hash))) {
|
||||
return { status: 'succeeded', payment_hash: hash, amount_sats: amount }
|
||||
}
|
||||
if (res.status !== 'pending' && res.status !== 'in_flight') {
|
||||
return { status: 'pending', payment_hash: hash, amount_sats: amount }
|
||||
}
|
||||
if (!hash) return { status: 'pending', payment_hash: '', amount_sats: amount }
|
||||
|
||||
// Let the caller unblock its UI right now ("settling…") — the backend
|
||||
|
||||
Reference in New Issue
Block a user