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 |
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.