Skip to content

sync: merge main into dev — bridge KYC state machine#1949

Closed
kushagrasarathe wants to merge 19 commits into
devfrom
sync/main-to-dev-kyc-state-machine
Closed

sync: merge main into dev — bridge KYC state machine#1949
kushagrasarathe wants to merge 19 commits into
devfrom
sync/main-to-dev-kyc-state-machine

Conversation

@kushagrasarathe

Copy link
Copy Markdown
Contributor

Syncs main into dev to deploy the bridge KYC state machine changes to staging. See #1943 for full details and testing.

kushagrasarathe and others added 18 commits May 6, 2026 23:12
…andling

the bridge KYC state handling in transfer flows (withdraw, deposit, claim, qr-pay)
had multiple issues: wrong priority order, missing ToS checks, redirects instead of
inline flows, and broken rejection handling.

changes:
- new `useBridgeTransferReadiness` hook: unified pre-transfer gate with correct
  priority (hard rejection → tos → fixable rejection → enrollment → ready)
- `useBridgeTosStatus`: expanded to check `tos_acceptance`/`tos_v2_acceptance` in
  rail `additionalRequirements` metadata, not just `REQUIRES_INFORMATION` status
- `InitiateKycModal`: added `blocked` variant (contact support CTA), `error` prop
  for failed self-heal attempts
- withdraw/bank, add-money/bank, AddWithdrawCountriesList: replaced fragmented
  `needsBridgeEnrollment` + `guardWithTos` + `bridgeRejection` checks with unified gate
- BankFlowManager (claim flow): added ToS guard + rejection handling for non-guest paths
- qr-pay: replaced redirect-based KYC (`router.push('/profile/identity-verification')`)
  with inline sumsub SDK initiation (`handleInitiateKyc('LATAM')`)
- BridgeTosStep: show confirmation modal before iframe, prevent modal flash during
  confirmation with `isConfirming` state
- KycProviderRejection, ActivationCTAs, RegionsVerification: replaced broken
  `$crisp.push` calls with `setIsSupportModalOpen`
- useSumsubKycFlow: fixed race condition where `fetchCurrentStatus` closes SDK wrapper
  on first attempt by guarding with `showWrapperRef`
- useProviderRejectionStatus: permanent rejections now show generic support message
  instead of misleading "upload a clearer photo"
- DynamicBankAccountForm: `__silent__` sentinel to prevent form navigation when gate blocks
- close kyc modal via `sumsubFlow.showWrapper` effect instead of in `onVerify` callback
…ata cast, gate fallthrough

- BridgeTosStep: wrap confirmBridgeTosAndAwaitRails in try/catch to prevent
  isConfirming getting stuck on error
- useBridgeTosStatus: use Array.isArray guard for additionalRequirements metadata
- all gate checks: always return when gate is not ready, even if guardWithTos
  returns false (defensive)
…lt, dedup variant mapping

- useSumsubKycFlow: save/restore prevStatusRef on crossRegion failure to prevent
  suppressing subsequent legitimate APPROVED transitions
- DynamicBankAccountForm: replace __silent__ magic string with typed { silent: true }
- useBridgeTransferReadiness: extract getKycModalVariant() and getGateProviderMessage()
  helpers to deduplicate gate→modal mapping across 4 files
- BankFlowManager: only close kyc modal if sdk opened (check showWrapper), preserving
  error visibility on failure
…minate SDK auto-close race

the fetchCurrentStatus effect could still race with handleInitiateKyc in rare
cases — initiatingRef resets in the finally block before React batches the
showWrapper state update. adding userInitiatedRef as a guard permanently
disables the background fetch after any user-initiated flow, since the SDK
and websocket handle status updates from that point.
Users paying with a Pix QR were told to ask the merchant for a Mercado
Pago QR, which is wrong and confusing. Branch the message on qrType so
Pix scans get Pix-specific guidance.

Also capture qr_decoding_error_shown so we can measure how often this
fallback fires and which rails are most affected.
Per CodeRabbit review on #1948: ARGENTINA_QR3 was hitting the default
branch and getting told to ask the merchant for a Mercado Pago QR —
QR3 and Mercado Pago are distinct Argentine standards, so the copy
was actively misleading.

