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 persisted, configurable daily USD limit for PIN-free QuickPay and coordinates reservations across dispatch, pending settlement, terminal events, retries, backup, and restoration.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| Bitkit/Utilities/QuickPayPaymentCoordinator.swift | Centralizes QuickPay reservation, dispatch, recovery, terminal-event attribution, fee application, and result navigation. |
| Bitkit/Utilities/QuickPaySpendStore.swift | Implements synchronized, persisted daily spend accounting with hash-bound reservations and LDK reconciliation. |
| Bitkit/ViewModels/AppViewModel.swift | Routes Lightning terminal events through the QuickPay coordinator before resolving pending send-sheet state. |
| Bitkit/ViewModels/WalletViewModel.swift | Integrates payment event handling and reconciliation with the revised QuickPay lifecycle. |
| Bitkit/Utilities/PaymentNavigationHelper.swift | Applies the per-payment and daily limits when selecting QuickPay and replaces over-cap QuickPay routes with confirmation. |
| Bitkit/Models/BackupPayloads.swift | Adds backward-compatible optional persistence for the QuickPay ledger. |
| Bitkit/Models/SettingsBackupConfig.swift | Adds cross-platform backup mappings for the QuickPay daily multiplier and ledger. |
| Bitkit/Views/Settings/Quickpay/QuickpaySettings.swift | Adds multiplier controls and displays the resolved daily QuickPay cap. |
| BitkitTests/QuickPayPaymentCoordinatorTests.swift | Covers immediate terminal events, ambiguous dispatch, recovery, reconciliation, and overlapping in-flight operations. |
| BitkitTests/QuickPaySpendStoreTests.swift | Covers reservation, release, daily rollover, persistence, and clock-rollback behavior. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Fixed-amount Lightning request] --> B{QuickPay enabled and per-payment threshold met?}
B -->|No| C[Confirmation and optional PIN]
B -->|Yes| D{Daily spend reservation succeeds?}
D -->|No| C
D -->|Yes| E[Dispatch Lightning payment]
E -->|Success| F[Keep daily spend and show fee-inclusive success]
E -->|Pending| G[Keep reservation and track by payment hash]
G -->|Later success| F
G -->|Later failure| H[Release matching-day reservation]
E -->|Failure| H
H --> I[Show failure and allow retry]
Reviews (4): Last reviewed commit: "fix: update QuickPay daily-limit copy an..." | 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 |
Write and restore quickPayAmount so the per-tx threshold round-trips with the daily multiplier.
Duplicate is NodeError.DuplicatePayment only.
Open Pending for a leftover ledger row instead of sitting on the loader. If noteTerminal already cleared the row after send, push Success. Ambiguous dispatch errors go Pending while the row remains, Failure when it is gone.
Pass feePaidMsat through complete() like Android signalCompletion. Instant failure after send no longer navigates to Success.
Match Android AppCacheData.quickPayLedger. Still decode the three older spend fields if a payload has them and no ledger.
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.node scripts/validate-translations.js: 0 errors.