Skip to content

fix: add quickpay daily spend limit - #1159

Draft
ovitrif wants to merge 45 commits into
masterfrom
fix/require-payment-pin-for-quickpay
Draft

fix: add quickpay daily spend limit#1159
ovitrif wants to merge 45 commits into
masterfrom
fix/require-payment-pin-for-quickpay

Conversation

@ovitrif

@ovitrif ovitrif commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Closes #1168

Builds on merged #1158 (base is master).

iOS port:

QuickPay stays PIN-free under limits (the point of QuickPay). A hard payment-PIN skip would remove that behavior, so this PR bounds auto-pay with a daily spend multiplier instead. Payments above the daily cap open Confirm, where PIN for payments still applies. Lock-time deferral remains in #1158.

Description

  • Keep QuickPay confirmation-free and PIN-free while under the per-tx threshold and daily cap
  • Add a daily limit multiplier on QuickPay settings (1, 3, 5, 10, 50; default 5)
  • Daily cap is threshold × multiplier in USD cents; spend rolls forward on the local calendar day
  • Bind spend to the invoice payment hash before send; settle only through signalCompletion; keep spend on success; release matching-day failure only
  • Over the daily cap, or if reserve fails at pay time → Confirm (replaces QuickPay; payment PIN only if that setting is on)
  • QuickPay success shows the amount with routing fee; Confirm keeps the invoice amount
  • Unlock/lock scan deferral from fix: secure shop payments and locked links #1158
  • Slider: labels included in layout bounds; tap settles from the current value (no jump back to the first on-screen value)
  • Internal architecture: QuickPayRepo is a thin facade over QuickPayCoordinator (sessions, in-flight ops, dispatch). Ledger persistence is QuickPaySpendStore in the same file.

Preview

QuickPay Settings Over Cap → Confirm + PIN
slider.mp4
1159-over-daily-cap-confirm-pin.mp4
Screenshot

QA Notes