Now branches PIX, ARGENTINA_QR3, and the MP default explicitly.
In Argentina, Mercado Pago is the dominant rail and a workable fallback
when a QR3 code fails to decode — so suggesting "ask for a Mercado Pago
QR" is the most useful guidance for QR3 users too. Only Pix needs the
rail-specific copy because Brazil has no equivalent fallback.

Reverts the previous QR3-specific message; adds a comment explaining
the regional reasoning so future readers don't trip on the same point
CodeRabbit raised.
…hine

fix: bridge KYC state machine — unified gate, inline ToS, rejection handling
Signed-off-by: Juan José Ramírez <70615692+jjramirezn@users.noreply.github.com>
…rror-message

[TASK-19529] fix(qr-pay): Pix-specific copy on QR decoding error + capture event
# Conflicts:
#	src/app/(mobile-ui)/add-money/[country]/bank/page.tsx
#	src/app/(mobile-ui)/qr-pay/page.tsx
#	src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx
#	src/components/AddWithdraw/AddWithdrawCountriesList.tsx
#	src/components/Kyc/BridgeTosStep.tsx
#	src/constants/analytics.consts.ts
@vercel

vercel Bot commented May 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
peanut-wallet Error Error May 7, 2026 2:30pm

Request Review

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR centralizes bridge transfer readiness into a prioritized gate, rewires KYC/TOS flows and support-modal integration across add-money, withdraw, and QR pay pages and related components, expands KYC modal variants and Sumsub flow guards, and adds SimpleFi QR payment handling.

Changes

Bridge Transfer Readiness & KYC Unification

Layer / File(s) Summary
Gate Infrastructure
src/hooks/useBridgeTransferReadiness.ts, src/hooks/useBridgeTosStatus.ts, src/hooks/useProviderRejectionStatus.ts, src/hooks/__tests__/useBridgeTransferReadiness.test.ts
Introduces useBridgeTransferReadiness() with BridgeGateAction and helpers getKycModalVariant() / getGateProviderMessage(). Updates TOS detection and provider-rejection messaging. Adds tests validating priority ordering and variant/message mapping.
KYC Modal & Flow Enhancements
src/components/Kyc/InitiateKycModal.tsx, src/components/Kyc/BridgeTosStep.tsx, src/components/Kyc/states/KycProviderRejection.tsx, src/components/Profile/views/RegionsVerification.view.tsx, src/hooks/useSumsubKycFlow.ts
Expands InitiateKycModal with blocked and cross_region variants, computed CTA behavior, and optional onContactSupport callback. Refactors BridgeTosStep to a single async confirmation flow and tightens useSumsubKycFlow guards. Integrates useModalsContext in rejection/verification views to open support modal.
Add-Money & Withdraw Page Refactoring
src/app/(mobile-ui)/add-money/[country]/bank/page.tsx, src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx
Pages now use useBridgeTransferReadiness gate instead of scattered local KYC/rejection checks. Amount-continue and offramp handlers branch on gate.type to invoke TOS guard, open KYC modal, or proceed. Simplifies confirmation logic, routing, and transaction handling.
Component Integration
src/components/AddWithdraw/AddWithdrawCountriesList.tsx, src/components/Claim/Link/views/BankFlowManager.view.tsx, src/components/AddWithdraw/DynamicBankAccountForm.tsx, src/components/Home/ActivationCTAs.tsx
AddWithdrawCountriesList refactors form submission to use unified gate with BridgeTosStep overlay and gate-driven KYC modal handlers. BankFlowManager applies same gate-based TOS/KYC orchestration. DynamicBankAccountForm adds optional silent flag to suppress displayed errors. ActivationCTAs replaces Crisp calls with useModalsContext.setIsSupportModalOpen.
QR Pay & SimpleFi KYC Wiring
src/app/(mobile-ui)/qr-pay/page.tsx
Rewires QR pay to multi-phase Sumsub flow and SumsubKycModals; CTA handlers call sumsubFlow methods. Adds SimpleFi as a QR payment processor with payment-state and status-update handling. Adjusts loading gating and decoding-error analytics.
Analytics & Assets
src/constants/analytics.consts.ts, src/assets/animations
Adds QR_DECODING_ERROR_SHOWN analytics event and updates animations submodule pinning.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • peanutprotocol/peanut-ui#1943: Implements the same unified useBridgeTransferReadiness gate and gate-driven KYC/TOS handling across add-money/withdraw/qr-pay pages, InitiateKycModal, BridgeTosStep, and support modal integration.
  • peanutprotocol/peanut-ui#1932: Contains overlapping provider-rejection, self-heal, and KYC modal variant changes.
  • peanutprotocol/peanut-ui#1905: Related KYC provider-rejection/self-heal flow updates across hooks, modals, and pages.

