From 5119fcab671646454c10563c7b79741728d33a03 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sun, 6 Sep 2026 14:26:53 -0700 Subject: LNURL/merchant payments read as PAYMENTS, not zaps, and skip redundant steps. (1) Terminology: a payment is a "zap" only when it targets a nostr person or note (npub / note-zap with an eventId, captured as z.social at begin); paying a lightning address, LNURL or merchant now says "Pay over Lightning" / "Pay" everywhere — amount screen, review title, success screen — even when the endpoint supports zap receipts. (2) A fixed-amount payment (min==max — a POS tag, paywall, bolt card) has nothing to type, so the amount screen is skipped and the flow goes straight to the quote/review; the two perceived confirmations collapse to one. (3) Per-recipient auto-pay budget: the review offers "Auto-pay up to N next time" (ctx.lnBudget/setLnBudget in prefs, synced), and a fixed charge within a set budget pays as soon as the quote lands — no tap. Guarded: only fixed amounts, only within the budget, only when funds cover it; over budget / no funds / quote error all fall back to the normal review, and social zaps are untouched. Verified with a driven-feature harness (fake ctx + local LNURL server): fixed skips to startLnPay with social=false/fixedSat set, a covering budget sets autopay, variable still shows the amount screen titled/buttoned "Pay" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz --- src/app.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/app.js') diff --git a/src/app.js b/src/app.js index a2411a9..802781c 100644 --- a/src/app.js +++ b/src/app.js @@ -4829,6 +4829,21 @@ const ctx = { wallet.saveFeatureState('prefs', p); try { wallet.saveCache(); } catch {} }, + // Per-recipient auto-pay budget: a fixed-amount LNURL/address the user + // trusts to pay without confirmation, up to this many sats. Keyed by the + // recipient's address/lnurl. Synced with the rest of prefs. + lnBudget: (key) => { + if (!key || !wallet.loadFeatureState) return 0; + return (wallet.loadFeatureState('prefs', {}).lnBudgets || {})[key] || 0; + }, + setLnBudget: (key, sat) => { + if (!key) return; + const p = wallet.loadFeatureState('prefs', {}); + p.lnBudgets = { ...(p.lnBudgets || {}) }; + if (sat > 0) p.lnBudgets[key] = Math.floor(sat); else delete p.lnBudgets[key]; + wallet.saveFeatureState('prefs', p); + try { wallet.saveCache(); } catch {} + }, brandHeader, activeAccount, setAccounts: (list) => { accounts = list; }, getAccounts: () => accounts, claimTargets, enterWallet, activateAccount, commitAccount, -- cgit v1.2.3