Skip to content

fix: kyc flow for SEPA/Euro services#694

Merged
kushagrasarathe merged 2 commits intodevelopfrom
fix/kyc-ui
Feb 25, 2025
Merged

fix: kyc flow for SEPA/Euro services#694
kushagrasarathe merged 2 commits intodevelopfrom
fix/kyc-ui

Conversation

@kushagrasarathe
Copy link
Copy Markdown
Contributor

@kushagrasarathe kushagrasarathe commented Feb 18, 2025

-a additional kyc step for SEPA/Euro accounts if account creation fails

@jjramirezn these changes are already implemented in the wallet, just pulled them here

fixes TASK-9017

Summary by CodeRabbit

  • Bug Fixes

    • Improved API responses to return clear, structured error messages with appropriate status codes.
    • Enhanced account linking error handling to prompt users for additional KYC verification when needed.
  • Style

    • Updated confirmation messaging wording for KYC to clarify potential progress loss.
    • Adjusted layout alignment for a more consistent and user-friendly presentation.
  • Refactor

    • Streamlined response parsing and expanded error details for improved consistency in feedback.
    • Enhanced type definitions for better clarity and maintainability.

@vercel
Copy link
Copy Markdown

vercel bot commented Feb 18, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
peanut-ui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 25, 2025 0:37am

@notion-workspace
Copy link
Copy Markdown

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 18, 2025

Walkthrough

This pull request updates error handling and response formatting in the external account creation API. The POST function in the API route now uses structured JSON responses instead of unhandled throw statements, with specific HTTP status codes for different errors. In parallel, UI components have been adjusted by reorganizing import orders, refining confirmation messages, removing unused imports, and updating KYC verification logic. Additionally, the response interface is enhanced with an optional property for more detailed error information, and the cashout utility consolidates imports and introduces a dedicated KYC status type.

Changes

Files Change Summary
src/app/api/bridge/.../route.ts
src/utils/cashout.utils.ts
Updated error handling and response management for external account creation. Consolidated import statements, introduced a new KYCStatus type, and streamlined duplicate account and API error processing.
src/components/Global/.../index.tsx (KYCComponent and LinkAccountComponent) Reorganized import structure and refined UI text. Removed unused imports, updated KYC status condition (from "verified" to "approved"), integrated a new state (reKYCUrl) for additional verification, and adjusted layout classes.
src/interfaces/interfaces.ts Enhanced the IResponse interface with a new optional details property providing structured error code, message, and additional requirements.

Possibly related PRs

  • Cashout fixes #473: Enhances error handling and response formatting in the POST function of the external account creation route, related to modifications in the GlobaLinkAccountComponent.
  • fix: cashout flow #703: Modifies error handling and response logic within the POST function of the create-external-account route, similar to the main PR.
  • feat: show additional KYC link wen create account fails #685: Addresses error handling and response formatting in the POST function of the create-external-account route, indicating a direct relationship with the main PR.

Suggested reviewers

  • jjramirezn

Poem

I'm a little rabbit, hopping through the code,
Changing throws to JSON, lightening up the load.
With responses clear and errors gently tamed,
Our changing paths in code are proudly named.
Code carrots aplenty, bugs set free,
A joyful hop forward for you and me!
(_/) 🥕 (^_^)

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/app/api/bridge/external-account/create-external-account/route.ts (1)

112-156: Consider extracting account matching logic into a helper function.

While the duplicate account handling is thorough, the account matching logic could be extracted into a helper function for better maintainability and reusability.