Suggested reviewers

  • jjramirezn
  • Hugo0
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'sync: merge main into dev — bridge KYC state machine' clearly and specifically describes the main purpose of the PR: syncing the main branch into dev with bridge KYC state machine changes.
Description check ✅ Passed The description is directly related to the changeset, referencing the bridge KYC state machine sync and linking to issue #1943 for full details and testing context.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 5774.88 → 5761.61 (-13.27)
Findings: +8 net (+115 new, -107 resolved)

🆕 New findings (115)

  • critical complexity — src/app/(mobile-ui)/qr-pay/page.tsx — CC 261, MI 54.07, SLOC 841
  • critical complexity — src/components/AddWithdraw/DynamicBankAccountForm.tsx — CC 134, MI 54.23, SLOC 380
  • critical complexity — src/components/AddWithdraw/AddWithdrawCountriesList.tsx — CC 98, MI 57.59, SLOC 279
  • critical complexity — src/components/Claim/Link/views/BankFlowManager.view.tsx — CC 94, MI 47.93, SLOC 375
  • critical complexity — src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx — CC 84, MI 52.46, SLOC 291
  • critical complexity — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — CC 82, MI 57.84, SLOC 295
  • critical method-complexity — src/app/(mobile-ui)/qr-pay/page.tsx:72 — QRPayPage CC 71 SLOC 304
  • critical complexity — src/hooks/useSumsubKycFlow.ts — CC 67, MI 54.52, SLOC 277
  • critical complexity — src/components/Profile/views/RegionsVerification.view.tsx — CC 51, MI 61.98, SLOC 134
  • high hotspot — src/app/(mobile-ui)/qr-pay/page.tsx — 96 commits, +1336/-1674 lines since 6 months ago
  • high hotspot — src/app/(mobile-ui)/withdraw/manteca/page.tsx — 50 commits, +521/-298 lines since 6 months ago
  • high hotspot — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — 41 commits, +455/-380 lines since 6 months ago
  • high complexity — src/hooks/useProviderRejectionStatus.ts — CC 36, MI 58.19, SLOC 123
  • high method-complexity — src/components/AddWithdraw/DynamicBankAccountForm.tsx:151 — CC 35 SLOC 114
  • high method-complexity — src/components/AddWithdraw/DynamicBankAccountForm.tsx:70 — CC 34 SLOC 152
  • high method-complexity — src/components/Claim/Link/views/BankFlowManager.view.tsx:253 — CC 32 SLOC 104
  • high complexity — src/constants/analytics.consts.ts — CC 1, MI 36.6, SLOC 127
  • medium react-long-component — src/app/(mobile-ui)/qr-pay/page.tsx:72 — QRPayPage is 1303 lines — split it
  • medium react-long-component — src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx:52 — WithdrawBankPage is 432 lines — split it
  • medium react-long-component — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:46 — OnrampBankPage is 398 lines — split it

…and 95 more.

✅ Resolved (107)

  • src/app/(mobile-ui)/qr-pay/page.tsx — CC 259, MI 54.12, SLOC 838
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx — CC 133, MI 54.27, SLOC 379
  • src/components/AddWithdraw/AddWithdrawCountriesList.tsx — CC 98, MI 56.48, SLOC 272
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — CC 90, MI 56.71, SLOC 298
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx — CC 85, MI 51.75, SLOC 293
  • src/components/Claim/Link/views/BankFlowManager.view.tsx — CC 84, MI 46.06, SLOC 333
  • src/app/(mobile-ui)/qr-pay/page.tsx:70 — QRPayPage CC 69 SLOC 301
  • src/hooks/useSumsubKycFlow.ts — CC 63, MI 54.9, SLOC 270
  • src/components/Profile/views/RegionsVerification.view.tsx — CC 53, MI 62.01, SLOC 132
  • src/app/(mobile-ui)/qr-pay/page.tsx — 90 commits, +1168/-1143 lines since 6 months ago
  • src/app/(mobile-ui)/withdraw/manteca/page.tsx — 45 commits, +477/-262 lines since 6 months ago
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — 36 commits, +402/-331 lines since 6 months ago
  • src/hooks/useProviderRejectionStatus.ts — CC 35, MI 58.46, SLOC 120
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx:67 — CC 34 SLOC 152
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx:148 — CC 34 SLOC 113
  • src/components/Claim/Link/views/BankFlowManager.view.tsx:231 — CC 32 SLOC 101
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:43 — OnrampBankPage CC 31 SLOC 143
  • src/constants/analytics.consts.ts — CC 1, MI 36.69, SLOC 126
  • src/app/(mobile-ui)/qr-pay/page.tsx:70 — QRPayPage is 1305 lines — split it
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx:49 — WithdrawBankPage is 430 lines — split it

