Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
Caution Review failedThe pull request is closed. 📝 Walkthrough📝 WalkthroughWalkthroughThis pull request introduces multiple enhancements across various components related to bank account handling, input validation, and user interface improvements. Key updates include the addition of utility functions for sanitizing and formatting bank account information, modifications to error handling and recipient type assignment, and the introduction of a new component for U.S. bank account inputs. Additionally, testing capabilities have been established with new scripts and configuration for Jest, alongside updates to environment variables for configuration management. Changes
Possibly related PRs
Suggested reviewers
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 21
🧹 Outside diff range and nitpick comments (13)
src/utils/format.utils.ts (1)
1-14: Consider implementing a comprehensive bank account handling strategyGiven that this code handles sensitive financial data, consider these architectural improvements:
- Create proper TypeScript interfaces for different bank account types
- Implement a centralized validation module
- Add proper error handling and logging (without exposing sensitive data)
- Consider using a dedicated financial data handling library
Example structure:
interface BankAccount { type: 'US' | 'IBAN'; value: string; routingNumber?: string; // for US accounts } interface ValidationResult { isValid: boolean; errors: string[]; }src/interfaces/index.ts (1)
1-38: Reconsider merging core type definitions in a temporary commitThe PR title suggests this is a temporary commit, but this file contains critical type definitions that will be used throughout the application. Consider:
- Splitting this into a separate, complete PR
- Removing the "temp commit" status
- Adding comprehensive documentation
- Getting team consensus on the type structure
These interfaces form a crucial part of the type system and should be well-thought-out before merging.
src/components/Global/GeneralRecipientInput/index.tsx (2)
107-114: Consider memoizing the format functionSince
formatDisplayValueis used during rendering and depends only on the recipient type, consider memoizing it withuseCallbackto prevent unnecessary re-renders.- const formatDisplayValue = (value: string) => { + const formatDisplayValue = useCallback((value: string) => { if (recipientType.current === 'iban') { return formatIBANDisplay(value) } else if (recipientType.current === 'us') { return formatUSAccountDisplay(value) } return value - } + }, [])
Line range hint
1-132: Address temporary status of changesThe PR title indicates this is a "temp commit, not fully done". Consider:
- Completing the US bank account validation
- Adding comprehensive test coverage
- Documenting the expected format for bank accounts
- Adding proper error messages for all validation cases
Please update the PR title and description once the implementation is complete.
Would you like help with any of these improvements?
src/components/Global/ValidatedInput/index.tsx (2)
107-107: Consider optimizing value formatting.While the formatting logic is correct, it could benefit from memoization to prevent unnecessary re-renders.
Consider using useMemo:
+const displayValue = useMemo( + () => (formatDisplayValue ? formatDisplayValue(value) : value), + [formatDisplayValue, value] +) <input type="text" - value={formatDisplayValue ? formatDisplayValue(value) : value} + value={displayValue} // ... other props />
Line range hint
1-158: Consider splitting responsibilities for better maintainability.The ValidatedInput component is handling multiple concerns:
- Input validation
- Value sanitization
- Value formatting
- UI rendering
Consider splitting this into smaller, more focused components following the Single Responsibility Principle.
Suggested architecture:
- Create a separate BankAccountInput component that uses ValidatedInput internally
- Move bank-specific logic (sanitization, formatting) to the new component
- Keep ValidatedInput as a generic validated input component
src/components/Cashout/Components/Initial.view.tsx (2)
231-236: Consider enhancing bank account formatting based on account typeWhile the current formatting improves readability, consider differentiating the formatting based on account type (US vs IBAN) for better user experience.
const formatBankAccountDisplay = (value: string) => { + // For US accounts (routing number + account number) + if (value.length === 17) { // 9 digits routing + 8 digits account + const routing = value.slice(0, 9) + const account = value.slice(9) + return `${routing.replace(/(.{3})/g, '$1 ').trim()} | ${account.replace(/(.{4})/g, '$1 ').trim()}` + } + // For IBAN return value .toUpperCase() .replace(/(.{4})/g, '$1 ') .trim()
368-376: Enhance error message clarity for bank account validationWhile the error message is improved, it could be more specific about the expected format for US bank accounts.
- 'Invalid bank account. For US bank accounts, enter your routing number and account number separately.', + 'Invalid bank account. For US bank accounts, enter your 9-digit routing number followed by your account number (typically 8-17 digits). For IBAN, enter your full IBAN number.',Also applies to: 387-387
src/components/Claim/Link/Initial.view.tsx (1)
461-465: Consider enhancing recipient type handlingThe current implementation sets the recipient type to 'address' when the address is empty, which might not handle all edge cases effectively.
Consider this more robust implementation:
-if (!update.recipient.address) { - setRecipientType('address') -} else { - setRecipientType(update.type) -} +const newType = !update.recipient.address ? 'address' : + update.type || determineRecipientType(update.recipient.address); +setRecipientType(newType);This would:
- Maintain the current logic
- Add a fallback to determine type from address format
- Make the code more maintainable
src/components/Offramp/Confirm.view.tsx (1)
Line range hint
1-24: Consider splitting into smaller, focused componentsThe
OfframpConfirmViewcomponent has grown quite large and handles multiple responsibilities. This makes it harder to maintain and test.Consider breaking it down into smaller, focused components:
KYCFlow- Handle KYC verification stepsBankAccountConfirmation- Display and handle bank account detailsTransactionConfirmation- Handle transaction submission and error statesThis would:
- Improve code organization and maintainability
- Make testing easier
- Allow for better reuse of common functionality
src/components/Global/LinkAccountComponent/index.tsx (3)
163-163: Remove unnecessary console.log statementThe
console.logstatement may have been used for debugging purposes and should be removed to clean up the code.Apply this diff to remove the
console.log:- console.log('Submitting form data:', formData)
167-167: Remove unnecessary console.log statementThe
console.logat this line is likely a leftover from debugging. It's best to remove it to maintain clean production code.Apply this diff to remove the
console.log:- console.log('Missing routing number')
202-202: Remove unnecessary console.log statementThe
console.logstatement here should be removed to avoid cluttering the console in production.Apply this diff to remove the
console.log:- console.log('Form validation failed')
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (10)
src/components/Cashout/Components/Initial.view.tsx(5 hunks)src/components/Claim/Link/Initial.view.tsx(1 hunks)src/components/Global/GeneralRecipientInput/index.tsx(3 hunks)src/components/Global/LinkAccountComponent/index.tsx(10 hunks)src/components/Global/USBankAccountInput/index.tsx(1 hunks)src/components/Global/ValidatedInput/index.tsx(5 hunks)src/components/LandingPage/BuildOnUs/index.tsx(1 hunks)src/components/Offramp/Confirm.view.tsx(3 hunks)src/interfaces/index.ts(1 hunks)src/utils/format.utils.ts(1 hunks)
🧰 Additional context used
📓 Learnings (1)
src/components/Cashout/Components/Initial.view.tsx (1)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#484
File: src/components/Cashout/Components/Initial.view.tsx:273-274
Timestamp: 2024-11-12T09:39:20.720Z
Learning: In the `InitialCashoutView` component (`src/components/Cashout/Components/Initial.view.tsx`), linked bank accounts should not generate error states, and the `ValidatedInput` component will clear any error messages if needed. Therefore, it's unnecessary to manually clear the error state when selecting or clearing linked bank accounts.
🔇 Additional comments (13)
src/utils/format.utils.ts (2)
12-14:
Enhance US bank account formatting and security
The current implementation is too basic for US bank account formatting needs.
Consider these security and formatting improvements:
+/**
+ * Formats a US bank account number for display
+ * @param value - The raw account number
+ * @returns Formatted and partially masked account number
+ */
export const formatUSAccountDisplay = (value: string) => {
- return value.toUpperCase()
+ if (!value) return '';
+ const cleaned = value.replace(/\D/g, '');
+ // Mask all but last 4 digits for security
+ return cleaned.slice(-4).padStart(cleaned.length, '*');
}Additionally:
- Consider separating routing number formatting into a different function
- Add validation for valid US bank account length and format
- Consider adding proper ACH formatting guidelines
Let's check for existing bank account validation patterns:
5-10: 🛠️ Refactor suggestion
Add IBAN validation and documentation
The IBAN formatting looks correct but lacks validation and proper documentation.
Consider these improvements:
+/**
+ * Formats an IBAN for display according to the standard format
+ * @param value - The raw IBAN string
+ * @returns Formatted IBAN with spaces every 4 characters
+ * @example
+ * formatIBANDisplay('DE89370400440532013000') // returns 'DE89 3704 0044 0532 0130 00'
+ */
export const formatIBANDisplay = (value: string) => {
+ if (!value) return '';
+ // Remove existing spaces first to ensure consistent formatting
+ const cleaned = value.replace(/\s/g, '');
return value
.toUpperCase()
.replace(/(.{4})/g, '$1 ')
.trim()
}Consider adding IBAN structure validation using a library like ibantools to ensure valid IBANs.
Let's check if the project already uses any IBAN validation libraries:
src/interfaces/index.ts (1)
21-32: 🛠️ Refactor suggestion
Replace any[] types with proper interfaces and document fields
The interface uses any[] types which reduces type safety. Also, there seems to be redundancy in points tracking.
Consider the following improvements:
+interface Transaction {
+ id: string
+ amount: number
+ timestamp: Date
+ type: string
+ // Add other relevant fields
+}
+interface ReferralPointsTransaction extends Transaction {
+ referralId: string
+ // Add referral-specific fields
+}
export interface IUserProfile {
+ /** Current point balance */
points: number
- transactions: any[]
+ transactions: Transaction[]
- referralsPointsTxs: any[]
+ referralsPointsTxs: ReferralPointsTransaction[]
+ /** Total number of successful referral connections */
totalReferralConnections: number
+ /** Number of users referred */
referredUsers: number
+ /** Current streak count */
streak: number
accounts: Account[]
- contacts: any[]
+ contacts: User[]
- totalPoints: number // Possibly redundant with points?
+ /** Lifetime total points earned (including spent points) */
+ totalPoints: number
user: User
}Also, please clarify the difference between points and totalPoints. Is one the current balance and the other the lifetime total?
src/components/LandingPage/BuildOnUs/index.tsx (1)
17-17: Verify the new Notion URL is accessible and correct
The integration form URL has been significantly changed. Please ensure:
- The new URL is accessible and points to the correct integration form
- No information or functionality is lost with the removal of the
pvsparameter
src/components/Global/GeneralRecipientInput/index.tsx (1)
9-9: Verify the implementation of bank account formatting utilities
The code now uses utility functions for sanitization and formatting, which is a good practice. However, we should verify their implementation to ensure they handle all edge cases correctly.
Also applies to: 44-45
✅ Verification successful
Bank account formatting utilities are properly implemented
The utility functions are implemented correctly in src/utils/format.utils.ts:
sanitizeBankAccount: Removes spaces, hyphens, dots, and underscores, converting to lowercaseformatIBANDisplay: Formats IBAN with spaces every 4 characters and converts to uppercaseformatUSAccountDisplay: Converts US account numbers to uppercase
These implementations follow standard formatting practices for bank accounts and provide consistent handling of the input values.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for the implementation of the imported utility functions
ast-grep --pattern 'export function sanitizeBankAccount($_) {
$$$
}'
ast-grep --pattern 'export function formatIBANDisplay($_) {
$$$
}'
ast-grep --pattern 'export function formatUSAccountDisplay($_) {
$$$
}'
Length of output: 219
Script:
#!/bin/bash
# Let's try a different approach using ripgrep to find these functions
rg "export (const|function) (sanitizeBankAccount|formatIBANDisplay|formatUSAccountDisplay)" -A 10
# Also search for the file that might contain these functions
fd "format.utils.ts"
Length of output: 866
src/components/Global/ValidatedInput/index.tsx (3)
4-4: LGTM! Clean type definition and import.
The new import and type definition are well-structured and properly typed.
Also applies to: 17-17
36-36: LGTM! Proper props destructuring.
The formatDisplayValue prop is correctly destructured alongside other props.
82-88: 🛠️ Refactor suggestion
Consider improving error handling and state management.
While the sanitization logic is good, there are a few concerns:
- Missing error handling for sanitizeBankAccount
- The isChanging flag might be misleading if sanitization removes all characters
- This appears to be temporary code based on the PR title
Let's verify the sanitizeBankAccount implementation:
Consider this safer implementation:
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const rawValue = e.target.value
- const sanitizedValue = sanitizeBankAccount(rawValue)
+ let sanitizedValue
+ try {
+ sanitizedValue = sanitizeBankAccount(rawValue)
+ } catch (error) {
+ console.error('Error sanitizing bank account:', error)
+ sanitizedValue = rawValue
+ }
onUpdate({
value: sanitizedValue,
isValid: false,
- isChanging: !!sanitizedValue,
+ isChanging: sanitizedValue !== value,
})
}src/components/Cashout/Components/Initial.view.tsx (3)
23-23: LGTM: Clean import of bank account sanitization utility
The addition of the sanitizeBankAccount utility aligns well with the component's bank account handling requirements.
224-225: LGTM: Proper sanitization of bank account identifiers
The sanitization of account identifiers before state updates ensures consistent handling of bank account numbers.
318-330: LGTM: Improved bank account display and interaction
The UI changes enhance the visual presentation and maintain consistent account handling with proper sanitization.
Also applies to: 339-340
src/components/Claim/Link/Initial.view.tsx (1)
461-465: Verify recipient type handling across the application
The changes to recipient type handling could affect other parts of the application.
Let's verify the usage of recipient types:
✅ Verification successful
Let me try different commands to gather the necessary information.
Recipient type handling is consistent across the application
The changes to recipient type handling in Initial.view.tsx are consistent with the application's type system and usage patterns. The search results show:
- The
RecipientTypeis properly defined ininterfaces.tsas'address' | 'ens' | 'iban' | 'us' - The
setRecipientTypeusage inInitial.view.tsxcorrectly sets the type based on the recipient's address presence - The recipient type is consistently used across components for conditional rendering and flow control
- The type handling aligns with the application's payment rail logic (SEPA for IBAN, ACH for US)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for recipient type usage
echo "Searching for recipient type references..."
rg "setRecipientType|recipientType.*=|type.*=.*('address'|'iban'|'us')" -t tsx -t ts
# Search for GeneralRecipientInput usage
echo "Searching for GeneralRecipientInput usage..."
ast-grep --pattern 'GeneralRecipientInput $$$'
# Search for related test files
echo "Searching for related test files..."
fd -e test.tsx -e test.ts -e spec.tsx -e spec.ts
Length of output: 507
Script:
#!/bin/bash
# Search for recipient type usage with correct file extensions
echo "Searching for recipient type references..."
rg "setRecipientType|recipientType.*=|type.*=.*('address'|'iban'|'us')" --type-add 'tsx:*.tsx' --type-add 'ts:*.ts' -t tsx -t ts
# Search for recipient type enum or type definition
echo "Searching for recipient type definitions..."
rg "type.*Recipient.*=|enum.*Recipient|interface.*Recipient" --type-add 'tsx:*.tsx' --type-add 'ts:*.ts' -t tsx -t ts
# Search specifically in the Claim directory
echo "Searching in Claim directory..."
rg "setRecipientType|recipientType" src/components/Claim/ --type-add 'tsx:*.tsx' --type-add 'ts:*.ts' -t tsx -t ts
Length of output: 9956
src/components/Offramp/Confirm.view.tsx (1)
657-662: LGTM! Improved bank account display formatting
The changes enhance the presentation of bank account information using proper flex layout and consistent formatting.
src/utils/format.utils.ts
Outdated
| export const sanitizeBankAccount = (value: string) => { | ||
| return value.replace(/[\s\-\._]/g, '').toLowerCase() | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add input validation and consider preserving case
The sanitization function needs additional safety checks and might need to preserve case for certain bank account formats.
Consider these improvements:
export const sanitizeBankAccount = (value: string) => {
+ if (!value) return '';
+ // Some bank accounts are case-sensitive
- return value.replace(/[\s\-\._]/g, '').toLowerCase()
+ return value.replace(/[\s\-\._]/g, '')
}Also, consider adding JSDoc comments to document the function's purpose and expected input format.
📝 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.
| export const sanitizeBankAccount = (value: string) => { | |
| return value.replace(/[\s\-\._]/g, '').toLowerCase() | |
| } | |
| export const sanitizeBankAccount = (value: string) => { | |
| if (!value) return ''; | |
| // Some bank accounts are case-sensitive | |
| return value.replace(/[\s\-\._]/g, '') | |
| } |
src/utils/format.utils.ts
Outdated
| export const sanitizeBankAccount = (value: string) => { | ||
| return value.replace(/[\s\-\._]/g, '').toLowerCase() | ||
| } | ||
|
|
||
| export const formatIBANDisplay = (value: string) => { | ||
| return value | ||
| .toUpperCase() | ||
| .replace(/(.{4})/g, '$1 ') | ||
| .trim() | ||
| } | ||
|
|
||
| export const formatUSAccountDisplay = (value: string) => { | ||
| return value.toUpperCase() | ||
| } |
There was a problem hiding this comment.
💡 Codebase verification
Missing test coverage for bank account formatting utilities
The codebase lacks dedicated test coverage for the newly added bank account formatting utilities. No test files were found for:
sanitizeBankAccountformatIBANDisplayformatUSAccountDisplay
Recommend adding test cases to verify:
- IBAN formatting with various input patterns
- US account number formatting
- Bank account sanitization with different special characters
🔗 Analysis chain
Verify test coverage for bank account formatting
Given that this PR is marked as "temp commit, not fully done", ensure proper test coverage is added before merging to production.
Let's check for existing tests:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Look for related test files
fd -e test.ts -e spec.ts format.utils
# Check for existing test patterns
rg -l "describe.*format.*bank|test.*iban|test.*account" --type ts
Length of output: 187
Script:
#!/bin/bash
# Let's check the content of the files that matched our pattern
# to understand the test coverage context better
echo "=== Content of files with potential test patterns ==="
rg "describe.*format.*bank|test.*iban|test.*account" -A 5 --type ts
# Let's also check if there are any test files we might have missed
echo -e "\n=== Looking for any test files containing 'sanitize' or 'format' ==="
fd -e test.ts -e spec.ts | xargs rg "sanitize|format" -l
# Check for any existing test directory structure
echo -e "\n=== Test directory structure ==="
fd -t d "test|spec|__tests__"
Length of output: 3740
src/interfaces/index.ts
Outdated
| export interface IResponse { | ||
| success: boolean | ||
| data: any | ||
| message?: string | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Make IResponse generic and follow naming conventions
The interface uses any type which reduces type safety, and the name doesn't follow TypeScript conventions.
-export interface IResponse {
+export interface Response<T = unknown> {
success: boolean
- data: any
+ data: T
message?: string
}This allows for type-safe usage like:
const userResponse: Response<User> = ...
const profileResponse: Response<IUserProfile> = ...
src/interfaces/index.ts
Outdated
| export interface Account { | ||
| account_id: string | ||
| account_identifier: string | ||
| account_type: string | ||
| bridge_account_id?: string | ||
| account_details?: string // JSON string containing address details | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Replace string JSON with typed interface for account_details
Using a string type for JSON data reduces type safety and makes it harder to work with the address details.
Consider creating a proper interface for address details:
+interface AddressDetails {
+ street?: string
+ city?: string
+ state?: string
+ postalCode?: string
+ country?: string
+}
export interface Account {
account_id: string
account_identifier: string
account_type: string
bridge_account_id?: string
- account_details?: string // JSON string containing address details
+ account_details?: AddressDetails
}📝 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.
| export interface Account { | |
| account_id: string | |
| account_identifier: string | |
| account_type: string | |
| bridge_account_id?: string | |
| account_details?: string // JSON string containing address details | |
| } | |
| interface AddressDetails { | |
| street?: string | |
| city?: string | |
| state?: string | |
| postalCode?: string | |
| country?: string | |
| } | |
| export interface Account { | |
| account_id: string | |
| account_identifier: string | |
| account_type: string | |
| bridge_account_id?: string | |
| account_details?: AddressDetails | |
| } |
src/interfaces/index.ts
Outdated
| export interface User { | ||
| userId: string | ||
| email?: string | ||
| username?: string | ||
| full_name?: string | ||
| bridge_customer_id?: string | ||
| kycStatus?: 'verified' | 'pending' | 'rejected' | undefined | ||
| profile_picture?: string | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Improve type definitions in User interface
Several improvements can be made to enhance type safety and maintainability:
export interface User {
+ /** Unique identifier for the user */
userId: string
+ /** User's email address */
email?: string
+ /** User's chosen username */
username?: string
+ /** User's full name */
full_name?: string
+ /** Bridge platform customer ID */
bridge_customer_id?: string
- kycStatus?: 'verified' | 'pending' | 'rejected' | undefined
+ kycStatus?: 'verified' | 'pending' | 'rejected'
+ /** URL to user's profile picture */
profile_picture?: string
}- Removed redundant
undefinedfrom union type as it's already optional - Added JSDoc comments for better documentation
- Consider standardizing naming convention (either camelCase or snake_case)
📝 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.
| export interface User { | |
| userId: string | |
| email?: string | |
| username?: string | |
| full_name?: string | |
| bridge_customer_id?: string | |
| kycStatus?: 'verified' | 'pending' | 'rejected' | undefined | |
| profile_picture?: string | |
| } | |
| export interface User { | |
| /** Unique identifier for the user */ | |
| userId: string | |
| /** User's email address */ | |
| email?: string | |
| /** User's chosen username */ | |
| username?: string | |
| /** User's full name */ | |
| full_name?: string | |
| /** Bridge platform customer ID */ | |
| bridge_customer_id?: string | |
| kycStatus?: 'verified' | 'pending' | 'rejected' | |
| /** URL to user's profile picture */ | |
| profile_picture?: string | |
| } |
| <div className="flex w-full flex-row items-center justify-between px-2 text-h8 text-gray-1"> | ||
| <div className="flex w-max flex-row items-center gap-1"> | ||
| <Icon name={'transfer'} className="h-4 fill-gray-1" /> | ||
| <label className="font-bold">You will receive</label> | ||
| </div> | ||
| <div className="relative flex flex-1 items-center justify-end gap-1 text-sm font-normal"> | ||
| <div className="flex items-center justify-end gap-1 text-sm font-normal"> |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Refactor fee calculation logic for better maintainability
The current implementation has several maintainability concerns:
- Complex nested ternary expressions reduce readability
- Fee amounts are hardcoded in multiple places
- Account type checks are repeated
Consider extracting the fee calculation logic into a separate function:
+const getFeeAmount = (accountType: string): number => {
+ return accountType === 'iban' ? 1 : 0.5;
+};
+
+const calculateTotalWithFee = (amount: number, accountType: string): number => {
+ const fee = getFeeAmount(accountType);
+ return amount - fee;
+};
-{user?.accounts.find(
- (account) =>
- account.account_identifier.replaceAll(/\s/g, '').toLowerCase() ===
- offrampForm.recipient.replaceAll(/\s/g, '').toLowerCase()
-)?.account_type === 'iban'
- ? offrampType == OfframpType.CASHOUT
- ? utils.formatTokenAmount(parseFloat(usdValue ?? tokenValue ?? '') - 1)
- : tokenPrice &&
- claimLinkData &&
- utils.formatTokenAmount(tokenPrice * parseFloat(claimLinkData.tokenAmount) - 1)
- : /* ... rest of the ternary ... */}
+{(() => {
+ const account = user?.accounts.find(
+ (acc) => acc.account_identifier.replaceAll(/\s/g, '').toLowerCase() ===
+ offrampForm.recipient.replaceAll(/\s/g, '').toLowerCase()
+ );
+ const amount = offrampType === OfframpType.CASHOUT
+ ? parseFloat(usdValue ?? tokenValue ?? '')
+ : tokenPrice && claimLinkData
+ ? tokenPrice * parseFloat(claimLinkData.tokenAmount)
+ : 0;
+ return utils.formatTokenAmount(calculateTotalWithFee(amount, account?.account_type ?? ''));
+})()}Committable suggestion skipped: line range outside the PR's diff.
| <div className="flex flex-col gap-2"> | ||
| <input | ||
| disabled | ||
| value={formatIBANDisplay(getAccountDetailsValue('accountNumber'))} |
There was a problem hiding this comment.
Display US account numbers without IBAN formatting
Using formatIBANDisplay on US account numbers may result in incorrect formatting. Display US account numbers as-is to ensure accuracy.
Apply this diff to correct the display:
- value={formatIBANDisplay(getAccountDetailsValue('accountNumber'))}
+ value={getAccountDetailsValue('accountNumber')}Committable suggestion skipped: line range outside the PR's diff.
| const formatDisplayValue = (value: string) => { | ||
| return formatIBANDisplay(value) | ||
| } |
There was a problem hiding this comment.
Ensure 'formatDisplayValue' handles account types correctly
Currently, formatDisplayValue uses formatIBANDisplay, which may not format US account numbers properly. Modify the function to conditionally format the account number based on the account type.
Apply this diff to update formatDisplayValue:
const formatDisplayValue = (value: string) => {
- return formatIBANDisplay(value)
+ const accountType = getAccountDetailsValue('type')
+ if (accountType === 'iban') {
+ return formatIBANDisplay(value)
+ }
+ return value // For US account numbers, no special formatting
}Committable suggestion skipped: line range outside the PR's diff.
| setValueAs: (value: string) => value?.toLowerCase(), // Store as lowercase | ||
| })} | ||
| className={`custom-input ${ibanErrors.accountNumber ? 'border border-red' : ''}`} | ||
| placeholder={'Bank account'} | ||
| autoComplete="on" | ||
| name="bank-account" | ||
| value={formatDisplayValue(getIbanFormValue('accountNumber') || '')} // Display formatted | ||
| onChange={(e) => { | ||
| // Remove spaces and store lowercase | ||
| const rawValue = e.target.value.replace(/\s/g, '') | ||
| registerIban('accountNumber').onChange({ | ||
| target: { | ||
| value: rawValue.toLowerCase(), | ||
| name: 'accountNumber', | ||
| }, |
There was a problem hiding this comment.
Avoid converting account numbers to lowercase
Converting account numbers to lowercase may lead to incorrect data, especially for numeric US account numbers. Remove the .toLowerCase() conversion to preserve the original account number.
Apply this diff to fix the issue:
{...registerIban('accountNumber', {
required: 'This field is required',
- setValueAs: (value: string) => value?.toLowerCase(), // Store as lowercase
+ setValueAs: (value: string) => value?.replace(/\s/g, ''), // Remove spaces
})}And update the onChange handler:
onChange={(e) => {
// Remove spaces
const rawValue = e.target.value.replace(/\s/g, '')
registerIban('accountNumber').onChange({
target: {
- value: rawValue.toLowerCase(),
+ value: rawValue,
name: 'accountNumber',
},
})
}}📝 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.
| setValueAs: (value: string) => value?.toLowerCase(), // Store as lowercase | |
| })} | |
| className={`custom-input ${ibanErrors.accountNumber ? 'border border-red' : ''}`} | |
| placeholder={'Bank account'} | |
| autoComplete="on" | |
| name="bank-account" | |
| value={formatDisplayValue(getIbanFormValue('accountNumber') || '')} // Display formatted | |
| onChange={(e) => { | |
| // Remove spaces and store lowercase | |
| const rawValue = e.target.value.replace(/\s/g, '') | |
| registerIban('accountNumber').onChange({ | |
| target: { | |
| value: rawValue.toLowerCase(), | |
| name: 'accountNumber', | |
| }, | |
| setValueAs: (value: string) => value?.replace(/\s/g, ''), // Remove spaces | |
| })} | |
| className={`custom-input ${ibanErrors.accountNumber ? 'border border-red' : ''}`} | |
| placeholder={'Bank account'} | |
| autoComplete="on" | |
| name="bank-account" | |
| value={formatDisplayValue(getIbanFormValue('accountNumber') || '')} // Display formatted | |
| onChange={(e) => { | |
| // Remove spaces | |
| const rawValue = e.target.value.replace(/\s/g, '') | |
| registerIban('accountNumber').onChange({ | |
| target: { | |
| value: rawValue, | |
| name: 'accountNumber', | |
| }, |
| useEffect(() => { | ||
| if (getAccountDetailsValue('type') === 'us') { | ||
| setAccountDetailsValue('country', 'USA') | ||
| } | ||
| }, [getAccountDetailsValue('type')]) |
There was a problem hiding this comment.
Fix dependency array in useEffect to properly watch 'type' changes
The dependency array in the useEffect hook uses getAccountDetailsValue('type'), which may not trigger the effect when the 'type' field changes. Instead, use the watch function from React Hook Form to monitor changes to the 'type' field.
Apply this diff to fix the issue:
+ const accountType = watch('type')
useEffect(() => {
- if (getAccountDetailsValue('type') === 'us') {
+ if (accountType === 'us') {
setAccountDetailsValue('country', 'USA')
}
- }, [getAccountDetailsValue('type')])
+ }, [accountType])📝 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.
| useEffect(() => { | |
| if (getAccountDetailsValue('type') === 'us') { | |
| setAccountDetailsValue('country', 'USA') | |
| } | |
| }, [getAccountDetailsValue('type')]) | |
| const accountType = watch('type') | |
| useEffect(() => { | |
| if (accountType === 'us') { | |
| setAccountDetailsValue('country', 'USA') | |
| } | |
| }, [accountType]) |
There was a problem hiding this comment.
Actionable comments posted: 26
🧹 Outside diff range and nitpick comments (19)
.github/workflows/tests.yml (3)
19-24: Add dependency caching to speed up workflow executionThe workflow could benefit from caching pnpm dependencies to improve execution time.
- uses: pnpm/action-setup@v2 with: version: 8 + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- - name: Install Dependencies run: pnpm install
29-33: Add coverage threshold checksWhile coverage artifacts are being uploaded, there's no verification of coverage thresholds. Consider adding coverage checks to maintain code quality.
- name: Run Tests - run: pnpm test + run: pnpm test -- --coverage --coverageThreshold='{"global":{"branches":"80","functions":"80","lines":"80","statements":"80"}}' - name: Upload Coverage uses: actions/upload-artifact@v4 with: name: coverage path: coverage/ + if: always() # Upload coverage even if tests fail
9-11: Consider adding a test matrix for multiple Node.js versionsTesting against multiple Node.js versions would help ensure compatibility.
jobs: test: runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x, 20.x] + fail-fast: false steps:Then update the Node.js setup step to use:
node-version: ${{ matrix.node-version }}.env.example (1)
1-23: Add documentation for environment variablesConsider adding comments to describe:
- The purpose of each variable
- Required vs optional variables
- Format/structure requirements for values
- Development vs production considerations
Would you like me to help generate comprehensive documentation for these environment variables?
🧰 Tools
🪛 Gitleaks (8.21.2)
3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
6-6: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
11-11: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
README.md (1)
35-66: Well-structured testing documentation with room for enhancementThe testing documentation is clear and well-organized. Consider enhancing it with:
- Information about test coverage requirements
- Guidelines for mocking and test data
- Best practices for testing async code
- Instructions for debugging tests
Would you like me to provide examples for these additional sections?
🧰 Tools
🪛 LanguageTool
[duplication] ~52-~52: Possible typo: you repeated a word
Context: ...ts__directories next to the code they test - Test files should be named.test.tsor...(ENGLISH_WORD_REPEAT_RULE)
src/utils/__tests__/format.utils.test.ts (4)
4-22: Consider adding more edge cases to sanitizeBankAccount tests.While the basic cases are covered, consider adding tests for:
- Special characters beyond spaces/hyphens/dots (e.g., @, #, $)
- Numbers-only input
- Mixed alphanumeric input
- Very long input strings
- Non-string input types (numbers, objects)
describe('sanitizeBankAccount', () => { + it('should handle special characters', () => { + expect(sanitizeBankAccount('BE68@539#007$547')).toBe('be68539007547') + }) + + it('should handle numbers-only input', () => { + expect(sanitizeBankAccount('12345')).toBe('12345') + }) + + it('should handle mixed alphanumeric input', () => { + expect(sanitizeBankAccount('abc123DEF')).toBe('abc123def') + }) + + it('should handle very long input', () => { + expect(sanitizeBankAccount('a'.repeat(100))).toBe('a'.repeat(100)) + }) + + it('should handle non-string input', () => { + expect(sanitizeBankAccount(123 as any)).toBe('123') + expect(sanitizeBankAccount({} as any)).toBe('') + })
25-38: Add validation tests for IBAN format.The current tests focus on formatting, but consider adding validation tests for:
- Invalid IBAN format (e.g., wrong country code)
- IBAN length constraints (too short/long)
- Invalid characters in IBAN
describe('IBAN format', () => { + it('should handle invalid country code', () => { + expect(formatBankAccountDisplay('XX68539007547034', 'iban')).toBe('XX68 5390 0754 7034') + }) + + it('should handle minimum/maximum IBAN length', () => { + // Minimum length IBAN (Norway - 15 chars) + expect(formatBankAccountDisplay('NO9386011117947', 'iban')).toBe('NO93 8601 1117 947') + // Maximum length IBAN (Malta - 31 chars) + expect(formatBankAccountDisplay('MT84MALT011000012345MTLCAST001S', 'iban')) + .toBe('MT84 MALT 0110 0001 2345 MTLC AST0 01S') + }) + + it('should handle invalid characters', () => { + expect(formatBankAccountDisplay('BE68$390@754#034', 'iban')).toBe('BE68 5390 0754 7034') + })
40-53: Add validation tests for US account format.Consider adding tests for:
- Invalid routing number length (should be exactly 9 digits)
- Invalid account number length (typically 10-12 digits)
- Special characters in account/routing numbers
describe('US account format', () => { + it('should handle invalid routing number length', () => { + expect(formatBankAccountDisplay('12345678', 'us')).toBe('12345678') + expect(formatBankAccountDisplay('1234567890', 'us')).toBe('123456789-0') + }) + + it('should handle invalid account number length', () => { + const routing = '123456789' + expect(formatBankAccountDisplay(routing + '123', 'us')).toBe('123456789-123') + expect(formatBankAccountDisplay(routing + '1'.repeat(15), 'us')) + .toBe('123456789-' + '1'.repeat(15)) + }) + + it('should handle special characters', () => { + expect(formatBankAccountDisplay('123@456#789$123456789', 'us')) + .toBe('123456789-123456789') + })
55-67: Enhance auto-detection test coverage.The auto-detection tests should be more comprehensive. Consider adding:
- Tests for ambiguous input that could match either format
- Tests for invalid input that matches neither format
- More edge cases beyond undefined
describe('Auto-detection', () => { + it('should handle ambiguous input', () => { + // Could be either a short IBAN or US account + expect(formatBankAccountDisplay('123456789')).toBe('123456789') + }) + + it('should handle invalid format input', () => { + expect(formatBankAccountDisplay('invalid-input')).toBe('INVALID-INPUT') + }) + + it('should handle various edge cases', () => { + expect(formatBankAccountDisplay(null as any)).toBe('') + expect(formatBankAccountDisplay(123 as any)).toBe('123') + expect(formatBankAccountDisplay({} as any)).toBe('') + })src/components/Profile/index.tsx (1)
544-583: Add defensive programming checksThe code assumes
user.pointsPerReferralis always defined and iterable. Add null checks to prevent runtime errors.Add null checks and provide fallback UI:
- user?.pointsPerReferral.map( + user?.pointsPerReferral?.length ? ( + user.pointsPerReferral.map( (referral: { address: string; points: number; totalReferrals: number }, index: number ) => ( // ... existing code ... )) + ) : ( + <div className="text-center text-h8">No referrals yet</div> + )src/components/Global/LinkAccountComponent/index.tsx (3)
15-15: Remove unused importThe
USBankAccountInputcomponent is imported but never used in the code.-import { USBankAccountInput } from '../USBankAccountInput'
163-167: Remove debug console.log statementsMultiple console.log statements are present throughout the code. These should be removed or replaced with proper logging for production code.
Consider using a logging utility that can be configured based on the environment:
-console.log('Starting form submission with user data:', { - user, - kycStatus: user?.user?.kycStatus, - accounts: user?.accounts, -}) +logger.debug('Starting form submission with user data:', { + kycStatus: user?.user?.kycStatus, + accountsCount: user?.accounts?.length, +})Also applies to: 177-180, 189-199, 205-206, 210-211, 287-288
478-480: Add ZIP code format validationThe ZIP code field should validate the input format to ensure it matches US ZIP code patterns (5 digits or 5+4 format).
{...registerAccountDetails('postalCode', { required: 'ZIP code is required', + pattern: { + value: /^\d{5}(-\d{4})?$/, + message: 'Please enter a valid ZIP code (e.g., 12345 or 12345-6789)' + } })}src/components/Offramp/Confirm.view.tsx (3)
Line range hint
251-333: Enhance error messages for better user experienceThe error handling for cross-chain scenarios is thorough, but some error messages could be more user-friendly and actionable.
Consider these improvements:
- errorMessage = - 'This token is not supported for cross-chain transfers. Please try a different token.' + errorMessage = + 'This token cannot be converted to your preferred currency. Please try using a popular token like ETH or USDC.'
785-790: Extract fee calculation logicThe amount received calculation is tightly coupled with the display logic, making it hard to test and maintain.
Consider creating a dedicated fee calculation service:
- Create a new file
src/services/fee.service.ts- Extract fee calculation logic:
export interface FeeConfig { sepaFee: number; achFee: number; } export const calculateFeeAmount = (accountType: string, config: FeeConfig): number => { return accountType === 'iban' ? config.sepaFee : config.achFee; }; export const calculateAmountReceived = (total: number, accountType: string, config: FeeConfig): number => { const fee = calculateFeeAmount(accountType, config); return total - fee; };
873-882: Enhance error message clarityThe error display implementation is good, but the messages could be more specific and actionable.
Consider these improvements:
- 'This token cannot be cashed out directly.{' '} + 'This token cannot be processed for bank withdrawal. For assistance with supported tokens,{' '}src/app/api/bridge/external-account/create-external-account/route.ts (3)
14-15: Simplify request data handling by destructuring directlyYou can destructure the request body directly without assigning it to
requestData, reducing unnecessary variables.Apply this diff to simplify the code:
- const requestData = await request.json() - const { accountType, accountDetails, address, accountOwnerName } = requestData + const { accountType, accountDetails, address, accountOwnerName } = await request.json()
99-101: Eliminate redundant re-reading of response text
responseTexthas already been read and assigned at line 90. Reading it again can cause errors as the stream is exhausted after the first read.Apply this diff to remove redundant code:
- const responseText = await response.text() console.log('Error response text:', responseText)
204-208: Handle JSON parsing errors gracefullyParsing the response without a try-catch block may lead to unhandled exceptions if the response is not valid JSON.
Apply this diff to safely parse the response:
- const data = JSON.parse(responseText) - console.log('Successfully created external account:', data) + let data + try { + data = JSON.parse(responseText) + console.log('Successfully created external account with ID:', data.id) + } catch (e) { + console.error('Error parsing response:', e) + return new NextResponse('Failed to parse Bridge API response', { status: 500 }) + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (15)
.env.example(1 hunks).github/workflows/tests.yml(1 hunks)README.md(1 hunks)jest.setup.ts(1 hunks)package.json(2 hunks)src/app/api/bridge/external-account/create-external-account/route.ts(4 hunks)src/components/Global/GeneralRecipientInput/index.tsx(3 hunks)src/components/Global/LinkAccountComponent/index.tsx(7 hunks)src/components/Offramp/Confirm.view.tsx(6 hunks)src/components/Offramp/Offramp.consts.ts(1 hunks)src/components/Offramp/Success.view.tsx(1 hunks)src/components/Profile/index.tsx(1 hunks)src/interfaces/interfaces.ts(2 hunks)src/utils/__tests__/format.utils.test.ts(1 hunks)src/utils/format.utils.ts(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- jest.setup.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/Global/GeneralRecipientInput/index.tsx
🧰 Additional context used
📓 Learnings (1)
src/components/Offramp/Offramp.consts.ts (2)
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#420
File: src/components/Offramp/Offramp.consts.ts:27-28
Timestamp: 2024-11-12T09:39:20.720Z
Learning: In `src/components/Offramp/Offramp.consts.ts`, the `MIN_CASHOUT_LIMIT` is set to $10 because smaller amounts are impractical due to approximately $1 fee per cashout.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#420
File: src/components/Offramp/Offramp.consts.ts:27-28
Timestamp: 2024-11-12T09:39:20.720Z
Learning: In `src/components/Offramp/Offramp.consts.ts`, the `MAX_CASHOUT_LIMIT` is set to $101,000 as a safety measure; it can be increased over time if needed, though it's unlikely to be exceeded.
🪛 Gitleaks (8.21.2)
.env.example
3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
6-6: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
11-11: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🪛 LanguageTool
README.md
[duplication] ~52-~52: Possible typo: you repeated a word
Context: ...ts__directories next to the code they test - Test files should be named.test.tsor...
(ENGLISH_WORD_REPEAT_RULE)
🔇 Additional comments (15)
src/utils/format.utils.ts (1)
1-30: Add comprehensive test coverage
As noted in previous reviews, test coverage is still missing for these utility functions.
Let's verify the current test coverage:
#!/bin/bash
# Check for existing test files
fd -e test.ts -e spec.ts format.utils
# Look for any test cases related to these functions
rg -l "describe.*sanitizeBankAccount|describe.*formatBankAccountDisplay" --type ts.env.example (1)
1-23: Verify and revoke exposed credentials
Given that this is marked as a "temp commit", please verify if any of the hardcoded API keys and secrets are real credentials. If they are:
- Revoke them immediately
- Generate new credentials
- Update all necessary services
- Consider this a security incident
Special attention to:
- Sentry DSN (appears to be a real project URL)
- Infura API key
- WalletConnect project ID
🧰 Tools
🪛 Gitleaks (8.21.2)
3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
6-6: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
11-11: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
README.md (1)
32-66:
Documentation changes should not be marked as temporary
The PR title suggests this is a "temp commit, not fully done" but documentation changes should be complete and accurate when merged to avoid confusion for other developers.
🧰 Tools
🪛 LanguageTool
[duplication] ~52-~52: Possible typo: you repeated a word
Context: ...ts__directories next to the code they test - Test files should be named.test.tsor...
(ENGLISH_WORD_REPEAT_RULE)
src/components/Offramp/Offramp.consts.ts (1)
27-27: Temporary debugging changes should not be committed
The PR title indicates this is a temporary commit. Modifying production constants for debugging purposes should be done locally rather than committed, especially when it contradicts established business logic.
Let's check if there are any other temporary changes in the codebase:
src/utils/__tests__/format.utils.test.ts (1)
1-4: Well-structured test organization!
The test file follows Jest best practices with clear describe blocks and proper imports.
package.json (3)
90-102: Verify Jest setup file and consider additional test patterns.
The Jest configuration looks good but requires verification of the setup file and could benefit from additional test patterns.
Let's verify the setup file exists and check for common test patterns:
Consider adding these additional test patterns to be more inclusive:
"testMatch": [
"**/__tests__/**/*.test.[jt]s?(x)",
- "**/?(*.)+(spec|test).[jt]s?(x)"
+ "**/?(*.)+(spec|test).[jt]s?(x)",
+ "**/tests/**/*.[jt]s?(x)",
+ "**/__tests__/**/*.[jt]s?(x)"
]✅ Verification successful
Jest setup and test patterns are properly configured
The verification shows:
jest.setup.tsexists with proper testing library imports and console mocking setup- Current test patterns successfully match existing test files (e.g.,
src/utils/__tests__/format.utils.test.ts) - The suggested additional patterns would be redundant since:
**/__tests__/**/*.test.[jt]s?(x)already covers the__tests__directory**/?(*.)+(spec|test).[jt]s?(x)covers both.testand.specfiles
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if jest.setup.ts exists and contains necessary imports
fd -t f "jest.setup.ts" --exec cat {}
# Look for existing test files to ensure patterns match
fd -e test.ts -e test.tsx -e spec.ts -e spec.tsx
Length of output: 380
Line range hint 1-102: Consider completing the implementation before merging.
The PR title indicates this is a temporary commit. While the Jest setup looks complete and well-structured, consider:
- Completing any pending changes
- Adding some initial tests to validate the setup
- Updating the PR title once it's ready for review
Let's check for any existing test files:
83-89: Verify TypeScript version compatibility.
The TypeScript version 5.6.3 is quite recent. Ensure it's compatible with all dependencies, especially Next.js and Jest.
Let's check for potential version conflicts:
✅ Verification successful
TypeScript 5.6.3 is compatible with the project setup
The TypeScript version is compatible with:
- Next.js 14.2.18 (which supports TypeScript 5.x)
- The project's tsconfig.json configuration is standard and doesn't use any deprecated features
- All @types packages are at compatible versions
- Jest and ts-jest versions are aligned for TypeScript 5.x support
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check Next.js TypeScript requirements
rg -A 5 '"typescript":' "package.json"
# Check for TypeScript-related entries in package-lock.json
fd -t f "package-lock.json" --exec rg -A 5 '"typescript":'
Length of output: 312
Script:
#!/bin/bash
# Check Next.js version and its dependencies
rg '"next":' package.json
# Check for any TypeScript configuration files
fd tsconfig
# Look for any TypeScript-related errors or configurations in Next.js config
fd -t f "next.config" --exec cat {}
Length of output: 5109
Script:
#!/bin/bash
# Let's check the content of tsconfig.json to verify TypeScript configuration
cat tsconfig.json
# Check for any TypeScript-specific Next.js requirements in package.json
rg "@types/node|@types/react|@types/react-dom" package.json
Length of output: 1143
src/components/Offramp/Success.view.tsx (1)
60-60: Verify layout behavior with varying content lengths
The change from w-1/3 to w-max improves flexibility but should be tested with:
- Long labels/translations
- Different viewport sizes
- RTL languages
Consider adding a maximum width constraint (max-w-[...]) to prevent potential layout issues with very long content.
src/interfaces/interfaces.ts (1)
8-8: LGTM: Optional message property addition
The optional message property is a good addition to the IResponse interface, following common API response patterns.
src/components/Global/LinkAccountComponent/index.tsx (3)
45-46: LGTM: Improved loading state management
The loading state implementation with specific states provides better user feedback during different stages of the account linking process.
Also applies to: 371-373
331-333: LGTM: Improved account number formatting
The formatDisplayValue function now correctly handles both IBAN and US account numbers using the formatBankAccountDisplay utility.
Line range hint 1-1: Address temporary commit status
The PR title indicates this is a temporary commit. Consider completing any remaining tasks and removing the temporary status before merging.
src/components/Offramp/Confirm.view.tsx (1)
685-690: LGTM! Clean implementation of bank account display
The bank account display implementation is well-structured and uses the new formatting utility for consistency.
src/app/api/bridge/external-account/create-external-account/route.ts (1)
143-155: Validate and handle the accounts data properly
Ensure that accounts is an array before using .find(), and verify that the comparison logic accurately identifies the existing account.
Run the following script to confirm accounts is an array:
Replace ${YOUR_API_BASE_URL} and test_customer_id with appropriate values.
✅ Verification successful
Array validation is properly implemented
The code already has sufficient validation and proper handling of the accounts data:
- In
get-all-for-customerId/route.ts, accounts is initialized as an array with a fallback:const accounts = responseData.data || [] - Before using
.find(), the code checks ifallAccounts.okis true - The
IBridgeAccountinterface is well-defined with proper typing for all fields - The comparison logic in
.find()correctly matches the account types and details according to the interface definition
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that 'accounts' is an array.
curl -s -X POST "${YOUR_API_BASE_URL}/api/bridge/external-account/get-all-for-customerId" \
-H "Content-Type: application/json" \
-d '{"customerId": "test_customer_id"}' | jq 'type'
Length of output: 155
Script:
#!/bin/bash
# Let's analyze how accounts is obtained and validated in the codebase
rg -A 5 "const accounts\s*="
# Also check for any type definitions or interfaces related to accounts
ast-grep --pattern 'interface IBridgeAccount {
$$$
}'
# Check how the accounts data is fetched and processed
rg "get-all-for-customerId" -A 10
Length of output: 6661
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '21.1.0' |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Consider using an LTS version of Node.js
Node.js 21.1.0 is a very recent version and might be unstable for production use. Consider using an LTS version like 20.x for better stability.
- node-version: '21.1.0'
+ node-version: '20.x'📝 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.
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '21.1.0' | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20.x' |
| - name: Run Tests | ||
| run: pnpm test |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add timeout and error handling for tests
The test step should have a timeout to prevent hanging builds and proper error handling.
- name: Run Tests
- run: pnpm test
+ run: pnpm test
+ timeout-minutes: 10
+ continue-on-error: false📝 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.
| - name: Run Tests | |
| run: pnpm test | |
| - name: Run Tests | |
| run: pnpm test | |
| timeout-minutes: 10 | |
| continue-on-error: false |
.github/workflows/tests.yml
Outdated
| on: | ||
| push: | ||
| branches: ['**'] | ||
| pull_request: | ||
| branches: [main, develop] |
There was a problem hiding this comment.
💡 Codebase verification
Based on the shell script results, I can now provide a final response as there's clear evidence of the workflow configurations in the repository.
Workflow trigger optimization needed for both CI workflows
The current configuration runs workflows on all branch pushes ('**'), which is resource-intensive. Additionally, the repository has two workflows with overlapping triggers:
tests.yml: Runs on all pushes and PRs to main/developprettier.yml: Runs on all pushes (with PR triggers commented out)
Suggested changes:
- Limit push triggers to important branches (main, develop) and feature branch patterns
- Enable pull_request triggers for the prettier workflow to catch formatting issues early
- Consider combining both workflows to reduce CI overhead
🔗 Analysis chain
Review the workflow trigger configuration
The current configuration runs on all pushes to any branch, which might be resource-intensive. Consider limiting this to specific branches or patterns.
on:
push:
- branches: ['**']
+ branches: [main, develop, 'feature/**']
pull_request:
branches: [main, develop]🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for existing workflow configurations
fd -e yml -e yaml . .github/workflows/ --exec grep -l "on:" {} \; | while read -r file; do
echo "=== $file ==="
cat "$file" | grep -A 5 "on:"
done
Length of output: 1327
| if (!type) { | ||
| type = /^[A-Z]{2}/i.test(sanitized) ? 'iban' : 'us' | ||
| } |
There was a problem hiding this comment.
Improve IBAN detection logic
The current IBAN detection is oversimplified and could lead to false positives. Not all strings starting with two letters are valid IBANs.
Consider using a more robust IBAN validation:
- if (!type) {
- type = /^[A-Z]{2}/i.test(sanitized) ? 'iban' : 'us'
- }
+ if (!type) {
+ // IBAN format: country code (2 letters) + check digits (2 numbers) + BBAN (up to 30 chars)
+ type = /^[A-Z]{2}\d{2}[A-Z0-9]{1,30}$/i.test(sanitized) ? 'iban' : 'us'
+ }📝 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.
| if (!type) { | |
| type = /^[A-Z]{2}/i.test(sanitized) ? 'iban' : 'us' | |
| } | |
| if (!type) { | |
| // IBAN format: country code (2 letters) + check digits (2 numbers) + BBAN (up to 30 chars) | |
| type = /^[A-Z]{2}\d{2}[A-Z0-9]{1,30}$/i.test(sanitized) ? 'iban' : 'us' | |
| } |
| export const sanitizeBankAccount = (value: string | undefined): string => { | ||
| if (!value) return '' | ||
| return value.replace(/[\s\-\._]/g, '').toLowerCase() | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Enhance type safety and add documentation
The function needs better documentation and type safety improvements.
Apply these changes:
+/**
+ * Sanitizes a bank account number by removing whitespace and special characters.
+ * @param value - The bank account number to sanitize
+ * @returns A cleaned string with all whitespace and special characters removed
+ */
-export const sanitizeBankAccount = (value: string | undefined): string => {
+export const sanitizeBankAccount = (value?: string | null): string => {
if (!value) return ''
- return value.replace(/[\s\-\._]/g, '').toLowerCase()
+ return value.replace(/[\s\-\._]/g, '') // Preserve case as some bank accounts are case-sensitive
}📝 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.
| export const sanitizeBankAccount = (value: string | undefined): string => { | |
| if (!value) return '' | |
| return value.replace(/[\s\-\._]/g, '').toLowerCase() | |
| } | |
| /** | |
| * Sanitizes a bank account number by removing whitespace and special characters. | |
| * @param value - The bank account number to sanitize | |
| * @returns A cleaned string with all whitespace and special characters removed | |
| */ | |
| export const sanitizeBankAccount = (value?: string | null): string => { | |
| if (!value) return '' | |
| return value.replace(/[\s\-\._]/g, '') // Preserve case as some bank accounts are case-sensitive | |
| } |
| console.log('Creating external account with:', { | ||
| customerId, | ||
| accountType, | ||
| accountDetails, | ||
| address, | ||
| accountOwnerName, | ||
| }) |
There was a problem hiding this comment.
Avoid logging sensitive information
Logging sensitive data such as accountDetails, address, and accountOwnerName can lead to security risks. It's best to limit the logged information.
Apply this diff to sanitize the logs:
- console.log('Creating external account with:', {
- customerId,
- accountType,
- accountDetails,
- address,
- accountOwnerName,
- })
+ console.log('Creating external account for customer:', customerId)📝 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.
| console.log('Creating external account with:', { | |
| customerId, | |
| accountType, | |
| accountDetails, | |
| address, | |
| accountOwnerName, | |
| }) | |
| console.log('Creating external account for customer:', customerId) |
| console.log('Sending request to Bridge API:', { | ||
| url: `https://api.bridge.xyz/v0/customers/${customerId}/external_accounts`, | ||
| method: 'POST', | ||
| headers: { | ||
| 'Idempotency-Key': idempotencyKey, | ||
| 'Api-Key': '[REDACTED]', | ||
| Accept: 'application/json', | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| body: JSON.stringify(body), | ||
| }) |
There was a problem hiding this comment.
Prevent exposure of sensitive headers and body in logs
Logging headers like Idempotency-Key and the request body may expose sensitive information. It's safer to log minimal details.
Apply this diff to adjust the logging:
- console.log('Sending request to Bridge API:', {
- url: `https://api.bridge.xyz/v0/customers/${customerId}/external_accounts`,
- method: 'POST',
- headers: {
- 'Idempotency-Key': idempotencyKey,
- 'Api-Key': '[REDACTED]',
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(body),
- })
+ console.log('Sending request to Bridge API for customer:', customerId)📝 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.
| console.log('Sending request to Bridge API:', { | |
| url: `https://api.bridge.xyz/v0/customers/${customerId}/external_accounts`, | |
| method: 'POST', | |
| headers: { | |
| 'Idempotency-Key': idempotencyKey, | |
| 'Api-Key': '[REDACTED]', | |
| Accept: 'application/json', | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify(body), | |
| }) | |
| console.log('Sending request to Bridge API for customer:', customerId) |
| const data = await response.json() | ||
|
|
||
| const data = JSON.parse(responseText) | ||
| console.log('Successfully created external account:', data) |
There was a problem hiding this comment.
Limit logging of sensitive information
Logging the entire data object may expose sensitive details. Log only the necessary identifiers or confirmation messages.
Apply this diff to adjust the logging:
- console.log('Successfully created external account:', data)
+ console.log('Successfully created external account with ID:', data.id)Committable suggestion skipped: line range outside the PR's diff.
| const allAccounts = await fetch(`/api/bridge/external-account/get-all-for-customerId`, { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| body: JSON.stringify({ | ||
| customerId, | ||
| }), | ||
| }) |
There was a problem hiding this comment.
Use absolute URLs for server-side fetch calls
When making server-side fetch calls to your own API routes, relative URLs may not resolve correctly. Use absolute URLs instead.
Consider modifying the fetch call:
- const allAccounts = await fetch(`/api/bridge/external-account/get-all-for-customerId`, {
+ const allAccounts = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/bridge/external-account/get-all-for-customerId`, {Ensure that NEXT_PUBLIC_BASE_URL is defined in your environment variables.
Committable suggestion skipped: line range outside the PR's diff.
| console.log('Found matching existing account:', existingAccount) | ||
| return new NextResponse( | ||
| JSON.stringify({ | ||
| success: true, | ||
| data: existingAccount, | ||
| }), | ||
| { | ||
| status: 200, | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| } | ||
| ) |
There was a problem hiding this comment.
Avoid returning full account details in responses
Returning sensitive account data can pose security risks. Return only the necessary information to the client.
Apply this diff to sanitize the response:
return new NextResponse(
JSON.stringify({
success: true,
data: {
id: existingAccount.id,
accountType: existingAccount.account_details.type,
last4: existingAccount.account_details.last_4,
// Include only non-sensitive fields
},
}),
{
status: 200,
headers: {
'Content-Type': 'application/json',
},
}
)Committable suggestion skipped: line range outside the PR's diff.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (1)
.github/workflows/prettier.yml (1)
5-5: Consider refining the branch pattern.The current pattern
['**']will trigger the workflow for PRs against any branch. Consider limiting this to your main development branches (e.g.,main,develop) to avoid unnecessary workflow runs.- branches: ['**'] + branches: ['main', 'develop']
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
.github/workflows/prettier.yml(1 hunks).github/workflows/tests.yml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/tests.yml
🔇 Additional comments (1)
.github/workflows/prettier.yml (1)
4-5: LGTM! Efficient workflow trigger configuration.
Changing the trigger from push to pull_request is a good practice as it:
- Prevents duplicate workflow runs (PR creation + push)
- Catches formatting issues during code review
- Aligns with the introduction of the new test workflow
| } else if (/^[0-9]{1,17}$/.test(sanitizedInput)) { | ||
| type = 'us' | ||
| isValid = await utils.validateBankAccount(recipient) | ||
| if (!isValid) { | ||
| errorMessage.current = | ||
| 'Invalid bank account. For US bank accounts, enter your bank routing number (9 digits) followed by your account number (example: 1112223330001234567 where routing number is: 111222333 and account number: 0001234567)' | ||
| } | ||
| isValid = true |
| placeholder={placeholder} | ||
| validate={checkAddress} | ||
| onUpdate={onInputUpdate} | ||
| className={className} | ||
| autoComplete="on" | ||
| name="bank-account" | ||
| suggestions={getSuggestions(recipientType.current)} | ||
| infoText={infoText} | ||
| formatDisplayValue={formatDisplayValue} |
There was a problem hiding this comment.
Input needs to be reworked for: autocomplete="bank-account-number"
| <div className="flex items-center gap-1"> | ||
| $ | ||
| {user?.accounts.find( | ||
| (account) => | ||
| account.account_identifier.replaceAll(/\s/g, '').toLowerCase() === | ||
| offrampForm.recipient.replaceAll(/\s/g, '').toLowerCase() | ||
| )?.account_type === 'iban' | ||
| ? offrampType == _consts.OfframpType.CASHOUT |
There was a problem hiding this comment.
this needs to be standardized with new format utils
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (8)
src/utils/token.utils.ts (1)
27-32: Add input validation and reuse constantsThe function looks good but could benefit from some improvements:
+const NATIVE_TOKEN_ADDRESS = '0x0000000000000000000000000000000000000000' + export const getSquidTokenAddress = (tokenAddress: string): string => { + if (!tokenAddress.match(/^0x[0-9a-fA-F]{40}$/)) { + throw new Error('Invalid Ethereum address format'); + } - return tokenAddress === '0x0000000000000000000000000000000000000000' + return tokenAddress === NATIVE_TOKEN_ADDRESS ? SQUID_ETH_ADDRESS : tokenAddress.toLowerCase() }src/components/Request/Pay/Views/Initial.view.tsx (2)
Line range hint
141-167: Consider consolidating error state updatesThe error handling sets multiple state variables independently. Consider creating a single function to handle all error-related state updates to ensure consistency and maintainability.
+ const handleEstimateTxError = () => { + setErrorState({ showError: true, errorMessage: ERR_NO_ROUTE }) + setIsFeeEstimationError(true) + setSlippagePercentage(undefined) + setXChainUnsignedTxs(undefined) + setTxFee('0') + } try { // ... existing code ... } catch (error) { - setErrorState({ showError: true, errorMessage: ERR_NO_ROUTE }) - setIsFeeEstimationError(true) - setSlippagePercentage(undefined) - setXChainUnsignedTxs(undefined) - setTxFee('0') + handleEstimateTxError() }
Line range hint
284-321: Enhance error handling specificity in transaction submissionThe current error handling uses a generic error handler. Consider handling specific error cases (e.g., insufficient balance, network errors, signature rejections) to provide more targeted user feedback.
try { // ... existing code ... } catch (error) { + if (error instanceof Error) { + if (error.message.includes('insufficient balance')) { + setErrorState({ + showError: true, + errorMessage: 'Insufficient balance to complete the transaction', + }) + } else if (error.message.includes('user rejected')) { + setErrorState({ + showError: true, + errorMessage: 'Transaction was rejected in wallet', + }) + } else { const errorString = ErrorHandler(error) setErrorState({ showError: true, errorMessage: errorString, }) + } + } console.error('Error while submitting request link fulfillment:', error) }src/components/Claim/Link/Initial.view.tsx (3)
179-196: Consider improving error handling and logging.While the routing logic is functional, there are a few areas for improvement:
- The debug log on line 183 should be removed or replaced with proper logging.
- The error handling could be more specific about why routing through USDC Optimism is necessary.
-console.log('Debug - Routing through USDC Optimism') +logger.info('Fallback: Routing through USDC Optimism due to unsupported token/chain combination')
331-376: Enhance route fetching implementation.The route fetching logic has been improved, but there are some potential enhancements:
- Consider extracting the hardcoded addresses to constants
- The error message could be more specific about why the route wasn't found
- route.toToken.toLowerCase() === claimLinkData.tokenAddress.toLowerCase() && + areTokenAddressesEqual(route.toToken, claimLinkData.tokenAddress) && - errorMessage: 'No route found for the given token pair.', + errorMessage: `No route found from ${fromToken} to ${toToken || selectedTokenAddress}`,
455-459: Consider adding input validation.The recipient type assignment logic could benefit from additional validation:
- Add type checking for the recipient address
- Consider handling edge cases where the address might be empty string vs undefined
- if (!update.recipient.address) { + if (!update.recipient.address?.trim()) { setRecipientType('address') } else { setRecipientType(update.type) }src/components/Offramp/Confirm.view.tsx (2)
Line range hint
252-334: Enhance user-facing error messagesWhile the error handling improvements are good, consider making the error messages more user-friendly and actionable:
- errorMessage: 'This token does not support cross-chain transfers. Please try a different token.', + errorMessage: 'This token cannot be transferred across chains. Please use a supported token like USDC or ETH.', - errorMessage = 'Unable to fetch token data' + errorMessage = 'We could not verify this token. Please try again or use a different token.' - errorMessage = 'Failed to setup cross-chain transfer' + errorMessage = 'Unable to complete the transfer. Please try again or contact support if the issue persists.'
875-893: Improve error message accessibilityWhile the error handling UI improvements are good, consider enhancing accessibility:
- <div className="text-center"> + <div className="text-center" role="alert" aria-live="polite"> - <label className="text-h8 font-normal text-red"> + <div className="text-h8 font-normal text-red"> - <CrispButton className="text-blue-600 underline"> + <CrispButton className="text-blue-600 underline" aria-label="Contact support via chat">
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
src/components/Claim/Link/Initial.view.tsx(6 hunks)src/components/Offramp/Confirm.view.tsx(8 hunks)src/components/Offramp/Offramp.consts.ts(1 hunks)src/components/Request/Pay/Views/Initial.view.tsx(2 hunks)src/utils/token.utils.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/Offramp/Offramp.consts.ts
🧰 Additional context used
📓 Learnings (2)
src/components/Claim/Link/Initial.view.tsx (1)
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#545
File: src/components/Global/GeneralRecipientInput/index.tsx:118-126
Timestamp: 2024-11-26T12:06:11.603Z
Learning: For bank account input fields, use `autocomplete="bank-account-number"` when the recipient type is `'us'` or `'iban'`.
src/components/Request/Pay/Views/Initial.view.tsx (3)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-11-12T09:39:20.720Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-11-12T09:39:20.720Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(...)` return strings, ensuring that `calculatedFee` consistently returns a string without the need for additional type conversion.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:67-74
Timestamp: 2024-11-12T09:39:20.720Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, the functions `getDefaultProvider` and `getTokenContractDetails` used in `fetchTokenSymbol` do not throw errors but can return `undefined`. Additional error handling is unnecessary since this is already handled in the code.
🔇 Additional comments (6)
src/utils/token.utils.ts (1)
24-25: Verify the standardized Squid ETH address
The SQUID_ETH_ADDRESS appears to be a special identifier. Let's verify this is the correct and standardized address used across the ecosystem.
✅ Verification successful
Let me gather more context about this address by searching for related documentation and checking if this is a standard ETH placeholder address used in other projects.
Based on the search results, I can now provide a final response as we have sufficient evidence about the usage of this address pattern in the codebase.
The SQUID_ETH_ADDRESS is correctly implemented
This is a standardized address pattern used to represent native ETH/native tokens in the Squid protocol. The evidence shows:
- It's consistently used across the codebase for native token handling
- The address is properly normalized in
areTokenAddressesEqualfunction - It's listed in
nativeCurrencyAddressesarray along with the zero address - The pattern
0xeeee...is used in both uppercase and lowercase forms but refers to the same concept
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other occurrences of this address in the codebase
rg -i "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
# Search for any documentation or comments about this address
rg -i "squid.*eth.*address" -A 2 -B 2
Length of output: 3261
Script:
#!/bin/bash
# Search for comments or documentation explaining this address pattern
rg -i "0xeeee|native eth|eth address" -A 2 -B 2
# Search for any configuration or documentation files
fd -e md -e json . -x grep -l -i "0xeeee|native eth|eth address" {} \;
Length of output: 1755
src/components/Request/Pay/Views/Initial.view.tsx (1)
26-26: LGTM! Good refactoring of cross-chain support check
Moving the cross-chain support check logic to a separate utility function improves code maintainability and reusability.
Also applies to: 131-134
src/components/Claim/Link/Initial.view.tsx (3)
39-40: LGTM! Clean import of utility functions.
The new utility imports improve code organization by moving token-related functions to a dedicated utils file.
148-151: LGTM! Improved code maintainability.
The refactoring of token support check into a utility function enhances code reusability and maintainability.
440-459: Verify recipient type assignment logic.
The recipient type handling has been updated to handle empty addresses correctly. However, we should verify that this change doesn't affect existing functionality.
✅ Verification successful
Let me gather more context about the GeneralRecipientInput component and its usage.
The recipient type handling is correctly implemented and safe.
The code inspection reveals that the recipient type logic in Initial.view.tsx aligns perfectly with the GeneralRecipientInput component's implementation. The component internally manages recipient types through a robust validation system, and the parent component's handling of empty addresses by setting type to 'address' is the correct fallback behavior. The update logic properly propagates the type from the GeneralRecipientInput's validation results in all other cases.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for any other components that might be affected by the recipient type changes
# Search for other components using GeneralRecipientInput
ast-grep --pattern 'onUpdate={$_} // inside GeneralRecipientInput'
# Search for direct recipient type assignments
rg "setRecipientType\(" -A 2
Length of output: 567
Script:
#!/bin/bash
# Search for GeneralRecipientInput component definition and usage
ast-grep --pattern 'type GeneralRecipientUpdate = {
$$$
}'
# Search for GeneralRecipientInput component implementations
ast-grep --pattern 'const GeneralRecipientInput = $_'
# Find all usages of GeneralRecipientInput
rg "GeneralRecipientInput" -A 3
Length of output: 12419
src/components/Offramp/Confirm.view.tsx (1)
20-21: LGTM: Improved bank account display consistency
The addition of formatBankAccountDisplay utility function centralizes the formatting logic, ensuring consistent display of bank account numbers across the application.
Also applies to: 692-692
| @@ -0,0 +1,32 @@ | |||
| import { areTokenAddressesEqual } from '@/utils/' | |||
There was a problem hiding this comment.
💡 Codebase verification
Import path should be updated to reference the correct file
The areTokenAddressesEqual function is defined in src/utils/general.utils.ts, but it's being imported from @/utils/. Update the import statement to:
import { areTokenAddressesEqual } from '@/utils/general.utils'🔗 Analysis chain
Verify the imported utility function exists
Let's ensure the imported areTokenAddressesEqual function is properly defined in the utils directory.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for the definition of areTokenAddressesEqual function
ast-grep --pattern 'export function areTokenAddressesEqual($_) {
$$$
}'
# Search for any file exporting this function
rg -l "export.*areTokenAddressesEqual"
Length of output: 143
Script:
#!/bin/bash
# Let's verify the actual implementation in general.utils.ts
rg "areTokenAddressesEqual" src/utils/general.utils.ts -A 5
Length of output: 937
| export const checkTokenSupportsXChain = ( | ||
| tokenAddress: string, | ||
| chainId: string, | ||
| supportedSquidChainsAndTokens: Record<string, any> | ||
| ): boolean => { | ||
| // For native tokens, check if the chain supports SQUID_ETH_ADDRESS | ||
| if (tokenAddress === '0x0000000000000000000000000000000000000000') { | ||
| return ( | ||
| supportedSquidChainsAndTokens[chainId]?.tokens.some((token: any) => | ||
| areTokenAddressesEqual(token.address, SQUID_ETH_ADDRESS) | ||
| ) ?? false | ||
| ) | ||
| } | ||
|
|
||
| return ( | ||
| supportedSquidChainsAndTokens[chainId]?.tokens.some((token: any) => | ||
| areTokenAddressesEqual(token.address, tokenAddress) | ||
| ) ?? false | ||
| ) | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Improve type safety and code maintainability
Several improvements could enhance the robustness of this function:
- Replace
anytypes with proper interfaces:
-supportedSquidChainsAndTokens: Record<string, any>
+interface TokenInfo {
+ address: string;
+ // add other token properties
+}
+interface ChainTokens {
+ tokens: TokenInfo[];
+ // add other chain properties
+}
+supportedSquidChainsAndTokens: Record<string, ChainTokens>- Extract magic strings to named constants:
+const NATIVE_TOKEN_ADDRESS = '0x0000000000000000000000000000000000000000'
-if (tokenAddress === '0x0000000000000000000000000000000000000000') {
+if (tokenAddress === NATIVE_TOKEN_ADDRESS) {- Simplify the nested logic:
-return (
- supportedSquidChainsAndTokens[chainId]?.tokens.some((token: any) =>
- areTokenAddressesEqual(token.address, tokenAddress)
- ) ?? false
-)
+const chainTokens = supportedSquidChainsAndTokens[chainId]?.tokens ?? [];
+return chainTokens.some((token: TokenInfo) =>
+ areTokenAddressesEqual(token.address, tokenAddress)
+);Committable suggestion skipped: line range outside the PR's diff.
| {offrampType === OfframpType.CASHOUT | ||
| ? utils.formatTokenAmount(parseFloat(usdValue ?? '0')) | ||
| : tokenPrice && claimLinkData | ||
| ? utils.formatTokenAmount(tokenPrice * parseFloat(claimLinkData.tokenAmount)) | ||
| : ''}{' '} | ||
| <MoreInfo | ||
| text={`This is the total amount before the ${ | ||
| user?.accounts.find( | ||
| (account) => | ||
| account.account_identifier.replaceAll(/\s/g, '').toLowerCase() === | ||
| offrampForm.recipient.replaceAll(/\s/g, '').toLowerCase() | ||
| )?.account_type === 'iban' | ||
| ? '$1 SEPA' | ||
| : '$0.50 ACH' | ||
| } fee is deducted.`} | ||
| /> |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Refactor fee calculation logic
The current implementation has several maintainability concerns:
- Complex nested ternary expressions
- Repeated account type checks
- Hardcoded fee values
Consider extracting the fee calculation logic into a separate utility function:
type AccountType = 'iban' | 'ach';
type OfframpFees = {
[key in AccountType]: number;
};
const OFFRAMP_FEES: OfframpFees = {
iban: 1,
ach: 0.5
};
const calculateFinalAmount = (
amount: number,
accountType: AccountType,
offrampType: OfframpType,
tokenPrice?: number,
claimLinkData?: any
): number => {
const fee = OFFRAMP_FEES[accountType];
const baseAmount = offrampType === OfframpType.CASHOUT
? amount
: tokenPrice && claimLinkData
? tokenPrice * parseFloat(claimLinkData.tokenAmount)
: 0;
return baseAmount - fee;
};Then use it in the component:
- {user?.accounts.find(
- (account) =>
- account.account_identifier.replaceAll(/\s/g, '').toLowerCase() ===
- offrampForm.recipient.replaceAll(/\s/g, '').toLowerCase()
- )?.account_type === 'iban'
- ? offrampType == OfframpType.CASHOUT
- ? utils.formatTokenAmount(parseFloat(usdValue ?? tokenValue ?? '') - 1)
- : tokenPrice &&
- claimLinkData &&
- utils.formatTokenAmount(
- tokenPrice * parseFloat(claimLinkData.tokenAmount) - 1
- )
+ {utils.formatTokenAmount(
+ calculateFinalAmount(
+ parseFloat(usdValue ?? '0'),
+ account?.account_type as AccountType,
+ offrampType,
+ tokenPrice,
+ claimLinkData
+ )
+ )}Also applies to: 787-792
|
I think there's still a bunch of stuff to improve here. Don't have time to tackle all of these, but:
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
.github/workflows/prettier.yml (3)
4-4: LGTM! Consider adding paths-ignore for efficiency.Good change to run on pull requests instead of pushes. This ensures code formatting is checked before merging.
Consider adding paths-ignore to skip unnecessary checks:
pull_request: branches: ['**'] + paths-ignore: + - '**/*.md' + - 'assets/**' + - '.gitignore'
24-27: Enhance file listing for better visibility.While listing files is helpful for debugging, the current implementation could be improved.
Consider these improvements:
- name: List files to be checked run: | echo "Files to be checked:" - find . -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" -o -name "*.md" -o -name "*.json" -o -name "*.css" -o -name "*.scss" -o -name "*.yaml" -o -name "*.yml" \) -not -path "./node_modules/*" -not -path "./.next/*" + pnpm exec prettier --config prettier.config.js --list-different "**/*.{js,jsx,ts,tsx,md,json,css,scss,yaml,yml}" || trueThis change:
- Uses Prettier's built-in file listing
- Respects
.prettierignoreconfigurations- Shows only files that would be processed
30-36: Improve error reporting with a summary.The error messaging is good, but we can make it even more helpful.
Consider enhancing the error reporting:
run: | echo "Running Prettier check..." - pnpm exec prettier --config prettier.config.js --check "**/*.{js,jsx,ts,tsx,md,json,css,scss,yaml,yml}" || ( + pnpm exec prettier --config prettier.config.js --check "**/*.{js,jsx,ts,tsx,md,json,css,scss,yaml,yml}" > prettier-results.txt || ( + echo "----------------------------------------" + echo "Summary of formatting issues:" + cat prettier-results.txt | grep "Code style issues" || true + echo "----------------------------------------" echo "❌ Prettier found style issues in the above files" echo "To fix these issues, run: pnpm format" exit 1 )This change:
- Captures Prettier output for better processing
- Adds a clear summary section
- Makes the output more readable in GitHub Actions logs
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
.github/workflows/prettier.yml(2 hunks)prettier.config.js(0 hunks)
💤 Files with no reviewable changes (1)
- prettier.config.js
| semi: false, | ||
| singleQuote: true, | ||
| printWidth: 120, | ||
| importOrder: [ |
jjramirezn
left a comment
There was a problem hiding this comment.
Changes seem good, lots of complexity around cashout
One comment about the ValidatedInput please review it before merging.
| const newValue = e.target.value | ||
| onUpdate({ value: newValue, isValid: false, isChanging: !!newValue }) | ||
| const rawValue = e.target.value | ||
| const sanitizedValue = sanitizeBankAccount(rawValue) |
There was a problem hiding this comment.
Why is this here, this component is used not only for bank accounts
.env.example
Outdated
| export NEXT_PUBLIC_WC_PROJECT_ID="6b12debabfec7d3971d2befb5a2e36fd" | ||
| export NEXT_PUBLIC_SENTRY_DSN="https://d2f7d5e16a3c2cecdd301c7f94e440d0@o4505827429187584.ingest.sentry.io/4505827431415808" | ||
| export NEXT_PUBLIC_RECAPTCHA_SITE_KEY="6Ldio2kpAAAAAAWJiNHbgv1yCzsROdxU3_Py85rZ" | ||
| export NEXT_PUBLIC_INFURA_API_KEY="051209b4dbce4a98bfe8b424c6b21417" |
There was a problem hiding this comment.
Should we publish these?
Bank Account Input and Validation Improvements
Core Changes