Manual Tests

  • 1. Settings → QuickPay: both sliders visible; tap a different stop snaps there without jumping to the first step; page scrolls when dragging vertically from a thumb; resolved daily $ copy updates
  • 2. Unlocked, under per-tx and daily cap, PIN for payments on → scan / paste a small LN invoice: QuickPay then success (no Confirm / payment PIN); success amount includes routing fee
  • 3. After the daily cap is filled → scan another under-threshold invoice: Confirm; swipe can ask for PIN
  • 4. Pay-time reserve miss / overlapping pay: Confirm replaces QuickPay; back does not return to an idle QuickPay loader
  • 5. Hold-invoice QuickPay that later fails: failure UI; a following under-cap invoice still QuickPays
  • 6. Hold-invoice QuickPay that later succeeds: success amount includes fee; spend counts toward the cap
  • 7. Confirm Lightning send (over threshold or QuickPay off) that settles immediately: success amount is the invoice amount
  • 8. Confirm Lightning send through Pending, then success: success amount is still the invoice amount
  • 9. regression: Cold start / locked with PIN → scan stays deferred until unlock (fix: secure shop payments and locked links #1158), then follows the rules above

Automated Checks

  • Unit tests added in QuickPayRepoTest.kt:
    • daily-cap reserveBound
    • matching-day release
    • conversion failure
    • signalCompletion success, failure, and idempotence
    • dual-alias settle
    • inlined iOS/Android ledger decode
    • dispatch-error classification
    • duplicate/ambiguous pending, recovered hash, concurrent same-hash pay
  • Unit tests added in QuickPayViewModelTest.kt:
    • session success, pending, and error mapping
    • pay forwards to the repo
    • stale-session detach
  • Unit tests modified in AppViewModelSendFlowTest.kt:
    • under-cap QuickPay vs over-cap Confirm
    • pending settlement through signalCompletion
  • Unit tests modified in PendingPaymentRepoTest.kt
  • Unit tests modified in SendPendingViewModelTest.kt
  • Instrumented tests modified: daily-limit slider tags in QuickPaySettingsScreenTest.kt
  • CI: standard compile, unit test, and detekt checks run by the PR bot.

@greptile-apps

greptile-apps Bot commented Aug 15, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a persisted USD-denominated daily spending cap to QuickPay while preserving confirmation-free, PIN-free payments below both limits.

  • Adds configurable daily-limit multipliers and updated QuickPay settings UI.
  • Reserves spend before payment and reconciles hash-bound reservations on success or failure.
  • Falls back to the Confirm route when the daily reservation cannot be made.
  • Carries routing fees into QuickPay success amounts and preserves pending resolutions across screen initialization.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains within the eligible follow-up-review scope.

No blocking failure remains.

Important Files Changed

Filename Overview
app/src/main/java/to/bitkit/repositories/QuickPayRepo.kt Introduces persisted daily-spend calculation, atomic reservation, payment-hash binding, and day-aware release and clearing.
app/src/main/java/to/bitkit/viewmodels/QuickPayViewModel.kt Reserves spend before submitting QuickPay, tracks pending payments, handles fee-inclusive success, and falls back to confirmation when reservation fails.
app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt Integrates the daily-cap eligibility check and reconciles bound QuickPay reservations from global payment events.
app/src/main/java/to/bitkit/repositories/PendingPaymentRepo.kt Caches the latest per-hash resolution so the pending screen can recover events received before initialization.
app/src/main/java/to/bitkit/ui/components/Slider.kt Reworks the stepped slider layout, gesture handling, labels, and accessibility semantics for the new settings controls.
app/src/main/java/to/bitkit/ui/settings/quickPay/QuickPaySettingsScreen.kt Adds the daily-limit multiplier control, resolved daily-limit copy, and vertically scrollable settings content.
app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt Replaces QuickPay with Confirm on reservation fallback and forwards fee-inclusive QuickPay amounts into success details.

Sequence Diagram

sequenceDiagram
    participant UI as Send Sheet
    participant QVM as QuickPayViewModel
    participant QPR as QuickPayRepo
    participant LN as LightningRepo
    participant PPR as PendingPaymentRepo
    participant AVM as AppViewModel

    UI->>QPR: canApply(amount)
    alt Under transaction and daily limits
        UI->>QVM: pay(data)
        QVM->>QPR: tryReserve(amount)
        alt Reservation succeeds
            QVM->>LN: payInvoice(invoice)
            LN-->>QVM: paymentHash
            QVM->>QPR: remember(hash, reservation)
            QVM->>PPR: track(hash)
            alt Payment succeeds
                LN-->>AVM: PaymentSuccessful
                AVM->>QPR: clear(hash)
                AVM->>PPR: resolve(Success)
            else Payment fails
                LN-->>AVM: PaymentFailed
                AVM->>QPR: release(hash)
                AVM->>PPR: resolve(Failure)
            end
        else Reservation fails
            QVM-->>UI: FallBackToConfirm
            UI->>UI: Replace QuickPay with Confirm
        end
    else Over a limit
        UI->>UI: Open Confirm
    end
Loading

Reviews (3): Last reviewed commit: "refactor: drop unused quickpay error par..." | Re-trigger Greptile

@ovitrif ovitrif changed the title fix: require payment pin for quickpay fix: add quickpay daily spend limit Aug 15, 2026
Comment thread app/src/main/java/to/bitkit/ui/components/Slider.kt Fixed
@ovitrif
ovitrif force-pushed the fix/require-payment-pin-for-quickpay branch from 0807618 to 2e4a4c0 Compare August 15, 2026 18:28
@ovitrif
ovitrif force-pushed the cursor/fix-shop-quickpay-auth-86ae branch from 32b59a5 to 49ab192 Compare August 15, 2026 18:28
@ovitrif ovitrif self-assigned this Aug 15, 2026
Base automatically changed from cursor/fix-shop-quickpay-auth-86ae to master August 15, 2026 23:02
@ovitrif
ovitrif force-pushed the fix/require-payment-pin-for-quickpay branch from 2e4a4c0 to 7b9ea19 Compare August 15, 2026 23:03
ben-kaufman

This comment was marked as resolved.

@ovitrif
ovitrif dismissed piotr-iohk’s stale review August 20, 2026 16:29

challenged the dust argument as it drifts from the urgency of this patch

@ovitrif

This comment was marked as outdated.

@ovitrif
ovitrif requested a review from ben-kaufman August 20, 2026 18:13
Comment thread app/src/main/java/to/bitkit/repositories/PendingPaymentRepo.kt
Comment thread app/src/main/java/to/bitkit/viewmodels/QuickPayViewModel.kt Outdated
Comment thread app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt
@ovitrif
ovitrif marked this pull request as draft August 20, 2026 19:17
@ovitrif
ovitrif marked this pull request as ready for review August 21, 2026 08:14
@ovitrif
ovitrif requested review from ben-kaufman and jvsena42 and removed request for ben-kaufman and jvsena42 August 21, 2026 08:15
@ovitrif
ovitrif marked this pull request as draft August 21, 2026 08:28
@ovitrif

ovitrif commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

drafted to look into issue flagged by greptile bot on iOS and see if fix needs porting here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: add quickpay daily spend limit

5 participants