…and 87 more.

📈 Painscore deltas (top movers)

File Before After Δ
src/hooks/useBridgeTransferReadiness.ts 0.0 6.0 +6.0
src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx 15.0 17.1 +2.1
src/app/(mobile-ui)/add-money/[country]/bank/page.tsx 17.6 18.9 +1.3
src/components/Kyc/InitiateKycModal.tsx 5.7 7.0 +1.2
src/components/AddWithdraw/AddWithdrawCountriesList.tsx 13.7 14.9 +1.2
src/components/Claim/Link/views/BankFlowManager.view.tsx 15.5 16.5 +1.0
src/components/Kyc/BridgeTosStep.tsx 8.4 9.3 +0.9
src/hooks/useBridgeTosStatus.ts 4.7 5.6 +0.9

@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — 🔴 12 failing

Suites

  • 🔴 unit: 915 ran, 12 failed, 0 skipped, 16.1s

🔴 Failing tests

  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › inputAmount step shows amount input and Continue button — 0.06s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › Continue disabled when no amount entered — 0.00s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › unknown country shows EmptyState — 0.00s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › user not KYC approved shows InitiateKycModal on Continue — 0.00s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › KYC approved shows confirmation modal on Continue — 0.00s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › confirmation modal confirm creates onramp and navigates to showDetails — 0.00s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › onramp error displays ErrorAlert — 0.00s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › limits blocking disables Continue and shows LimitsWarningCard — 0.01s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › showDetails step with onrampData shows AddMoneyBankDetails — 0.00s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › showDetails step without onrampData redirects to inputAmount — 0.00s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › Bridge TOS guard shows TOS step — 0.00s
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx › GROUP 5: Bridge Bank Onramp › loading state when user is null and no step — 0.00s

📊 Coverage (unit)

metric %
statements 42.4%
branches 20.3%
functions 21.5%
lines 42.0%
⏱ 10 slowest test cases
time test
0.3s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in updateUserById body
0.3s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in updateUserById
0.2s src/components/Request/__tests__/request-states.test.tsx › renders request form with nav header, action card, QR code, amount input, and create button
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid 9-digit US account
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid US account with spaces 2
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle too long for US account
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid UK IBAN with spaces
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle invalid ETH address (missing 0x prefix)
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle maximum length (17 digits) US account
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid US account with spaces
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@coderabbitai coderabbitai Bot added the enhancement New feature or request label May 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
src/components/Kyc/BridgeTosStep.tsx (1)

60-79: 💤 Low value

Consider retry handling for ToS confirmation failures.

When confirmBridgeTosAndAwaitRails fails (lines 68-69), the error is displayed but the "Try again" button (line 96-97) will call handleAcceptTerms, which fetches the ToS link again rather than retrying the confirmation. Since the user already accepted in the iframe, they'd need to go through the iframe flow again unnecessarily.

