From dd1489303f59ccef6b322142f94e08d750c06e79 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Mon, 14 Sep 2026 09:16:23 -0700 Subject: A zap answers as fast as the route allows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wallet used to add two to four seconds of its own around a Lightning send: a random pause plus a relay look-back before paying, and a two-second poll for the result after. The notifier's claim now decides who pays in one round trip, with the relay look-back kept only for replays and for when the notifier gives no verdict; a phone answering from behind another app waits a second so a desktop tab wins the claim instead of paying at a throttled crawl. After the send, one held CheckLightningPayment call brings the preimage the moment CLN has it — for wallet-connect pays, the background worker, and the app's own Send. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR --- src/features/ark.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/features/ark.js') diff --git a/src/features/ark.js b/src/features/ark.js index e9c93b1..04444ff 100644 --- a/src/features/ark.js +++ b/src/features/ark.js @@ -763,6 +763,17 @@ export function arkFeature(ctx) { } function pollArkLn(id, onSettle) { stopArkLnPoll(id); + // One held call brings the settlement the moment the server has it; + // the interval below is the fallback pace if that call breaks. + if (ark) { + ark.awaitLnPay(id).then((a) => { + if (a && ['done', 'failed'].includes(a.step) && arkLnTimers.has(id)) { + stopArkLnPoll(id); + onSettle(a); + } + render(); + }).catch(() => {}); + } arkLnTimers.set(id, setInterval(async () => { if (!ark) return; const a = await ark.driveLn(id).catch(() => null); @@ -882,6 +893,7 @@ export function arkFeature(ctx) { for (let attempt = 0; attempt < 3; attempt++) { const routingFeeSat = attempt === 0 ? undefined : (last?.routingFeeSat ?? 0) + 1; const id = await mgr.payLnInvoice(invoice, { routingFeeSat }); + await mgr.awaitLnPay(id).catch(() => {}); for (let i = 0; i < 60; i++) { const a = mgr.lnAction(id); if (!a || ['done', 'failed'].includes(a.step)) break; -- cgit v1.2.3