+function findMatchingAccount(accounts: interfaces.IBridgeAccount[], accountType: string, accountDetails: any): interfaces.IBridgeAccount | undefined {
+    return accounts.find((account: interfaces.IBridgeAccount) => {
+        if (accountType === 'iban') {
+            return (
+                account.account_details.type === 'iban' &&
+                account.account_details.last_4 === accountDetails.accountNumber.slice(-4)
+            )
+        } else {
+            return (
+                account.account_details.type === 'us' &&
+                account.account_details.last_4 === accountDetails.accountNumber.slice(-4) &&
+                account.account_details.routing_number === accountDetails.routingNumber
+            )
+        }
+    })
+}

 if (responseData?.code === 'duplicate_external_account') {
     console.log('Duplicate account detected, fetching existing accounts')
     const allAccounts = await fetch(`/api/bridge/external-account/get-all-for-customerId`, {
         method: 'POST',
         headers: { 'Content-Type': 'application/json' },
         body: JSON.stringify({ customerId }),
     })

     if (!allAccounts.ok) {
         return new NextResponse(
             JSON.stringify({ success: false, message: 'Failed to fetch existing accounts' }),
             { status: 500, headers: { 'Content-Type': 'application/json' } }
         )
     }

     const accounts = await allAccounts.json()
     console.log('Found existing accounts:', accounts)

-    const existingAccount = accounts.find((account: interfaces.IBridgeAccount) => {
-        if (accountType === 'iban') {
-            return (
-                account.account_details.type === 'iban' &&
-                account.account_details.last_4 === accountDetails.accountNumber.slice(-4)
-            )
-        } else {
-            return (
-                account.account_details.type === 'us' &&
-                account.account_details.last_4 === accountDetails.accountNumber.slice(-4) &&
-                account.account_details.routing_number === accountDetails.routingNumber
-            )
-        }
-    })
+    const existingAccount = findMatchingAccount(accounts, accountType, accountDetails)
src/utils/cashout.utils.ts (1)

224-275: Consider defining error code constants.

While the error handling is robust, defining constants for error codes would improve maintainability and reduce the risk of typos.

+// Add at the top of the file
+export const ERROR_CODES = {
+    DUPLICATE_ACCOUNT: 'duplicate_external_account',
+    ENDORSEMENT_REQUIREMENTS: 'endorsement_requirements_not_met',
+} as const;

-if (responseData.code === 'duplicate_external_account') {
+if (responseData.code === ERROR_CODES.DUPLICATE_ACCOUNT) {
    // ...
}

-if (responseData.details?.code === 'endorsement_requirements_not_met') {
+if (responseData.details?.code === ERROR_CODES.ENDORSEMENT_REQUIREMENTS) {
    // ...
}
src/components/Global/LinkAccountComponent/index.tsx (1)

598-614: Add ARIA labels for better accessibility.

While the error display is clear, adding ARIA labels would improve accessibility for screen readers.

-<div className="flex flex-col gap-2">
+<div className="flex flex-col gap-2" role="alert" aria-live="polite">
     <label className="whitespace-normal text-h8 font-normal text-red">
         {errorState.errorMessage}{' '}
         <a
             href={reKYCUrl}
             target="_blank"
             rel="noopener noreferrer"
             className="underline"
+            aria-label="Complete additional KYC verification"
         >
             Click here to complete additional KYC verification.
         </a>
     </label>
 </div>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 671715d and 6347830.

📒 Files selected for processing (5)
  • src/app/api/bridge/external-account/create-external-account/route.ts (3 hunks)
  • src/components/Global/KYCComponent/index.tsx (2 hunks)
  • src/components/Global/LinkAccountComponent/index.tsx (12 hunks)
  • src/interfaces/interfaces.ts (1 hunks)
  • src/utils/cashout.utils.ts (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/components/Global/KYCComponent/index.tsx
🔇 Additional comments (7)
src/app/api/bridge/external-account/create-external-account/route.ts (3)

10-14: LGTM! Improved error handling for missing parameters.

The error handling follows best practices with proper HTTP status codes and structured JSON responses.


85-97: LGTM! Enhanced KYC verification flow.

The code properly handles KYC verification requirements by checking for endorsement requirements and providing a verification URL when needed. This aligns well with the PR's objective of improving the KYC flow.


173-182: LGTM! Robust error handling in catch block.

The error handling follows best practices by providing structured error responses with appropriate status codes and clear error messages.

src/interfaces/interfaces.ts (1)

9-15: LGTM! Well-structured interface extension.

The addition of the details property to IResponse interface provides a robust structure for enhanced error responses, supporting the improved KYC flow.

src/utils/cashout.utils.ts (1)

134-134: LGTM! Well-defined KYC status type.

The KYCStatus type provides clear and descriptive status values, improving type safety throughout the codebase.

src/components/Global/LinkAccountComponent/index.tsx (2)

113-113: LGTM! Consistent KYC status check.

The change from 'verified' to 'approved' aligns with the new KYCStatus type and maintains consistency with backend changes.


315-330: LGTM! Enhanced KYC verification handling.

The code properly handles KYC verification requirements by providing a clear path for users to complete additional verification when needed.

@kushagrasarathe
Copy link
Copy Markdown
Contributor Author

@jjramirezn after you are done with the review of this, please do not merge it to staging, i've some other cashout related issues that i'm investigating so gotta check a few things after I'm done investigating those

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/app/api/peanut/user/add-account/route.ts (1)

36-43: Improved error handling for user conflict scenario.

The addition of specific handling for 409 status code significantly improves error handling. Now, instead of throwing an error, the API returns a structured JSON response when a user already exists, making it easier for the client to process and display appropriate messages.

Consider standardizing the error response format for all error cases, not just the 409 case. This would make error handling more consistent throughout the application.

 if (!response.ok) {
     if (response.status === 409) {
         return new NextResponse(JSON.stringify({ error: 'User already exists' }), {
             status: 409,
             headers: {
                 'Content-Type': 'application/json',
             },
         })
     }
-    throw new Error(`Failed to create user: ${response.status}`)
+    return new NextResponse(JSON.stringify({ error: `Failed to create user: ${response.status}` }), {
+        status: response.status,
+        headers: {
+            'Content-Type': 'application/json',
+        },
+    })
 }
src/components/Global/LinkAccountComponent/index.tsx (1)

334-334: Remove redundant double negation.

The double negation (!!) is unnecessary as the expression will already be evaluated as a boolean in the if statement.

-if (!!bridgeAccountId) {
+if (bridgeAccountId) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 334-334: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6347830 and f3916f2.

📒 Files selected for processing (4)
  • src/app/api/bridge/external-account/create-external-account/route.ts (3 hunks)
  • src/app/api/peanut/user/add-account/route.ts (2 hunks)
  • src/components/Global/LinkAccountComponent/index.tsx (13 hunks)
  • src/utils/cashout.utils.ts (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/app/api/bridge/external-account/create-external-account/route.ts
  • src/utils/cashout.utils.ts
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/Global/LinkAccountComponent/index.tsx

[error] 334-334: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

🔇 Additional comments (16)
src/app/api/peanut/user/add-account/route.ts (1)

3-4: Import statement order has been reorganized.

The order of import statements has been changed, with NextRequest and NextResponse now imported after the constants and cookies. While this doesn't affect functionality, it's a minor stylistic change.

src/components/Global/LinkAccountComponent/index.tsx (15)

2-14: Import statements reorganized and optimized.

The imports have been reorganized for better readability and unused imports have been removed, which is a good practice for code maintenance.


49-49: Added state for KYC verification URL.

A new state variable reKYCUrl has been added to store the KYC URL when re-verification is required. This enhances the user experience by providing a direct link for users to complete additional verification steps.


113-113: Updated KYC status check condition.

The KYC status check has been changed from 'verified' to 'approved', ensuring alignment with the expected status values from the backend.


188-188: Reset KYC URL state when starting a new submission.

This ensures that any previous KYC URL is cleared when a new form submission is initiated, preventing potential confusion from displaying old URLs.


190-199: Added user and customer ID verification.

The component now properly checks for user existence and the presence of bridge_customer_id before proceeding with account linking. This improves error handling and provides clearer error messages to users when these prerequisites are not met.


201-206: Enhanced account owner name retrieval.

The component now has a fallback mechanism to fetch the customer's full name from the Bridge API if it's not available in the user object. This ensures that the account creation process has all required information.


304-308: Updated external account creation with proper typing.

The response from createExternalAccount is now properly typed as IResponse, making the code more robust and type-safe. The function parameters have also been adjusted to align with the expected parameter structure.


312-330: Added KYC verification flow for failed account creation.

This is a significant enhancement to handle cases where account creation fails due to insufficient KYC verification. Now, if endorsement requirements are not met, the component sets a verification URL that users can follow to complete the necessary verification steps.


411-429: Enhanced error display with KYC verification link.

The error display now conditionally renders a link for users to complete KYC verification when required. This improves user experience by providing a clear path to resolve verification issues.


522-522: Improved layout structure for form fields.

The form layout has been updated to be more responsive with flex column on small screens and flex row on medium screens and above.


586-604: Consistent error display across form steps.

The error display logic has been replicated across both form steps, ensuring a consistent experience regardless of which step encounters an error.


613-613: Improved text alignment for better readability.

Changed text alignment from centered to left-aligned (text-center to text-start), which generally improves readability for larger text blocks.

Also applies to: 626-626


636-636: Added step navigation functionality.

The component now allows users to navigate between steps by clicking on them, improving the user experience.


653-653: Improved component layout with better responsive design.

The layout has been updated with improved z-index handling and responsive padding for different screen sizes.


663-663: Simplified KYC component implementation.

The KYC component is now directly imported and used without additional wrapper elements, making the code cleaner.

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.

2 participants