This may be acceptable as a rare edge case (network failure during confirmation), but consider whether a dedicated retry for the confirmation step would improve the UX.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Kyc/BridgeTosStep.tsx` around lines 60 - 79, The handler
handleIframeClose currently treats a failed confirmBridgeTosAndAwaitRails as a
generic error and the UI's "Try again" button calls handleAcceptTerms (which
re-opens the iframe); change this by recording that the iframe closed with
source 'tos_accepted' (e.g., store lastTosAccepted boolean or lastCloseSource
state) and implement a retryConfirmBridgeTos function that calls
confirmBridgeTosAndAwaitRails, sets setIsConfirming, and calls
onComplete/onError like the original try/catch; update the "Try again" button
logic to call retryConfirmBridgeTos when lastCloseSource === 'tos_accepted'
(otherwise fall back to handleAcceptTerms), keeping existing state updates
(setShowIframe, setError, setIsConfirming) consistent with handleIframeClose.
src/hooks/__tests__/useBridgeTransferReadiness.test.ts (1)

69-73: 💤 Low value

Consider adding a test case for unapproved Sumsub user.

The current tests cover scenarios where isSumsubApproved: true, but there's no explicit test for when a user hasn't completed Sumsub KYC at all (isSumsubApproved: false, isBridgeApproved: false, no rejections, no TOS needed). The hook would return ready, which may be intentional (letting downstream flows handle initial KYC) but worth documenting with a test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks/__tests__/useBridgeTransferReadiness.test.ts` around lines 69 - 73,
Add a new unit test in useBridgeTransferReadiness.test.ts that calls the
existing setup helper with isSumsubApproved: false and isBridgeApproved: false
(and no rejections/TOS flags), then renders the hook via renderHook(() =>
useBridgeTransferReadiness()) and asserts the expected gate type (e.g.,
expect(result.current.gate.type).toBe('ready')) so the unapproved-Sumsub
scenario is explicitly covered; reference the setup helper, renderHook, and
result.current.gate.type to locate where to add the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(mobile-ui)/qr-pay/page.tsx:
- Line 125: The call to useQrKycGate in page.tsx passes paymentProcessor but the
hook's current signature takes no args; fix by making the call site and hook
signature consistent—either remove the argument from the call in page.tsx
(change const { shouldBlockPay, kycGateState } = useQrKycGate()) or update the
hook definition of useQrKycGate to accept and use the paymentProcessor
parameter; locate the hook implementation named useQrKycGate and the call site
in page.tsx to apply the matching change.
- Around line 39-46: The import failures happen because parseSimpleFiQr, the
SimpleFiQrData type, and the SIMPLEFI_* members of EQrType (used by this file's
SimpleFi branches) are not exported from the DirectSendQR utils; update that
module to re-export parseSimpleFiQr, export the SimpleFiQrData type, and
add/export the EQrType entries for SIMPLEFI_* (or export the full EQrType enum)
so callers can reference EQrType.SIMPLEFI_*. Ensure NAME_BY_QR_TYPE and QrType
remain exported and that parseSimpleFiQr signature matches the consumer usage in
page.tsx (and other locations mentioned).
- Around line 11-12: The imports simplefiApi and SimpleFiQrPaymentResponse from
'@/services/simplefi' are unresolved and break typechecking; until the SimpleFi
service/types are merged, remove the broken imports in page.tsx and replace them
with local stubs: declare a temporary SimpleFiQrPaymentResponse type/interface
matching the minimal fields used in this file and create a local simplefiApi
stub (or lazily import it) that implements only the methods this page calls;
ensure all references in the page use the local stub names so the page builds
and add a TODO comment to revert to '@/services/simplefi' once the service is
merged.
- Around line 1553-1557: The CTA is reading qrPayment!.details.merchant.name
which is null in the SimpleFi success path; update the Button
onClick/router.push call to use the SimpleFi merchant source instead by
replacing qrPayment!.details.merchant.name with the SimpleFi variables (prefer
merchantName or fallback to simpleFiQrData?.merchant?.name) so the URL uses
merchantName ?? simpleFiQrData?.merchant?.name; keep the existing
formatNumberForDisplay usage for amount and ensure the change is applied in the
Button onClick handler that builds the `/request?amount=...&merchant=...` URL.

---

Nitpick comments:
In `@src/components/Kyc/BridgeTosStep.tsx`:
- Around line 60-79: The handler handleIframeClose currently treats a failed
confirmBridgeTosAndAwaitRails as a generic error and the UI's "Try again" button
calls handleAcceptTerms (which re-opens the iframe); change this by recording
that the iframe closed with source 'tos_accepted' (e.g., store lastTosAccepted
boolean or lastCloseSource state) and implement a retryConfirmBridgeTos function
that calls confirmBridgeTosAndAwaitRails, sets setIsConfirming, and calls
onComplete/onError like the original try/catch; update the "Try again" button
logic to call retryConfirmBridgeTos when lastCloseSource === 'tos_accepted'
(otherwise fall back to handleAcceptTerms), keeping existing state updates
(setShowIframe, setError, setIsConfirming) consistent with handleIframeClose.

