TASK-22692: Prepare QR payments early and measure Pay-to-success - #3221
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code-analysis diffPainscore total: 7997.19 → 8021.13 (+23.94) 🆕 New findings (402)
…and 382 more. ✅ Resolved (381)
…and 361 more. 📈 Painscore deltas (top movers)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
|
/chip review |
🖼 Visual diff — 1 screen moved2 of 96 shots changed · 94 identical · baseline
job summary · before/after/diff images — artifact Fixture screenshots, no backend. Advisory — this check never blocks a merge. Posted from the default branch by ds-shots-comment.yml; the report it renders is untrusted data. |
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
No findings.
Findings
- MINOR · src/features/payments/flows/qr-pay/usePerkHoldToClaim.ts:93 · [claude-opus] Reward is celebrated even when the API reports the payout failed
This pair moves the reward transfer off the completion response: the API now returns as soon as the usage is issued and reserved, withpayoutStatus: 'pending' | 'completed' | 'failed'(new field, declared in src/services/manteca.ts:59). The UI readseligibleonly —usePerkHoldToClaim.ts:93gates on!qrPayment.perk?.eligible, andQrPaySuccessView.tsx:71/117render 'You earned a reward!' / 'You earned ${amount}! Hold to claim your reward.' oneligiblealone — so a response carryingpayoutStatus: 'failed'(reachable on a replayed completion for an intent whose payout job already failed terminally) still produces the card, the hold gesture, confetti and areward_claimedcapture. The code comment states this deliberately: 'which this hook neither reads nor requests'.
Product truth says the reward is real money that lands: /home/chip/mono/product/rewards.md — 'Tap to claim, and the reward moves to your spendable balance.' And /home/chip/mono/product/feedback/problems/cashback-wrong-or-missing.md records 'saw cashback on screen but it never credited' as a top support cluster (2026-02-16 discord: 'users report seeing they received cashback on screen but it never reflects in their wallet balance'). Before this change the API only returned a perk after claimPerk succeeded, so the celebration implied the money had already moved; now it does not. The code is the side that is wrong here.
The pending case is fine and is correctly tested — the job pays shortly. The narrow fix: treat perk.payoutStatus === 'failed' as not claimable (same branch as eligible: false), and add the mirror of the existing 'payout still pending' test for a failed payout. Optionally soften the post-reveal copy for pending so the screen does not assert the balance already moved.
Checked clean
- Confirmed the detached worktree head and merge base match the supplied SHAs.
- Reviewed fixed-amount warmup, live strategy routing, nonce/client/lock validation, sponsorship refresh, fallback preparation, and one-shot candidate lifecycle.
- Reviewed QR completion outcomes, attempt telemetry ordering and privacy bounds, durable reward reveal semantics, and the paired generated API contract.
- Core CI gates succeeded at this head; visual capture and ds-shots jobs were still in progress when checked.
Security review by moonshotai/kimi-k3: 0 finding(s), marked with the model name. It reads the diff only and answers only security, privacy and money, so treat its findings as advice.
Third opinion by claude-opus: 1 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.
Exact head: 378a6592f400 · Context: repo, product · Took 23m
|
/chip review |
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
Found one major issue: fixed-amount QR warm-up consumes ZeroDev sponsorship policy before Pay, and the Pay-time refresh consumes it again. The previously raised failed-reward celebration defect is fixed at this head.
Findings
- MAJOR · src/hooks/wallet/useSignUserOp.ts:134 · Warm-up consumes sponsorship before Pay
prepareWithClientruns the real client's fullprepareUserOperation, whose configured paymaster callback invokes ZeroDevsponsorUserOperationwithoutshouldConsume; the pinned SDK defaults that flag totrue. Merely opening a fixed-amount QR therefore consumes one sponsorship-policy use, andreusePreparedUserOpconsumes a second during its Pay-time sponsorship refresh. With per-account or budget policies, abandoned scans drain quota and a later valid payment can be rejected before signing. Prepare with a non-consuming paymaster request (or without final sponsorship), then consume exactly once during the Pay-time refresh.
Checked clean
- Exact detached head, supplied base SHA, merge base, author, and PR metadata
- Failed-reward success UI and hold lifecycle, including pending-to-failed cancellation
- Smart-only, mixed, and collateral routing plus prepared UserOp staleness, nonce, and sponsorship refresh
- QR payment telemetry bounds and terminal outcome paths
- Exact-head CI: unit, typecheck, lint, format, screen tests, native export, and preview passed; screenshot publication alone failed Cloudflare token verification
Security review by moonshotai/kimi-k3: 0 finding(s), marked with the model name. It reads the diff only and answers only security, privacy and money, so treat its findings as advice.
Third opinion by claude-opus: 0 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.
Exact head: d8c41fec9dc8 · Context: repo, dependency · Took 26m
|
/chip review |
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
Both prior findings are fixed at this head; one minor telemetry correctness issue remains.
Findings
- MINOR · src/features/payments/flows/qr-pay/useQrPayFlow.ts:643 · Do not mark pre-signing failures as signature-ready
This catch covers failures before any signature work, but it always emitssignature_ready. For example, an insufficient live balance can make strategy resolution throw beforestrategy_ready, and a session-key grant can fail during preflight; both attempts are then recorded as reaching the signature stage even though they did not. That contradicts the telemetry contract that absent stages are not reported and corrupts the stage funnel. Emit this stage only after signing actually starts, or have the lower layer report the precise failed stage and finish the attempt withoutsignature_readyfor earlier failures.
Checked clean
- Pinned head, supplied base SHA, merge base, trusted author, and dev base all match the request.
- Warm-up sponsorship now carries the preview context through real viem preparation, and ZeroDev SDK 5.5.7 forwards shouldConsume=false without serializing the context into the UserOperation.
- Prepared UserOperations are rejected on client, chain, call, lock-expiry, or nonce drift; the Pay path consumes sponsorship once and propagates uncertain consuming failures without retrying.
- Failed reward payouts suppress the reward offer, hold gesture, confetti, reveal UI, and reward analytics, including a status change during an armed hold.
- Smart-only, mixed, and collateral-only routing, API request shapes, generated contract updates, and payment outcome telemetry were reviewed.
- Completed CI at this head has no failures: unit, typecheck, lint, format, native export, screen tests, preview deployment, and the aggregate ci-success gate passed; visual capture jobs were still running at review time.
Security review by moonshotai/kimi-k3: 0 finding(s), marked with the model name. It reads the diff only and answers only security, privacy and money, so treat its findings as advice.
Third opinion by claude-opus: 0 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.
Exact head: ffecd05c47ee · Context: repo, sdk-source · Took 14m
|
/chip review |
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
No findings at the supplied head.
Checked clean
- P1 is fixed: warm-up uses a per-request non-consuming ZeroDev sponsorship preview, while Pay performs one consuming refresh and propagates uncertain consuming failures.
- P2 is fixed: signature_ready is emitted only after signing_preparation_ready; routing, collateral preflight, and Rain draft failures do not invent a signature stage.
- Reviewed prepared-candidate identity and staleness, live strategy and nonce validation, sponsorship refresh and signing, reward payout-status UI, telemetry stages and attempt IDs, request types, and focused regression tests.
- Verified the split prepare/sign and paymaster-context assumptions against the exact @zerodev/sdk 5.5.7 and viem 2.55.0 package sources.
- Exact-head unit, typecheck, lint, format, native-export, screen, preview, and aggregate CI checks passed; visual capture jobs were still running when checked.
- Checked the canonical Lexicon and Funnels & Rewards v2; the linked Notion task was not shared with the integration and returned object_not_found.
Security review by moonshotai/kimi-k3: 0 finding(s), marked with the model name. It reads the diff only and answers only security, privacy and money, so treat its findings as advice.
Third opinion by claude-opus: 0 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.
Exact head: 2d3db3060417 · Context: repo, notion, provider-sdk · Took 14m
Chip review — no blocking findings — this is not an approvalNo actionable defects found; both prior findings are fixed at this head. Checked clean
Security review by Third opinion by Exact head: |
QR Pay now prepares the unsigned smart-wallet operation while the user reads a fixed-amount payment. At Pay it still checks the live strategy, client, nonce, lock expiry and sponsorship before signing. Stale or failed warmup falls back to a fresh operation; mixed, collateral and open-amount paths retain their live preparation.
Validation: full UI suite, 624 suites / 7,705 passing tests (7 skipped); 237 focused wallet, context and QR state tests after sponsorship review; 74 focused QR flow tests after telemetry review. Typecheck, generated API drift check, full Prettier and ESLint (0 errors, 68 warnings, identical to dev). Production build passes with LOCAL_BUILD=true (Sentry uploads disabled). Hook tests cover no early signature/draft, stale nonce/client, live routing, sponsorship failure, telemetry and confetti. Normal payment and pending-reward layouts and copy stay the same. Failed reward payouts use the existing plain payment-success layout.
Design notes: the candidate is best-effort and only helps when preparation completes before Pay. Sponsorship is refreshed at Pay after the live nonce check. The shared paymaster retains its existing single callback, so this adds no paymaster round trip to normal wallet preparation. Tests exercise the installed viem preparation path and check the consuming request count. The success timing ends at committed client state; it is not screen paint or merchant bank credit. The generated snapshot also catches up two existing backend contracts (residence refusal and username check).
Release with API PR #1617 for TASK-22692. Both changes operate on release without rollout flags. The API request and reward fields are additive. No merge or deployment from this task.
Tracking: TASK-22692. Measurement: QR latency dashboard; new charts await release. Separate rewards/privacy documentation follow-up is recorded on the API PR.
Screenshots:⚠️ No capture of the failed-payout state. Existing screenshot fixtures cannot enter QR payment completion; the separate QR claim-success fixture does not cover this view. Real-view state tests cover failed, failed-after-reveal and pending confetti.
Screenshot capture and ds-shots checks pass. Publishing the screen-library report failed during Cloudflare token verification (job log); this PR does not change the publishing scripts or workflows. Required CI and the Vercel preview pass.