fix: unify all KYC flows through Sumsub via useMultiPhaseKycFlow#1690
fix: unify all KYC flows through Sumsub via useMultiPhaseKycFlow#1690kushagrasarathe merged 11 commits intopeanut-wallet-devfrom
Conversation
kushagrasarathe
commented
Feb 25, 2026
- Delete Bridge iframe integration: useBridgeKycFlow, InitiateBridgeKYCModal
- Delete Manteca widget integration: useMantecaKycFlow, InitiateMantecaKYCModal
- Extract shared useMultiPhaseKycFlow hook + SumsubKycModals component
- Replace all KYC entry points with inline Sumsub flow:
- Bridge bank flows use regionIntent: 'STANDARD'
- Manteca flows use regionIntent: 'LATAM'
- Add polling fallback in useSumsubKycFlow for missed WebSocket events
- Relocate KycHistoryEntry type + isKycStatusItem guard to KycStatusItem
- Net reduction: ~970 lines
- Delete Bridge iframe integration: useBridgeKycFlow, InitiateBridgeKYCModal - Delete Manteca widget integration: useMantecaKycFlow, InitiateMantecaKYCModal - Extract shared useMultiPhaseKycFlow hook + SumsubKycModals component - Replace all KYC entry points with inline Sumsub flow: - Bridge bank flows use regionIntent: 'STANDARD' - Manteca flows use regionIntent: 'LATAM' - Add polling fallback in useSumsubKycFlow for missed WebSocket events - Relocate KycHistoryEntry type + isKycStatusItem guard to KycStatusItem - Net reduction: ~970 lines Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughReplaces provider‑specific KYC hooks/modals with a unified multi‑phase Sumsub KYC flow: adds Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
When user clicks "Accept terms of service" from the activity feed, auto-fetch the ToS link and open the iframe directly instead of showing a redundant "Accept Terms" confirmation modal first. The modal now only appears as an error fallback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (4)
src/components/AddMoney/components/MantecaAddMoney.tsx (1)
67-70: NoonKycSuccessoronManualClosecallbacks — user gets no post-KYC feedback.The
sumsubFlowis created withoutonKycSuccessoronManualClose. After KYC completes,completeFlow()in the hook will reset internal state but won't trigger any UI transition in this component. The user will return to the amount input step with no toast, modal, or visual confirmation that verification succeeded.If this is intentional (user just continues filling the form), it works because
isUserMantecaKycApprovedwill update after the hook's internalfetchUser(). But it may feel abrupt to the user.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/AddMoney/components/MantecaAddMoney.tsx` around lines 67 - 70, The sumsubFlow created by useMultiPhaseKycFlow lacks onKycSuccess and onManualClose handlers so users receive no post-KYC feedback; add onKycSuccess to call completeFlow(), trigger a success toast/modal (or advance to the next UI step) and refresh or re-fetch user state (so isUserMantecaKycApproved updates immediately), and add onManualClose to gracefully close the KYC UI and show a cancellation/next-step hint; update the sumsubFlow instantiation to include onKycSuccess and onManualClose callbacks that perform these actions.src/components/Profile/views/RegionsVerification.view.tsx (1)
175-177: Error display rendered outside the drawer/modal hierarchy.The
flow.errorparagraph (line 175) renders at the bottom of the page layout, below all modals. If the error occurs while a modal is open (e.g.,StartVerificationModal), the user won't see it since it's behind the modal overlay. Consider displaying the error inside the relevant modal or as a toast.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/Profile/views/RegionsVerification.view.tsx` around lines 175 - 177, The error paragraph currently renders outside modal hierarchy so it's hidden behind overlays; remove the external "{flow.error}" <p> and instead surface errors inside the modal component or via the app toast system: pass the error down to SumsubKycModals (e.g., add an error prop like error={flow.error}) or into the specific modal component such as StartVerificationModal, and render the message within that modal's markup (or call the toast helper from where flow.error is set) so users see it while a modal is open.src/app/(mobile-ui)/withdraw/manteca/page.tsx (1)
190-193: KYC guard returns early without user feedback.When
!isUserMantecaKycApproved, the handler callssumsubFlow.handleInitiateKyc()and returns. The Sumsub SDK will open, which serves as implicit feedback. After successful KYC the user needs to click "Review" again — consider whether a brief toast or inline message would improve the UX, but this is a minor polish item.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(mobile-ui)/withdraw/manteca/page.tsx around lines 190 - 193, The guard for isUserMantecaKycApproved returns immediately after calling sumsubFlow.handleInitiateKyc(), leaving no explicit user feedback; update the handler (the function that calls sumsubFlow.handleInitiateKyc()) to show a brief UI feedback before returning — e.g., trigger your existing toast/notification helper (or set a local state flag to render an inline message) saying something like "KYC flow launched — please complete verification and tap Review again", then call sumsubFlow.handleInitiateKyc() and return; reference isUserMantecaKycApproved and sumsubFlow.handleInitiateKyc() to locate where to add the notification.src/components/AddWithdraw/AddWithdrawCountriesList.tsx (1)
64-64: Remove unusedisKycModalOpenstate.The state is only written to (lines 56, 59, 290) but never read. After migrating to the new KYC modal system, this state became obsolete and should be cleaned up along with its setter calls.
♻️ Remove dead state
- const [isKycModalOpen, setIsKycModalOpen] = useState(false)Remove the setter calls from:
- Line 56:
onKycSuccesscallback insumsubFlow- Line 59:
onManualClosecallback insumsubFlow- Line 290:
NavHeaderonPrevhandler🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/AddWithdraw/AddWithdrawCountriesList.tsx` at line 64, Remove the dead React state isKycModalOpen and its setter setIsKycModalOpen from AddWithdrawCountriesList: delete the useState declaration and remove all invocations of setIsKycModalOpen in the sumsubFlow callbacks (onKycSuccess and onManualClose) and the NavHeader onPrev handler so the component no longer writes to a nonexistent/unused state; keep existing KYC modal integration logic (sumsubFlow, NavHeader handlers) intact otherwise.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/Kyc/SumsubKycModals.tsx`:
- Around line 18-46: SumsubKycModals currently can render nothing when KYC
initiation fails; add a visible error surface that displays flow.error whenever
flow.error is set and both flow.showWrapper and flow.isModalOpen are false so
callers get feedback. Implement this by conditionally rendering an error block
inside SumsubKycModals (e.g., a small Alert or div) when flow.error &&
!flow.showWrapper && !flow.isModalOpen, show the error text and provide actions
that call existing handlers like flow.refreshToken for "Retry" and
flow.handleSdkClose or flow.handleModalClose for "Dismiss"/close, ensuring the
UI is consistent with the other modal flows.
In `@src/hooks/useMultiPhaseKycFlow.ts`:
- Around line 84-89: The flow enters the 'bridge_tos' modal phase without
starting rail tracking, which can leave the phase stuck; update the
useMultiPhaseKycFlow effect so that when you setModalPhase('bridge_tos') (where
setForceShowModal(true) and clearPreparingTimer() are called) you also call
startTracking() immediately; apply the same change to the other branch
referenced around lines 167-185 so any transition into 'bridge_tos' always
invokes startTracking(), ensuring the rail-status watcher in SumsubKycFlow
resumes and drives subsequent phase transitions.
In `@src/hooks/useSumsubKycFlow.ts`:
- Around line 89-104: The polling function pollStatus can overlap because
setInterval fires regardless of async completion; change polling to serialize
requests by introducing a guard (e.g., isPollingRef or a local boolean) or
convert to a self-scheduling loop using await + setTimeout so you only call
initiateSumsubKyc when the previous call finished; update references to
initiateSumsubKyc, regionIntentRef, levelNameRef and setLiveKycStatus
accordingly and ensure you still clear the timeout/interval on cleanup to avoid
leaks.
---
Nitpick comments:
In `@src/app/`(mobile-ui)/withdraw/manteca/page.tsx:
- Around line 190-193: The guard for isUserMantecaKycApproved returns
immediately after calling sumsubFlow.handleInitiateKyc(), leaving no explicit
user feedback; update the handler (the function that calls
sumsubFlow.handleInitiateKyc()) to show a brief UI feedback before returning —
e.g., trigger your existing toast/notification helper (or set a local state flag
to render an inline message) saying something like "KYC flow launched — please
complete verification and tap Review again", then call
sumsubFlow.handleInitiateKyc() and return; reference isUserMantecaKycApproved
and sumsubFlow.handleInitiateKyc() to locate where to add the notification.
In `@src/components/AddMoney/components/MantecaAddMoney.tsx`:
- Around line 67-70: The sumsubFlow created by useMultiPhaseKycFlow lacks
onKycSuccess and onManualClose handlers so users receive no post-KYC feedback;
add onKycSuccess to call completeFlow(), trigger a success toast/modal (or
advance to the next UI step) and refresh or re-fetch user state (so
isUserMantecaKycApproved updates immediately), and add onManualClose to
gracefully close the KYC UI and show a cancellation/next-step hint; update the
sumsubFlow instantiation to include onKycSuccess and onManualClose callbacks
that perform these actions.
In `@src/components/AddWithdraw/AddWithdrawCountriesList.tsx`:
- Line 64: Remove the dead React state isKycModalOpen and its setter
setIsKycModalOpen from AddWithdrawCountriesList: delete the useState declaration
and remove all invocations of setIsKycModalOpen in the sumsubFlow callbacks
(onKycSuccess and onManualClose) and the NavHeader onPrev handler so the
component no longer writes to a nonexistent/unused state; keep existing KYC
modal integration logic (sumsubFlow, NavHeader handlers) intact otherwise.
In `@src/components/Profile/views/RegionsVerification.view.tsx`:
- Around line 175-177: The error paragraph currently renders outside modal
hierarchy so it's hidden behind overlays; remove the external "{flow.error}" <p>
and instead surface errors inside the modal component or via the app toast
system: pass the error down to SumsubKycModals (e.g., add an error prop like
error={flow.error}) or into the specific modal component such as
StartVerificationModal, and render the message within that modal's markup (or
call the toast helper from where flow.error is set) so users see it while a
modal is open.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
src/app/(mobile-ui)/add-money/[country]/bank/page.tsxsrc/app/(mobile-ui)/history/page.tsxsrc/app/(mobile-ui)/withdraw/manteca/page.tsxsrc/components/AddMoney/components/MantecaAddMoney.tsxsrc/components/AddWithdraw/AddWithdrawCountriesList.tsxsrc/components/Claim/Link/MantecaFlowManager.tsxsrc/components/Claim/Link/views/BankFlowManager.view.tsxsrc/components/Home/HomeHistory.tsxsrc/components/Kyc/InitiateBridgeKYCModal.tsxsrc/components/Kyc/InitiateMantecaKYCModal.tsxsrc/components/Kyc/KycStatusDrawer.tsxsrc/components/Kyc/KycStatusItem.tsxsrc/components/Kyc/SumsubKycFlow.tsxsrc/components/Kyc/SumsubKycModals.tsxsrc/components/Profile/views/RegionsVerification.view.tsxsrc/hooks/useBridgeKycFlow.tssrc/hooks/useMantecaKycFlow.tssrc/hooks/useMultiPhaseKycFlow.tssrc/hooks/useSumsubKycFlow.ts
💤 Files with no reviewable changes (4)
- src/hooks/useBridgeKycFlow.ts
- src/components/Kyc/InitiateMantecaKYCModal.tsx
- src/components/Kyc/InitiateBridgeKYCModal.tsx
- src/hooks/useMantecaKycFlow.ts
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/Kyc/BridgeTosStep.tsx (1)
96-126:⚠️ Potential issue | 🟡 Minor
isLoadingis tracked but never surfaced — blank render during initial fetch.When
visibleflips totrueandhandleAcceptTermsis in-flight (isLoading=true,error=null,tosLink=null,showIframe=false), both conditional branches evaluate tofalseand the component renders an empty fragment. There is no spinner, skeleton, or any visual cue for the user until either the iframe appears or an error is shown.💡 Suggested fix — render a loading state
return ( <> + {isLoading && !showIframe && ( + <ActionModal + visible={true} + onClose={onSkip} + icon={'clock' as IconName} + title="Loading terms…" + description="Please wait while we fetch the terms of service." + ctas={[]} + /> + )} {/* only show modal on error — normal flow goes straight to iframe */} {error && !showIframe && (🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/Kyc/BridgeTosStep.tsx` around lines 96 - 126, The component currently renders nothing when isLoading is true because neither the error modal nor the iframe are shown; update the JSX in BridgeTosStep (the render that uses error, showIframe, tosLink, isLoading, ActionModal, and IframeWrapper) to render a loading UI when isLoading is true — for example show a spinner/skeleton or a disabled ActionModal/placeholder with a message while handleAcceptTerms is in-flight; ensure the loading state appears before tosLink or error are set and keep existing onSkip and handleIframeClose behavior unchanged.
🧹 Nitpick comments (1)
src/components/Kyc/BridgeTosStep.tsx (1)
27-35: HoisthandleAcceptTermsabove theuseEffectto eliminate theeslint-disable.The
useEffecton line 27 callshandleAcceptTerms, which isconst-declared five lines later (line 37). This is safe at runtime (the effect callback executes after the full render, past the TDZ), but it forces theeslint-disable-line react-hooks/exhaustive-depscomment. Moving theuseCallbackdeclaration before theuseEffectallowshandleAcceptTermsto be listed in the dependency array cleanly.♻️ Proposed reorder
+ const handleAcceptTerms = useCallback(async () => { + setIsLoading(true) + setError(null) + try { + const response = await getBridgeTosLink() + if (response.error || !response.data?.tosLink) { + setError(response.error || 'Could not load terms. You can accept them later from your activity feed.') + return + } + setTosLink(response.data.tosLink) + setShowIframe(true) + } catch { + setError('Something went wrong. You can accept terms later from your activity feed.') + } finally { + setIsLoading(false) + } + }, []) + // auto-fetch ToS link when step becomes visible so the iframe opens directly // (skips the intermediate "Accept Terms" confirmation modal) useEffect(() => { if (visible) { handleAcceptTerms() } else { setShowIframe(false) setTosLink(null) setError(null) } - }, [visible]) // eslint-disable-line react-hooks/exhaustive-deps + }, [visible, handleAcceptTerms]) - - const handleAcceptTerms = useCallback(async () => { - ... - }, [])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/Kyc/BridgeTosStep.tsx` around lines 27 - 35, The effect calls handleAcceptTerms before its declaration which forced an eslint-disable; move the handleAcceptTerms useCallback declaration above the useEffect so you can add handleAcceptTerms to the dependency array (remove the eslint-disable-line), and ensure handleAcceptTerms' own dependency array includes any values it reads (e.g., setShowIframe, setTosLink, setError, visible or other referenced state/props) so the hook dependencies are correct.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@src/components/Kyc/BridgeTosStep.tsx`:
- Around line 96-126: The component currently renders nothing when isLoading is
true because neither the error modal nor the iframe are shown; update the JSX in
BridgeTosStep (the render that uses error, showIframe, tosLink, isLoading,
ActionModal, and IframeWrapper) to render a loading UI when isLoading is true —
for example show a spinner/skeleton or a disabled ActionModal/placeholder with a
message while handleAcceptTerms is in-flight; ensure the loading state appears
before tosLink or error are set and keep existing onSkip and handleIframeClose
behavior unchanged.
---
Nitpick comments:
In `@src/components/Kyc/BridgeTosStep.tsx`:
- Around line 27-35: The effect calls handleAcceptTerms before its declaration
which forced an eslint-disable; move the handleAcceptTerms useCallback
declaration above the useEffect so you can add handleAcceptTerms to the
dependency array (remove the eslint-disable-line), and ensure handleAcceptTerms'
own dependency array includes any values it reads (e.g., setShowIframe,
setTosLink, setError, visible or other referenced state/props) so the hook
dependencies are correct.
…on mount
- Add InitiateKycModal shown before opening Sumsub SDK in Manteca flows
- Remove regionIntent from hook initialization in all consumers to prevent
useSumsubKycFlow from calling initiateSumsubKyc() on mount (which created
backend UserKycVerification records even when user never started KYC)
- Pass regionIntent at call time: handleInitiateKyc('LATAM'/'STANDARD')
Fixes: KYC auto-opening without confirmation, phantom pending KYC entries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/AddMoney/components/MantecaAddMoney.tsx (1)
1-225:⚠️ Potential issue | 🟡 MinorFormatting check is failing for this file.
CI reports style issues here. Please run Prettier and commit the formatted output before merge.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/AddMoney/components/MantecaAddMoney.tsx` around lines 1 - 225, Formatting in MantecaAddMoney.tsx is failing CI; run your project's Prettier configuration and reformat this file (MantecaAddMoney component) then commit the changes so the style checks pass. Specifically, run the project's formatting script (e.g., npm/yarn prettier or the configured format command), ensure the file containing the MantecaAddMoney component and its imports/JSX are reformatted, and re-run CI/lint to confirm the formatting error is resolved before merging.
🧹 Nitpick comments (2)
src/app/(mobile-ui)/add-money/[country]/bank/page.tsx (1)
59-59: Remove obsolete local KYC modal state/handlers.
isKycModalOpen,handleKycSuccess, andhandleKycModalCloseare no longer part of the active modal rendering path after the Sumsub flow migration.Also applies to: 77-82, 278-285
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(mobile-ui)/add-money/[country]/bank/page.tsx at line 59, Remove the obsolete local KYC modal state and handlers: delete the useState declaration for isKycModalOpen and the functions handleKycSuccess and handleKycModalClose from the component (they are no longer used after the Sumsub flow migration), and remove any JSX or props that reference these symbols (e.g., KYC modal component props or event handlers). Ensure you also remove any related imports or variables that become unused as a result and run a quick type/lint check to clean up leftover references to isKycModalOpen, handleKycSuccess, and handleKycModalClose.src/components/AddWithdraw/AddWithdrawCountriesList.tsx (1)
56-61: Consider removing leftoverisKycModalOpenstate.This local state no longer controls modal rendering in the new flow and now adds noise to the component logic.
Also applies to: 65-65
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/AddWithdraw/AddWithdrawCountriesList.tsx` around lines 56 - 61, Remove the now-unused local state isKycModalOpen and its setter setIsKycModalOpen from the component; delete the useState declaration and every usage (including in the onKycSuccess and onManualClose callbacks) and instead rely solely on the new flow control (e.g., setView('form') inside onKycSuccess). Update onKycSuccess to only call setView('form') and onManualClose to perform the new flow-specific close behavior (or be removed if redundant), and ensure no props or JSX still reference isKycModalOpen or setIsKycModalOpen.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/Claim/Link/MantecaFlowManager.tsx`:
- Around line 44-48: The useEffect currently only opens the KYC modal when
isUserMantecaKycApproved is false and never closes it when approval changes;
update the effect that references isUserMantecaKycApproved to set the modal
state to the boolean inverse of the approval status (e.g., call
setShowKycModal(!isUserMantecaKycApproved)) so showKycModal stays synchronized
in both directions; touch the useEffect that uses isUserMantecaKycApproved and
the setShowKycModal state updater to implement this change.
---
Outside diff comments:
In `@src/components/AddMoney/components/MantecaAddMoney.tsx`:
- Around line 1-225: Formatting in MantecaAddMoney.tsx is failing CI; run your
project's Prettier configuration and reformat this file (MantecaAddMoney
component) then commit the changes so the style checks pass. Specifically, run
the project's formatting script (e.g., npm/yarn prettier or the configured
format command), ensure the file containing the MantecaAddMoney component and
its imports/JSX are reformatted, and re-run CI/lint to confirm the formatting
error is resolved before merging.
---
Nitpick comments:
In `@src/app/`(mobile-ui)/add-money/[country]/bank/page.tsx:
- Line 59: Remove the obsolete local KYC modal state and handlers: delete the
useState declaration for isKycModalOpen and the functions handleKycSuccess and
handleKycModalClose from the component (they are no longer used after the Sumsub
flow migration), and remove any JSX or props that reference these symbols (e.g.,
KYC modal component props or event handlers). Ensure you also remove any related
imports or variables that become unused as a result and run a quick type/lint
check to clean up leftover references to isKycModalOpen, handleKycSuccess, and
handleKycModalClose.
In `@src/components/AddWithdraw/AddWithdrawCountriesList.tsx`:
- Around line 56-61: Remove the now-unused local state isKycModalOpen and its
setter setIsKycModalOpen from the component; delete the useState declaration and
every usage (including in the onKycSuccess and onManualClose callbacks) and
instead rely solely on the new flow control (e.g., setView('form') inside
onKycSuccess). Update onKycSuccess to only call setView('form') and
onManualClose to perform the new flow-specific close behavior (or be removed if
redundant), and ensure no props or JSX still reference isKycModalOpen or
setIsKycModalOpen.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/app/(mobile-ui)/add-money/[country]/bank/page.tsxsrc/app/(mobile-ui)/withdraw/manteca/page.tsxsrc/components/AddMoney/components/MantecaAddMoney.tsxsrc/components/AddWithdraw/AddWithdrawCountriesList.tsxsrc/components/Claim/Link/MantecaFlowManager.tsxsrc/components/Claim/Link/views/BankFlowManager.view.tsxsrc/components/Kyc/InitiateKycModal.tsx
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/AddMoney/components/MantecaAddMoney.tsx`:
- Around line 196-199: In onVerify handler (the onVerify prop in
MantecaAddMoney), don't call setShowKycModal(false) before starting KYC;
instead, first await sumsubFlow.handleInitiateKyc('LATAM'), check for success
(or catch errors), and only call setShowKycModal(false) after a successful
initiation; on failure keep the modal open and surface an error (e.g., set an
error state or show toast). Reference: onVerify handler, setShowKycModal, and
sumsubFlow.handleInitiateKyc.
- Remove collectUserDetails step from bridge bank onramp flow (page.tsx) Non-KYC'd users now go directly to KYC step - Remove updateUserById calls for name/email before handleInitiateKyc in AddWithdrawCountriesList and BankFlowManager - Sumsub SDK now collects name and email, backend fills them in DB Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/Claim/Link/views/BankFlowManager.view.tsx (1)
69-70:⚠️ Potential issue | 🟡 MinorRemove the unused destructure of
showVerificationModal; keepsetShowVerificationModalcalls as they properly communicate state to parent components.
showVerificationModal(destructured asisKycModalOpen) is never read withinBankFlowManager, so the destructure can be removed. However,setShowVerificationModal(aliased assetIsKycModalOpen) is correctly used in bothonKycSuccessandonManualCloseto signal to parent components that the KYC modal should close. Keep the setter calls and remove only the unused state variable destructure.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/Claim/Link/views/BankFlowManager.view.tsx` around lines 69 - 70, In BankFlowManager remove the unused destructure showVerificationModal (aliased as isKycModalOpen) from the props but keep the setter; keep setShowVerificationModal (aliased as setIsKycModalOpen) intact since it’s used in onKycSuccess and onManualClose to notify parents — update the component props/destructure to only pull setIsKycModalOpen and remove isKycModalOpen references.src/app/(mobile-ui)/add-money/[country]/bank/page.tsx (1)
1-1:⚠️ Potential issue | 🟡 MinorNext.js version
16.0.10does not exist — verify the pinned version.The library context lists
next@16.0.10, which is not a valid release. As of February 2026, the latest stable versions are v15.5.12 (main stable line) and v16.1.6 (16.x Active LTS line). If thepackage.jsonpins Next.js to 16.x, confirm that the intended version is v16.1.6 or another valid release in that line.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(mobile-ui)/add-money/[country]/bank/page.tsx at line 1, The project lists an invalid Next.js version "next@16.0.10"; open package.json and update the "next" dependency (and any lockfile or package-resolutions) to a valid release in the 16.x line (for example "16.1.6") or to the correct intended version, then run your package manager (npm/yarn/pnpm) to regenerate the lockfile and verify no other files (e.g., package-lock.json, yarn.lock, pnpm-lock.yaml) still reference 16.0.10; ensure package.json's "dependencies.next" and any CI/engine/version checks are consistent.
🧹 Nitpick comments (4)
src/components/Claim/Link/views/BankFlowManager.view.tsx (1)
83-92:onKycSuccessinline function causes unnecessary churn insideuseMultiPhaseKycFlow.Because
onKycSuccessis an unstabilized inline async arrow (nouseCallback),useMultiPhaseKycFlow.completeFlow— which listsonKycSuccessin itsuseCallbackdependency array — is recreated on every render ofBankFlowManager. This cascades to every callback that depends oncompleteFlowinside the hook (handleSumsubApproved,handleSkipTerms,handleModalClose).♻️ Proposed fix
+ const handleKycSuccess = useCallback(async () => { + if (justCompletedKyc) return + setIsKycModalOpen(false) + await fetchUser() + setJustCompletedKyc(true) + setClaimBankFlowStep(ClaimBankFlowStep.BankDetailsForm) + }, [justCompletedKyc, fetchUser, setIsKycModalOpen, setJustCompletedKyc, setClaimBankFlowStep]) + const sumsubFlow = useMultiPhaseKycFlow({ - onKycSuccess: async () => { - if (justCompletedKyc) return - setIsKycModalOpen(false) - await fetchUser() - setJustCompletedKyc(true) - setClaimBankFlowStep(ClaimBankFlowStep.BankDetailsForm) - }, - onManualClose: () => setIsKycModalOpen(false), + onKycSuccess: handleKycSuccess, + onManualClose: () => setIsKycModalOpen(false), })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/Claim/Link/views/BankFlowManager.view.tsx` around lines 83 - 92, The inline async onKycSuccess passed into useMultiPhaseKycFlow inside BankFlowManager causes unstable references and forces recreate of useMultiPhaseKycFlow.completeFlow and its dependents (handleSumsubApproved, handleSkipTerms, handleModalClose); refactor onKycSuccess into a stable callback using useCallback (e.g., define const onKycSuccess = useCallback(async () => { if (justCompletedKyc) return; setIsKycModalOpen(false); await fetchUser(); setJustCompletedKyc(true); setClaimBankFlowStep(ClaimBankFlowStep.BankDetailsForm); }, [justCompletedKyc, fetchUser, setIsKycModalOpen, setJustCompletedKyc, setClaimBankFlowStep]) and pass that to useMultiPhaseKycFlow so completeFlow and downstream callbacks stop being recreated on every render.src/app/(mobile-ui)/add-money/[country]/bank/page.tsx (3)
174-178: Document the WebSocket fallback intent to clarify why two KYC-completion paths coexist.Both
onKycSuccess(lines 68–70) and this effect advance the step to'inputAmount'on KYC approval. The duplication is intentional (SDK event vs. WebSocket update as fallback for missed events), but a brief comment prevents future readers from treating one path as dead code.♻️ Suggested clarifying comment
+ // Fallback: advance past KYC via WebSocket status update in case the + // Sumsub SDK success event (onKycSuccess above) was missed or delayed. useEffect(() => { if (urlState.step === 'kyc' && liveKycStatus === 'approved') { setUrlState({ step: 'inputAmount' }) } }, [liveKycStatus, urlState.step, setUrlState])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(mobile-ui)/add-money/[country]/bank/page.tsx around lines 174 - 178, Add a short inline comment above the useEffect that checks liveKycStatus (the effect that updates urlState via setUrlState when urlState.step === 'kyc' and liveKycStatus === 'approved') explaining that this is a WebSocket-based fallback to advance the flow when the SDK callback onKycSuccess may be missed; clarify that both onKycSuccess and this useEffect are intentional and complementary (SDK event vs. WS update) to avoid future removal as dead code.
174-178: Duplicate KYC-completion advance — consider consolidating.Both
onKycSuccess(lines 68–70) and thisuseEffectadvance the step to'inputAmount'when KYC succeeds.onKycSuccesshandles the Sumsub SDK success event; this effect handles the WebSocketliveKycStatusupdate. The WebSocket path is a useful fallback for missed SDK events, but the intent is clearer if a comment documents it as such.♻️ Suggested clarifying comment
+ // Fallback: advance past KYC via WebSocket status update in case the + // Sumsub SDK success event (onKycSuccess) was missed. useEffect(() => { if (urlState.step === 'kyc' && liveKycStatus === 'approved') { setUrlState({ step: 'inputAmount' }) } }, [liveKycStatus, urlState.step, setUrlState])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(mobile-ui)/add-money/[country]/bank/page.tsx around lines 174 - 178, The effect watching liveKycStatus duplicates the step-advance already handled by onKycSuccess; update the useEffect (the block that checks if urlState.step === 'kyc' && liveKycStatus === 'approved' and calls setUrlState({ step: 'inputAmount' })) to include a concise comment stating it's a fallback for missed Sumsub SDK events (i.e., WebSocket-driven fallback) so intent is clear, and keep the logic as-is to preserve robustness; reference onKycSuccess, liveKycStatus, urlState.step and setUrlState when adding the comment.
274-278:eslint-disablemasks a real missing dependency — memoizehandleInitiateKycin the hook or add it to deps.
sumsubFlow.handleInitiateKycis called inside the effect but omitted from the dependency array with// eslint-disable-line react-hooks/exhaustive-deps. IfuseMultiPhaseKycFlowdoesn't wraphandleInitiateKycinuseCallback, every render produces a new function reference and the effect captures a stale one (never re-runs to pick it up since onlyurlState.stepis watched).The lint suppression should be removed in favor of either:
- ensuring
handleInitiateKycis a stableuseCallbackinsideuseMultiPhaseKycFlowand adding it to deps, or- memoizing the callback at the call site before passing it in.
♻️ Proposed fix
- useEffect(() => { - if (urlState.step === 'kyc') { - sumsubFlow.handleInitiateKyc('STANDARD') - } - }, [urlState.step]) // eslint-disable-line react-hooks/exhaustive-deps + useEffect(() => { + if (urlState.step === 'kyc') { + sumsubFlow.handleInitiateKyc('STANDARD') + } + }, [urlState.step, sumsubFlow.handleInitiateKyc])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(mobile-ui)/add-money/[country]/bank/page.tsx around lines 274 - 278, The effect is suppressing a real dependency: remove the "// eslint-disable-line react-hooks/exhaustive-deps" and ensure the function reference is stable by either (A) updating useMultiPhaseKycFlow to wrap sumsubFlow.handleInitiateKyc in useCallback so it can be safely added to the effect deps, or (B) memoizing handleInitiateKyc at the call site (e.g., const initiate = useCallback(() => sumsubFlow.handleInitiateKyc('STANDARD'), [sumsubFlow]) ) and then change the effect to depend on urlState.step and the stable function; reference sumsubFlow.handleInitiateKyc and the useEffect that currently reads urlState.step to apply the fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@src/app/`(mobile-ui)/add-money/[country]/bank/page.tsx:
- Line 1: The project lists an invalid Next.js version "next@16.0.10"; open
package.json and update the "next" dependency (and any lockfile or
package-resolutions) to a valid release in the 16.x line (for example "16.1.6")
or to the correct intended version, then run your package manager
(npm/yarn/pnpm) to regenerate the lockfile and verify no other files (e.g.,
package-lock.json, yarn.lock, pnpm-lock.yaml) still reference 16.0.10; ensure
package.json's "dependencies.next" and any CI/engine/version checks are
consistent.
In `@src/components/Claim/Link/views/BankFlowManager.view.tsx`:
- Around line 69-70: In BankFlowManager remove the unused destructure
showVerificationModal (aliased as isKycModalOpen) from the props but keep the
setter; keep setShowVerificationModal (aliased as setIsKycModalOpen) intact
since it’s used in onKycSuccess and onManualClose to notify parents — update the
component props/destructure to only pull setIsKycModalOpen and remove
isKycModalOpen references.
---
Nitpick comments:
In `@src/app/`(mobile-ui)/add-money/[country]/bank/page.tsx:
- Around line 174-178: Add a short inline comment above the useEffect that
checks liveKycStatus (the effect that updates urlState via setUrlState when
urlState.step === 'kyc' and liveKycStatus === 'approved') explaining that this
is a WebSocket-based fallback to advance the flow when the SDK callback
onKycSuccess may be missed; clarify that both onKycSuccess and this useEffect
are intentional and complementary (SDK event vs. WS update) to avoid future
removal as dead code.
- Around line 174-178: The effect watching liveKycStatus duplicates the
step-advance already handled by onKycSuccess; update the useEffect (the block
that checks if urlState.step === 'kyc' && liveKycStatus === 'approved' and calls
setUrlState({ step: 'inputAmount' })) to include a concise comment stating it's
a fallback for missed Sumsub SDK events (i.e., WebSocket-driven fallback) so
intent is clear, and keep the logic as-is to preserve robustness; reference
onKycSuccess, liveKycStatus, urlState.step and setUrlState when adding the
comment.
- Around line 274-278: The effect is suppressing a real dependency: remove the
"// eslint-disable-line react-hooks/exhaustive-deps" and ensure the function
reference is stable by either (A) updating useMultiPhaseKycFlow to wrap
sumsubFlow.handleInitiateKyc in useCallback so it can be safely added to the
effect deps, or (B) memoizing handleInitiateKyc at the call site (e.g., const
initiate = useCallback(() => sumsubFlow.handleInitiateKyc('STANDARD'),
[sumsubFlow]) ) and then change the effect to depend on urlState.step and the
stable function; reference sumsubFlow.handleInitiateKyc and the useEffect that
currently reads urlState.step to apply the fix.
In `@src/components/Claim/Link/views/BankFlowManager.view.tsx`:
- Around line 83-92: The inline async onKycSuccess passed into
useMultiPhaseKycFlow inside BankFlowManager causes unstable references and
forces recreate of useMultiPhaseKycFlow.completeFlow and its dependents
(handleSumsubApproved, handleSkipTerms, handleModalClose); refactor onKycSuccess
into a stable callback using useCallback (e.g., define const onKycSuccess =
useCallback(async () => { if (justCompletedKyc) return;
setIsKycModalOpen(false); await fetchUser(); setJustCompletedKyc(true);
setClaimBankFlowStep(ClaimBankFlowStep.BankDetailsForm); }, [justCompletedKyc,
fetchUser, setIsKycModalOpen, setJustCompletedKyc, setClaimBankFlowStep]) and
pass that to useMultiPhaseKycFlow so completeFlow and downstream callbacks stop
being recreated on every render.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/app/(mobile-ui)/add-money/[country]/bank/page.tsxsrc/components/AddWithdraw/AddWithdrawCountriesList.tsxsrc/components/Claim/Link/views/BankFlowManager.view.tsx
No longer needed — name and email are now collected by Sumsub SDK. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add optimistic local state to BridgeTosReminder so it hides immediately after ToS acceptance (backend rail transition is async) - Remove BridgeTosReminder from KycCompleted drawer (avoid duplication) - Consolidate duplicate KYC activity entries into one per region (STANDARD, LATAM) via new groupKycByRegion() utility - Add region prop to KycStatusItem/KycStatusDrawer for region-aware titles Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@coderabbitai review in depth. Evaluate:
Also, write a very concise testing guide for QA |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 19501 🏁 Script executed: Length of output: 17223
🔴 Risk Assessment: HIGH-MEDIUMCritical Risk Areas1. Race Conditions in Multi-Phase Flow
Recommendation: Add cleanup flag: useEffect(() => {
let cancelled = false;
const handleTosIframeClose = async (source) => {
// ... existing logic
if (source === 'tos_accepted') {
await new Promise((resolve) => setTimeout(resolve, 2000))
if (cancelled) return; // Add guard
const retryResult = await confirmBridgeTos()
// ...
}
}
return () => { cancelled = true }
}, [])2. Missing Dependency Arrays 🚨
3. State Machine Complexity
4. Silent Failures
Medium Risk Areas5. Removed
6. Breaking Changes Not Documented
Low Risk (Well-Handled)✅ Polling cleanup is correct with ⚡ Performance AnalysisPositive Impacts (+)
Negative Impacts (-)
Latency Impact
Estimated worst-case flow time: 60-90 seconds (SDK submit → 30s preparing timeout → ToS → retry) 📊 Code Quality: GOOD with ConcernsStrengths ✅
Weaknesses
|