In `@src/hooks/__tests__/useBridgeTransferReadiness.test.ts`:
- Around line 69-73: Add a new unit test in useBridgeTransferReadiness.test.ts
that calls the existing setup helper with isSumsubApproved: false and
isBridgeApproved: false (and no rejections/TOS flags), then renders the hook via
renderHook(() => useBridgeTransferReadiness()) and asserts the expected gate
type (e.g., expect(result.current.gate.type).toBe('ready')) so the
unapproved-Sumsub scenario is explicitly covered; reference the setup helper,
renderHook, and result.current.gate.type to locate where to add the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d72d9ff3-2e39-4731-8f9a-5f8626a24fbf

📥 Commits

Reviewing files that changed from the base of the PR and between db1a114 and 53cec87.

📒 Files selected for processing (18)
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx
  • src/app/(mobile-ui)/qr-pay/page.tsx
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx
  • src/assets/animations
  • src/components/AddWithdraw/AddWithdrawCountriesList.tsx
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx
  • src/components/Claim/Link/views/BankFlowManager.view.tsx
  • src/components/Home/ActivationCTAs.tsx
  • src/components/Kyc/BridgeTosStep.tsx
  • src/components/Kyc/InitiateKycModal.tsx
  • src/components/Kyc/states/KycProviderRejection.tsx
  • src/components/Profile/views/RegionsVerification.view.tsx
  • src/constants/analytics.consts.ts
  • src/hooks/__tests__/useBridgeTransferReadiness.test.ts
  • src/hooks/useBridgeTosStatus.ts
  • src/hooks/useBridgeTransferReadiness.ts
  • src/hooks/useProviderRejectionStatus.ts
  • src/hooks/useSumsubKycFlow.ts

Comment thread src/app/(mobile-ui)/qr-pay/page.tsx Outdated
Comment thread src/app/(mobile-ui)/qr-pay/page.tsx Outdated
Comment thread src/app/(mobile-ui)/qr-pay/page.tsx Outdated
Comment thread src/app/(mobile-ui)/qr-pay/page.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(mobile-ui)/qr-pay/page.tsx:
- Around line 975-976: The current isLoadingPaymentData expression
short-circuits on !shouldBlockPay and can allow undefined currency to pass
through when shouldBlockPay is true; update the expression in page.tsx
(isLoadingPaymentData) to always treat missing currency as loading (e.g., make
the expression start with !currency || ... or otherwise include a top-level
currency check) so subsequent unguarded reads like currency.price are safe even
when pay is blocked; keep other conditions (isFirstLoad, paymentProcessor,
paymentLock) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1794ec45-ac85-401c-96d3-4343e089d863

📥 Commits

Reviewing files that changed from the base of the PR and between 53cec87 and c248f9e.

📒 Files selected for processing (1)
  • src/app/(mobile-ui)/qr-pay/page.tsx

Comment on lines +975 to +976
const isLoadingPaymentData =
!shouldBlockPay && (isFirstLoad || (paymentProcessor === 'MANTECA' && !paymentLock) || !currency)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prevent fallthrough render with undefined currency when pay is blocked.

At Line 975, isLoadingPaymentData short-circuits on !shouldBlockPay. If shouldBlockPay is true, the page can skip loading while currency is still unset (query is disabled at Line 366), then hit unguarded reads like currency.price in the main render path.

💡 Minimal fix
-    const isLoadingPaymentData =
-        !shouldBlockPay && (isFirstLoad || (paymentProcessor === 'MANTECA' && !paymentLock) || !currency)
+    const isLoadingPaymentData =
+        isFirstLoad || (paymentProcessor === 'MANTECA' && !paymentLock) || !currency
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isLoadingPaymentData =
!shouldBlockPay && (isFirstLoad || (paymentProcessor === 'MANTECA' && !paymentLock) || !currency)
const isLoadingPaymentData =
isFirstLoad || (paymentProcessor === 'MANTECA' && !paymentLock) || !currency
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/qr-pay/page.tsx around lines 975 - 976, The current
isLoadingPaymentData expression short-circuits on !shouldBlockPay and can allow
undefined currency to pass through when shouldBlockPay is true; update the
expression in page.tsx (isLoadingPaymentData) to always treat missing currency
as loading (e.g., make the expression start with !currency || ... or otherwise
include a top-level currency check) so subsequent unguarded reads like
currency.price are safe even when pay is blocked; keep other conditions
(isFirstLoad, paymentProcessor, paymentLock) unchanged.

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants