Skip to content

fix: bridge account creation fail when adding account#697

Merged
kushagrasarathe merged 3 commits intopeanut-wallet-devfrom
fix/bridge-account-cashout
Feb 19, 2025
Merged

fix: bridge account creation fail when adding account#697
kushagrasarathe merged 3 commits intopeanut-wallet-devfrom
fix/bridge-account-cashout

Conversation

@kushagrasarathe
Copy link
Copy Markdown
Contributor

@kushagrasarathe kushagrasarathe commented Feb 18, 2025

after kyc, when adding account, bridge account creation was failing for new users, this led to cashout's failing on staging.peanut.me without any proper message, issue was there was no bridge customer id present in db to be user here.
updated the flow to always check for bridge customer id and if it doesnt exist then create one, same for bridge external id's.

improved error handling for api routes

fixes TASK-9043

Summary by CodeRabbit

  • Bug Fixes

    • Improved error messaging and validations across account creation, cashout confirmation, KYC verification, and profile updates, ensuring clearer user feedback.
    • Enhanced checks during bank account linking to prevent incomplete submissions and improve transaction reliability.
    • Streamlined key user workflows, resulting in a more intuitive and robust experience.
  • New Features

    • Introduced enhanced error handling and validation in various API endpoints and user components, improving robustness and clarity of user interactions.

@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 19, 2025 8:31pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 18, 2025

Walkthrough

This pull request updates several API routes and frontend components by refining request data handling, increasing input validations, and standardizing error responses. The API endpoints now extract parameters from the JSON body instead of URL search parameters, and they return structured error responses using an error key. Frontend components have been improved with robust validations for user data and clearer feedback messages. Additionally, utility functions for cashout processes have enhanced error logging and input checking. Overall, the changes streamline control flows, reduce redundant error handling, and ensure consistent responses.

Changes

File(s) Change Summary
src/app/api/bridge/.../create-external-account/route.ts
src/app/api/bridge/.../get-all-for-customerId/route.ts
src/app/api/bridge/.../get-links/route.ts
Modified POST handlers to extract parameters from JSON, standardized error responses (using error key), simplified Bridge API error handling, and enhanced logging.
src/components/Global/.../KYCComponent/index.tsx
src/components/Global/.../LinkAccountComponent/index.tsx
src/components/Global/.../UpdateUserComponent/index.tsx
Added input validations for name and email, refined error messages, updated API call logic, and streamlined form data handling and response feedback.
src/components/Offramp/Confirm.view.tsx
src/utils/cashout.utils.ts
Improved error handling with granular error messages, enhanced logging in fetchApi, updated function signatures (e.g., making parameters optional), and refined cashout confirmation flows.
src/app/api/peanut/user/add-account/route.ts
src/app/api/peanut/user/update-user/route.ts
src/context/authContext.tsx
Renamed parameters for clarity (e.g., bridgeAccountId to bridgeAccountIdentifier), updated error handling to return structured JSON responses, and modified type definitions for user payloads.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant S as Server (Route Handler)
    participant B as Bridge API

    C->>S: POST /create-external-account (JSON body with parameters)
    S->>S: Extract parameters (customerId, accountType, etc.)
    S->>B: Forward request after validation
    B-->>S: Return API response (success or error)
    S->>C: Return structured JSON response (data or error)
Loading
sequenceDiagram
    participant U as User
    participant C as UpdateUserComponent
    participant G as getUserLinks Utility
    participant B as Bridge API

    U->>C: Submit profile update form
    C->>C: Validate inputs (name, email)
    C->>G: Invoke getUserLinks({ full_name, email })
    G->>B: Request bridge customer creation/linking
    B-->>G: Return response with customer_id or error
    G-->>C: Pass back response data
    C->>U: Display success or error feedback
Loading

Possibly related PRs

Suggested reviewers

  • jjramirezn

Poem

I'm a rabbit, hopping in code's delight,
Nibbling through errors, making everything light.
With parameters clear and validations on track,
I dance through endpoints, never looking back.
Celebrate these changes—hop, skip, and cheer!
🐇✨
Keep on coding, my friends, let joy appear!

✨ 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.

@notion-workspace
Copy link
Copy Markdown

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: 1

🧹 Nitpick comments (10)
src/app/api/bridge/user/new/get-links/route.ts (1)

54-57: Consider adding more detailed error information.

While the error handling is good, consider including more details from the error object to help with debugging.

