feat: add quickpay daily spend limit - #672
Conversation
Track USD spend on the local calendar day so QuickPay can enforce a daily cap.
Expose the Android daily multiplier steps and resolved dollar cap in settings, and keep the value in backup.
Keep auto-pay PIN-free under the daily limit, record spend on success or pending, and send over-cap payments to Confirm.
Greptile SummaryThe PR adds a configurable QuickPay daily spending cap and persists hash-bound reservations so pending payments can be reconciled safely.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| Bitkit/Utilities/QuickPayPaymentCoordinator.swift | Coordinates hash-bound reservation, dispatch, pending recovery, and terminal settlement without leaving either previously reported race outstanding. |
| Bitkit/Utilities/QuickPaySpendStore.swift | Implements locked, day-keyed USD-cent reservations with matching release, reconciliation, persistence, and backup behavior. |
| Bitkit/ViewModels/WalletViewModel.swift | Separates payment dispatch from cancellable settlement watching while retaining session-wide terminal event handling. |
| Bitkit/ViewModels/AppViewModel.swift | Routes global Lightning terminal events through the QuickPay coordinator and suppresses duplicate result notifications for the active hash. |
| Bitkit/Views/Wallets/Send/SendQuickpay.swift | Delegates payment lifecycle to the coordinator and detaches presentation state when the QuickPay view disappears. |
| Bitkit/Utilities/PaymentNavigationHelper.swift | Applies per-transaction and daily-cap eligibility and replaces over-cap QuickPay routes with confirmation. |
| BitkitTests/QuickPayPaymentCoordinatorTests.swift | Covers terminal-event ordering, duplicate invoices, ambiguous dispatch, recovery, spend accounting, and fee-inclusive success behavior. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[QuickPay request] --> B{Per-payment threshold and daily cap allow it?}
B -->|No| C[Open confirmation flow]
B -->|Yes| D[Reserve USD cents by payment hash]
D --> E[Dispatch Lightning payment]
E -->|Success| F[Keep spend and show success]
E -->|Pending| G[Keep hash-bound reservation]
G --> H{Later terminal event}
H -->|Success| F
H -->|Failure| I[Release matching reservation]
E -->|Immediate failure| I
Reviews (5): Last reviewed commit: "fix: prevent QuickPay success replays" | Re-trigger Greptile
This comment was marked as outdated.
This comment was marked as outdated.
|
Tested the QuickPay daily limit flow on local regtest with fixed-amount hold invoices. Covered:
The timeout now starts after I also reviewed the code structure around |
|
Retested. Previous findings are fixed:
New issue, both platforms: paying an invoice via QuickPay, then scanning/pasting that same invoice again, shows Bitcoin Sent / success again. LDK rejects it as already paid ( Recordings + logs attached. bitkit_logs_2026-08-27_10-54-19.zip repeat.invoice.-.ios.mov |
This comment was marked as outdated.
This comment was marked as outdated.
|
Addressed the latest QuickPay findings in
Focused |

Closes #670
This PR ports QuickPay daily spend limits from Android (synonymdev/bitkit-android#1159) so auto-pay stays PIN-free under a configurable daily cap.
Description
QuickPay stays confirmation-free and PIN-free while a payment is under the per-tx threshold and the daily cap (
threshold × multiplierUSD). Once the cap would be exceeded, the payment opens Confirm, where PIN for payments still applies if that setting is on.1,3,5,10,50(default5)$capquickPayDailyLimitMultiplierOut of scope
Preview
Updated screenshot, integrating designer's feedback.
happy-daily-cap.mp4
over-cap.mp4
QA Notes
Manual Tests
$copy updates (threshold × multiplier).regression:Settings → QuickPay → leave QuickPay off → scan a fixed-amount LN invoice: Confirm still opens.regression:Variable amount LN invoice / LNURL-pay: still lands on Amount, not QuickPay.Automated Checks
BitkitTests/QuickPaySpendStoreTests.swift.BitkitTests/PaymentNavigationHelperTests.swift.BitkitTests/QuickPayLimitsTests.swift.BitkitTests/AddressTypeSettingsTests.swift.BitkitTests/QuickPayPaymentCoordinatorTests.swift.node scripts/validate-translations.js: 0 errors.