-        return new NextResponse(JSON.stringify({ error: 'Internal Server Error' }), {
+        return new NextResponse(JSON.stringify({
+            error: 'Internal Server Error',
+            details: error instanceof Error ? error.message : 'Unknown error occurred'
+        }), {
src/app/api/bridge/external-account/get-all-for-customerId/route.ts (1)

68-78: Consider adding request tracing.

While the error handling is good, consider adding a request ID to help with tracing issues across the system.

 return new NextResponse(
     JSON.stringify({
         success: false,
         error: 'Internal server error',
         details: error instanceof Error ? error.message : 'Unknown error occurred',
+        requestId: uuidv4(), // Add this after importing uuid
     }),
     {
         status: 500,
         headers: { 'Content-Type': 'application/json' },
     }
 )
src/app/api/bridge/external-account/create-external-account/route.ts (1)

38-80: Consider using TypeScript enums for account types.

The account type validation could be more type-safe using TypeScript enums.

+type AccountType = 'iban' | 'us';
+
+const isValidAccountType = (type: string): type is AccountType => {
+    return ['iban', 'us'].includes(type);
+};
+
+if (!isValidAccountType(accountType)) {
    return new NextResponse(
        JSON.stringify({
            success: false,
            error: 'Invalid account type',
        }),
        {
            status: 400,
            headers: { 'Content-Type': 'application/json' },
        }
    )
}
src/components/Global/UpdateUserComponent/index.tsx (3)

58-81: Consider extracting Bridge customer creation logic.

The Bridge customer creation logic could be moved to a separate function for better maintainability.

+    const createBridgeCustomer = async (name: string, email: string) => {
+        try {
+            console.log('Creating bridge customer with:', { name, email })
+            const bridgeCustomer = await getUserLinks({
+                full_name: name,
+                email: email,
+            })
+            console.log('Bridge customer created:', bridgeCustomer)
+            return bridgeCustomer.customer_id
+        } catch (error) {
+            console.error('Failed to create Bridge customer:', error)
+            throw error
+        }
+    }

91-124: Consider using a loading state enum.

The loading state messages could be more maintainable using an enum.

+enum LoadingState {
+    Idle = 'Idle',
+    CreatingProfile = 'Creating your profile',
+    SettingUpAccount = 'Setting up your account',
+    SavingDetails = 'Saving your details'
+}
+
-    const [loadingState, setLoadingState] = useState<string>('Idle')
+    const [loadingState, setLoadingState] = useState<LoadingState>(LoadingState.Idle)

172-176: Consider using a toast notification system.

For a better user experience, consider using a toast notification system for error messages instead of inline errors.

src/components/Global/KYCComponent/index.tsx (1)

98-117: Enhance error handling with more specific validation messages.

While the validation for name and email is good, the error messages could be more specific about the format requirements.

-if (!name.trim() || !email.trim()) {
+if (!name.trim()) {
+    setErrorState({
+        showError: true,
+        errorMessage: 'Please provide your full name.',
+    })
+    return
+}
+if (!email.trim()) {
     setErrorState({
         showError: true,
-        errorMessage: 'Please provide both your name and email address.',
+        errorMessage: 'Please provide your email address.',
     })
     return
 }
src/utils/cashout.utils.ts (1)

167-199: Enhance error handling with more specific validation messages.

While the input validation is good, the error messages could be more specific and include validation requirements.

 if (!full_name?.trim() || !email?.trim()) {
     console.error('Invalid input:', { full_name, email })
-    throw new Error('Name and email are required')
+    throw new Error(
+        !full_name?.trim()
+            ? 'Full name is required and cannot be empty'
+            : 'Email is required and cannot be empty'
+    )
 }
src/components/Global/LinkAccountComponent/index.tsx (1)

201-206: Consider caching bridge customer data.

While the fallback for missing account owner name works, consider caching the bridge customer data to avoid unnecessary API calls.

+const [bridgeCustomerCache, setBridgeCustomerCache] = useState<any>(null)

 let accountOwnerName = user.user.full_name
 if (!accountOwnerName) {
-    const bridgeCustomer = await utils.getCustomer(customerId)
+    if (!bridgeCustomerCache) {
+        const bridgeCustomer = await utils.getCustomer(customerId)
+        setBridgeCustomerCache(bridgeCustomer)
+    }
+    const bridgeCustomer = bridgeCustomerCache
     accountOwnerName = `${bridgeCustomer.first_name} ${bridgeCustomer.last_name}`
 }
src/components/Offramp/Confirm.view.tsx (1)

245-249: Consider adding retry functionality for failed operations.

While the error handling is good, consider adding a retry mechanism for transient failures.

+const [retryCount, setRetryCount] = useState(0)
+const MAX_RETRIES = 3

 const errorMessage =
     error instanceof Error
         ? error.message
         : "We've encountered an error. Your funds are SAFU, please reach out to support"

+if (retryCount < MAX_RETRIES) {
+    return (
+        <button
+            onClick={() => {
+                setRetryCount(prev => prev + 1)
+                handleCashoutConfirm()
+            }}
+            className="btn-secondary"
+        >
+            Retry ({MAX_RETRIES - retryCount} attempts remaining)
+        </button>
+    )
+}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3b3966e and 14f3493.

📒 Files selected for processing (8)
  • src/app/api/bridge/external-account/create-external-account/route.ts (2 hunks)
  • src/app/api/bridge/external-account/get-all-for-customerId/route.ts (1 hunks)
  • src/app/api/bridge/user/new/get-links/route.ts (1 hunks)
  • src/components/Global/KYCComponent/index.tsx (4 hunks)
  • src/components/Global/LinkAccountComponent/index.tsx (5 hunks)
  • src/components/Global/UpdateUserComponent/index.tsx (5 hunks)
  • src/components/Offramp/Confirm.view.tsx (4 hunks)
  • src/utils/cashout.utils.ts (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview
🔇 Additional comments (14)
src/app/api/bridge/user/new/get-links/route.ts (2)

33-39: Improved duplicate user handling logic.

The updated condition now properly checks for both duplicate_record code and the presence of an existing KYC link, making the handling more robust.


41-46: Good addition of data validation.

The check for data.id ensures proper error handling when Bridge customer creation fails.

src/app/api/bridge/external-account/get-all-for-customerId/route.ts (3)

5-20: Well-structured request validation.

Good implementation of request validation with detailed error messages. The error response includes success status and details, which is helpful for debugging.


23-34: Improved server configuration error handling.

The error response for missing API key is well structured and provides clear information about the configuration issue.


44-59: Comprehensive Bridge API error handling.

Good use of optional chaining and fallback error message. The error response includes the original status and message from the Bridge API.

src/app/api/bridge/external-account/create-external-account/route.ts (1)

112-123: Good error handling structure.

The error handling includes both a generic message and detailed error information when available.

src/components/Global/UpdateUserComponent/index.tsx (1)

33-34: Good use of fallback values.

The default values properly cascade from props to user context.

src/components/Global/KYCComponent/index.tsx (3)

78-82: LGTM! Form value initialization is properly handled.

The code correctly sets form values from user data, ensuring a smooth user experience.


157-164: LGTM! Validation in handleTOSStatus is properly implemented.

The validation ensures required fields are present before proceeding with TOS status handling.


227-234: LGTM! Validation in handleKYCStatus is properly implemented.

The validation ensures required fields are present before proceeding with KYC status handling.

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

119-147: LGTM! Robust error handling in fetchApi.

The error handling is comprehensive, with proper logging of request details and error responses.


254-316: LGTM! Proper validation and error handling in createExternalAccount.

The function properly validates the customer ID and includes detailed error logging.

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

191-199: LGTM! Proper user validation checks.

The code properly validates user existence and bridge_customer_id with clear error messages.

src/components/Offramp/Confirm.view.tsx (1)

164-166: LGTM! Proper validation of link preparation.

The code properly validates the presence of preparedCreateLinkWrapperResponse before proceeding.

Comment on lines +7 to +8
const { customerId, accountType, accountDetails, address, accountOwnerName } = await request.json()

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.

🛠️ Refactor suggestion

Consider validating all required fields.

While customerId is validated, other required fields like accountType and accountDetails should also be validated upfront.

+        if (!accountType || !accountDetails) {
+            return new NextResponse(
+                JSON.stringify({
+                    success: false,
+                    error: 'Account type and details are required',
+                }),
+                {
+                    status: 400,
+                    headers: { 'Content-Type': 'application/json' },
+                }
+            )
+        }
📝 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 { customerId, accountType, accountDetails, address, accountOwnerName } = await request.json()
const { customerId, accountType, accountDetails, address, accountOwnerName } = await request.json()
if (!accountType || !accountDetails) {
return new NextResponse(
JSON.stringify({
success: false,
error: 'Account type and details are required',
}),
{
status: 400,
headers: { 'Content-Type': 'application/json' },
}
)
}

@kushagrasarathe kushagrasarathe changed the title [WIP] fix: bridge account creation fail when adding account fix: bridge account creation fail when adding account Feb 18, 2025
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

🔭 Outside diff range comments (2)
src/app/api/peanut/user/add-account/route.ts (1)

16-18: 🛠️ Refactor suggestion

Add validation for bridge account identifier.

Based on the PR objectives to fix bridge account creation failures, consider adding validation for bridgeAccountIdentifier to ensure proper error handling when it's missing.

-        if (!apiKey || !accountType || !accountIdentifier || !userId || !token) {
+        if (!apiKey || !accountType || !accountIdentifier || !userId || !token || !bridgeAccountIdentifier) {
             return new NextResponse('Bad Request: Missing required fields', { status: 400 })
         }
src/context/authContext.tsx (1)

223-238: 🛠️ Refactor suggestion

Fix parameter naming inconsistency.

The function parameter uses bridgeAccountId but the request payload uses bridgeAccountIdentifier. This inconsistency could lead to confusion and potential bugs.

     const addAccount = async ({
         accountIdentifier,
         accountType,
         userId,
-        bridgeAccountId,
+        bridgeAccountIdentifier,
         connector,
     }: {
         accountIdentifier: string
         accountType: string
         userId: string
-        bridgeAccountId?: string
+        bridgeAccountIdentifier?: string
         connector?: {
             iconUrl: string
             name: string
         }
     }) => {

Also applies to: 247-247

🧹 Nitpick comments (1)
src/context/authContext.tsx (1)

315-315: Remove debug console.log.

Remove the debug log statement to keep the production code clean.

-    console.log({ user })
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 14f3493 and 66daad9.

📒 Files selected for processing (8)
  • src/app/api/bridge/external-account/create-external-account/route.ts (2 hunks)
  • src/app/api/bridge/external-account/get-all-for-customerId/route.ts (1 hunks)
  • src/app/api/peanut/user/add-account/route.ts (2 hunks)
  • src/app/api/peanut/user/update-user/route.ts (3 hunks)
  • src/components/Global/LinkAccountComponent/index.tsx (6 hunks)
  • src/components/Offramp/Confirm.view.tsx (4 hunks)
  • src/context/authContext.tsx (1 hunks)
  • src/utils/cashout.utils.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/app/api/bridge/external-account/get-all-for-customerId/route.ts
  • src/utils/cashout.utils.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview
🔇 Additional comments (18)
src/app/api/peanut/user/add-account/route.ts (1)

9-9: LGTM! Parameter renaming is consistent.

The renaming from bridgeAccountId to bridgeAccountIdentifier aligns with the changes in the auth context.

Also applies to: 29-29

src/app/api/peanut/user/update-user/route.ts (3)

2-2: LGTM!

The import of KYCStatus type from @/utils is appropriate for type safety.


8-10: LGTM!

Making username and bridge_customer_id optional in the UserPayload type is appropriate as they may not be available during initial user creation.


100-106: LGTM!

The enhanced error handling with structured JSON responses improves error reporting and debugging.

src/app/api/bridge/external-account/create-external-account/route.ts (7)

6-22: LGTM!

The request body parsing with structured error handling improves the robustness of the API.


26-39: LGTM!

The validation of required fields with clear error messages helps identify missing parameters.


41-53: LGTM!

The server configuration validation ensures the API key is available before proceeding.


85-95: LGTM!

The account type validation with clear error messages helps identify invalid account types.


110-127: LGTM!

The Bridge API error handling with detailed error information improves debugging.


130-139: LGTM!

The success response handling with structured JSON response improves consistency.


141-163: LGTM!

The global error handling with detailed error information and stack traces in development improves debugging.

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

190-199: LGTM!

The validation ensures bridge customer ID exists before proceeding with account linking, which prevents the issue mentioned in the PR objective.


201-206: LGTM!

The account owner name handling with fallback to bridge customer data improves reliability.


312-336: LGTM!

The external account creation error handling with clear error messages improves user experience.


422-422: LGTM!

The error message improvements provide clearer guidance to users.

Also applies to: 597-597

src/components/Offramp/Confirm.view.tsx (3)

191-199: LGTM!

The validation ensures bridge customer ID exists before proceeding with cashout, which prevents the issue mentioned in the PR objective.


201-206: LGTM!

The account owner name handling with fallback to bridge customer data improves reliability.


244-254: LGTM!

The error handling improvements with clear error messages and refund option improve user experience.

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