-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Develop SYNC #672
base: peanut-wallet
Are you sure you want to change the base?
Develop SYNC #672
Conversation
…into feat/seo-optimization
[TASK-7742] update: merge t&c and privacy links in footer
…into feat/seo-optimization
- replaced `seo.config.ts` with new `metadata.ts` in `/app` dir - removed privacy and terms metadata - updated robots and sitemap config to remove terms, privacy and blog page
[TASK-7729] fix: remove allowedDomains from safe connector
[TASK-5516] feat: seo optimizations
[TASK-6560] + [TASK-6688] fix: update formatAmount function
…tion Fix/wrong password validation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
src/config/wagmi.config.tsx (3)
33-36
: Consider network ordering impact.The network array is well-typed, but since
mainnet
is set as the default network (line 48), consider moving it to the first position in the array for consistency.-export const networks = [arbitrum, mainnet, optimism, polygon, gnosis, base, scroll, mantle, bsc] as [ +export const networks = [mainnet, arbitrum, optimism, polygon, gnosis, base, scroll, mantle, bsc] as [
46-62
: Verify default network selection.The configuration looks good, but please verify that
mainnet
as the default network aligns with your application's requirements, especially for development and testing environments.Consider making the default network configurable through environment variables to support different environments (development, staging, production).
64-79
: LGTM! Well-documented cookie handling.The cookie-based state initialization is well-implemented and documented. However, consider adding type information for the cookies parameter in the JSDoc.
/** * converts the provided cookies into an initial state for the application. * * @param {Config} wagmiConfig - The configuration object for the wagmi adapter. - * @param {Record<string, string>} cookies - An object representing the cookies. + * @param {string | null} cookies - The cookie string or null if no cookies are present. * @returns {InitialState} The initial state derived from the cookies. */src/config/peanut.config.tsx (1)
4-16
: Consider reorganizing imports for better maintainability.Group imports by type (external libraries, components, styles, configs) for better organization:
'use client' import * as config from '@/config' import peanut from '@squirrel-labs/peanut-sdk' +// External libraries import { Analytics } from '@vercel/analytics/react' import countries from 'i18n-iso-countries' import enLocale from 'i18n-iso-countries/langs/en.json' import { useEffect } from 'react' import ReactGA from 'react-ga4' import { ChakraProvider } from '@chakra-ui/react' +// Styles import * as styles from '@/styles/theme' import 'react-tooltip/dist/react-tooltip.css' +// Configs import '../../sentry.client.config' import '../../sentry.edge.config' import '../../sentry.server.config'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/config/peanut.config.tsx
(2 hunks)src/config/wagmi.config.tsx
(3 hunks)
🔇 Additional comments (5)
src/config/wagmi.config.tsx (2)
3-14
: LGTM! Well-organized network imports.The network imports are properly structured and all imported networks are utilized in the configuration.
38-43
: LGTM! Proper WagmiAdapter configuration.The adapter is correctly configured with all necessary properties and SSR support for Next.js.
src/config/peanut.config.tsx (3)
18-18
: LGTM! Clean component structure.The component follows React best practices with proper TypeScript type definitions.
19-24
:❓ Verification inconclusive
Verify analytics configuration and environment-specific settings.
- Ensure the Google Analytics environment variable is properly set
- Consider making verbose mode development-only
useEffect(() => { ReactGA.initialize(process.env.NEXT_PUBLIC_GA_KEY ?? '') - peanut.toggleVerbose(true) + if (process.env.NODE_ENV === 'development') { + peanut.toggleVerbose(true) + } countries.registerLocale(enLocale) }, [])
🏁 Script executed:
#!/bin/bash # Check if GA environment variable is defined in relevant config files echo "Checking for GA environment variable..." fd -t f "env" -x grep -l "NEXT_PUBLIC_GA_KEY"Length of output: 132
Analytics and Environment Configuration Verification
- Ensure that the GA environment variable (
NEXT_PUBLIC_GA_KEY
) is defined in your production configuration (e.g., in an appropriate.env
file or deployment settings). Our initial file search did not return any files containing the key, so please double-check that it’s properly set in your production environment.- It's good that the
peanut.toggleVerbose(true)
call is now wrapped in a development-only condition (if (process.env.NODE_ENV === 'development')
).- If LogRocket is no longer needed, consider removing the commented initialization line to clean up the code.
useEffect(() => { ReactGA.initialize(process.env.NEXT_PUBLIC_GA_KEY ?? '') - peanut.toggleVerbose(true) + if (process.env.NODE_ENV === 'development') { + peanut.toggleVerbose(true) + } countries.registerLocale(enLocale) }, [])
29-32
:❓ Verification inconclusive
Verify the impact of setting cookies prop to null.
The change to set
cookies={null}
might affect functionality if the application relies on cookie-based features.
🏁 Script executed:
#!/bin/bash # Search for cookie-related functionality in the codebase echo "Checking for cookie usage..." rg -l "cookies?" --type ts --type tsxLength of output: 134
Action: Verify Cookies Prop Impact
The update sets
cookies={null}
in theconfig.ContextProvider
on lines 29–32 ofsrc/config/peanut.config.tsx
. A previous attempt to search for cookie-related usage using ripgrep encountered file type errors, so we re-ran a command using glob patterns. As the results are still inconclusive, please manually verify that no parts of the application rely on a valid (non-null) cookies prop. Pay special attention to any functionality that might use cookies for session management or configuration.
- Check any components or hooks that might expect a cookie value.
- Confirm that the null assignment won’t disrupt cookie-dependent functionalities.
🏁 Script executed:
#!/bin/bash echo "Re-checking cookie usage in TS and TSX files using glob patterns..." rg -l 'cookies=' -g "*.tsx" -g "*.ts"Length of output: 211
Verify impact of setting cookies prop to null
We've re-run the search and confirmed that the only occurrence of the
cookies
prop is insrc/config/peanut.config.tsx
. This suggests that there aren’t other direct references to cookie-based functionality in the broader codebase. However, please manually verify that theconfig.ContextProvider
implementation safely handles anull
value forcookies
, especially if downstream components or session-related features might rely on a valid cookie object.
- Confirm that any logic within
ContextProvider
and its consumers properly accounts forcookies={null}
- Double-check session or cookie-dependent functionality, if applicable
fix: chevron and clear icons overalapping in address input
fix: claim cta changes on navigation b/w intial and confirm view
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
src/components/Global/ValidatedInput/index.tsx (2)
113-118
: Simplify the boolean coercion in className.The double negation (
!!infoText
) is redundant as the value will already be coerced to a boolean in this context.- !!infoText ? 'pl-8' : 'pl-4' + infoText ? 'pl-8' : 'pl-4'🧰 Tools
🪛 Biome (1.9.4)
[error] 117-117: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation(lint/complexity/noExtraBooleanCast)
140-144
: Consider simplifying the opacity transition logic.The current opacity transition logic could be simplified for better readability.
- className={`h-full ${ - isValidating - ? 'opacity-100' - : 'opacity-100 transition-opacity hover:opacity-100 md:opacity-0' - }`} + className="h-full transition-opacity md:opacity-0 md:hover:opacity-100" + style={{ opacity: isValidating ? 1 : undefined }}src/components/Claim/Link/Initial.view.tsx (3)
63-66
: Consider using a custom hook for error state management.The error state management could be abstracted into a custom hook to improve reusability and reduce boilerplate code across the component.
-const [errorState, setErrorState] = useState<{ - showError: boolean - errorMessage: string -}>({ showError: false, errorMessage: '' }) +const useErrorState = () => { + const [error, setError] = useState<{ + showError: boolean + errorMessage: string + }>({ showError: false, errorMessage: '' }) + + const clearError = () => setError({ showError: false, errorMessage: '' }) + const setErrorMessage = (message: string) => + setError({ showError: true, errorMessage: message }) + + return { error, clearError, setErrorMessage } +}
326-387
: Add retry logic for route fetching.The route fetching function could fail due to temporary network issues. Consider implementing a retry mechanism with exponential backoff.
const fetchRoute = async (toToken?: string, toChain?: string) => { + const MAX_RETRIES = 3; + const INITIAL_DELAY = 1000; + let retryCount = 0; + + const fetchWithRetry = async () => { try { const existingRoute = routes.find( (route) => route.fromChain === claimLinkData.chainId && route.fromToken.toLowerCase() === claimLinkData.tokenAddress.toLowerCase() && route.toChain === (toChain || selectedChainID) && areTokenAddressesEqual(route.toToken, toToken || selectedTokenAddress) ) if (existingRoute) { setSelectedRoute(existingRoute) return existingRoute } else if (!isXChain && !toToken && !toChain) { setHasFetchedRoute(false) return undefined } // ... rest of the function ... } catch (error) { + if (retryCount < MAX_RETRIES) { + retryCount++; + await new Promise(resolve => + setTimeout(resolve, INITIAL_DELAY * Math.pow(2, retryCount - 1)) + ); + return fetchWithRetry(); + } console.error('Error fetching route:', error) if (!toToken && !toChain) { setSelectedRoute(undefined) } setErrorState({ showError: true, - errorMessage: 'No route found for the given token pair.', + errorMessage: 'Unable to find a route. Please try again or select a different token pair.', }) return undefined } + } + + return fetchWithRetry(); }
434-443
: Enhance accessibility for the attachment download link.The download link could benefit from improved accessibility attributes.
<a href={attachment.attachmentUrl} download target="_blank" + rel="noopener noreferrer" + aria-label="Download attachment" className="flex w-full cursor-pointer flex-row items-center justify-center gap-1 text-h9 font-normal text-gray-1 underline " > <Icon name={'download'} /> - Download attachment + <span>Download attachment</span> </a>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/components/Claim/Link/Initial.view.tsx
(8 hunks)src/components/Claim/Link/Onchain/Confirm.view.tsx
(5 hunks)src/components/Global/ValidatedInput/index.tsx
(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/Claim/Link/Onchain/Confirm.view.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/Global/ValidatedInput/index.tsx
[error] 117-117: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation
(lint/complexity/noExtraBooleanCast)
🔇 Additional comments (3)
src/components/Global/ValidatedInput/index.tsx (2)
1-20
: LGTM! Good improvements to the type definitions.The changes to make the
label
prop optional and the addition of necessary imports enhance the component's flexibility.
28-93
: LGTM! Well-structured component implementation.The component demonstrates good practices:
- Efficient debouncing of validation
- Proper cleanup in useEffect
- Comprehensive error handling
- Clean state management
src/components/Claim/Link/Initial.view.tsx (1)
39-673
: Implementation looks solid!The component has been well-structured with good error handling, cross-chain support, and user feedback. The changes improve the overall functionality while maintaining good code organization.
fix: clear icon visibility
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/components/Global/ValidatedInput/index.tsx (1)
113-118
: Remove redundant double negation.The double negation in
!!infoText
is unnecessary as the value will already be coerced to a boolean.- !!infoText ? 'pl-8' : 'pl-4' + infoText ? 'pl-8' : 'pl-4'🧰 Tools
🪛 Biome (1.9.4)
[error] 117-117: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation(lint/complexity/noExtraBooleanCast)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/components/Global/ValidatedInput/index.tsx
(5 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/Global/ValidatedInput/index.tsx
[error] 117-117: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation
(lint/complexity/noExtraBooleanCast)
🔇 Additional comments (3)
src/components/Global/ValidatedInput/index.tsx (3)
1-20
: LGTM! Good improvements to imports and type definitions.The changes enhance flexibility by making the label optional, and the new imports support the component's functionality.
42-92
: LGTM! Robust validation and state management implementation.The component implements proper debouncing, error handling, and state cleanup. The validation logic is well-structured with appropriate user feedback.
94-162
: LGTM! Improved UI structure and feedback.The changes enhance the component's UI through:
- Better layout using flex containers
- Improved loading state visibility
- Enhanced close button positioning
🧰 Tools
🪛 Biome (1.9.4)
[error] 117-117: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation(lint/complexity/noExtraBooleanCast)
feat: add maintenance banner with configurable time window
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
src/config/routesUnderMaintenance.ts (2)
3-6
: Add JSDoc documentation for the maintenanceTime property.Please document the expected date format and any validation requirements for the maintenance window.
interface MaintenanceConfig { routes: string[] + /** + * Optional maintenance window configuration. + * @property {string} start - Start time in ISO 8601 format (e.g., '2025-02-20T11:10:00Z') + * @property {string} end - End time in ISO 8601 format (e.g., '2025-02-20T17:30:00Z') + */ maintenanceTime?: { start: string end: string } }
24-27
: Consider adding runtime validation for maintenance times.The maintenance window configuration should validate that:
- Dates are in valid ISO 8601 format
- Start time is before end time
- Dates are not too far in the future (to prevent stale configurations)
Consider adding a validation function:
function validateMaintenanceWindow(start: string, end: string): void { const startDate = new Date(start); const endDate = new Date(end); if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) { throw new Error('Invalid date format. Use ISO 8601 format (e.g., 2025-02-20T11:10:00Z)'); } if (startDate >= endDate) { throw new Error('Maintenance start time must be before end time'); } const maxFutureDate = new Date(); maxFutureDate.setMonth(maxFutureDate.getMonth() + 3); // Example: max 3 months ahead if (startDate > maxFutureDate) { throw new Error('Maintenance window cannot be scheduled too far in the future'); } }src/components/Global/Banner/MaintenanceBanner.tsx (2)
11-17
: Extract time window check into a reusable utility function.The maintenance window check logic could be reused elsewhere. Consider extracting it into a utility function.
+// In a new file: src/utils/maintenance.ts +export function isWithinMaintenanceWindow(config: MaintenanceConfig): boolean { + const now = Date.now(); + const startTime = config.maintenanceTime ? new Date(config.maintenanceTime.start).getTime() : null; + const endTime = config.maintenanceTime ? new Date(config.maintenanceTime.end).getTime() : null; + + return Boolean(config.maintenanceTime && startTime && endTime && now >= startTime && now <= endTime); +} // In MaintenanceBanner.tsx -// Check if we're within the maintenance window -const now = Date.now() // Current time in milliseconds -const startTime = config.maintenanceTime ? new Date(config.maintenanceTime.start).getTime() : null -const endTime = config.maintenanceTime ? new Date(config.maintenanceTime.end).getTime() : null - -const isWithinMaintenanceWindow = - config.maintenanceTime && startTime && endTime && now >= startTime && now <= endTime +const isWithinMaintenanceWindow = isWithinMaintenanceWindow(config)
23-26
: Remove unused function and enhance maintenance message.The
formatDate
function is defined but never used. Also, consider making the maintenance message more informative by including the time window.- const formatDate = (timestamp: number) => new Date(timestamp).toUTCString() - const maintenanceMessage = config.maintenanceTime - ? `Scheduled maintenance. Some features might be unavailable.` - : 'Under maintenance' + const maintenanceMessage = config.maintenanceTime + ? `Scheduled maintenance from ${new Date(config.maintenanceTime.start).toUTCString()} to ${new Date(config.maintenanceTime.end).toUTCString()}. Some features might be unavailable.` + : 'Under maintenance'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/components/Global/Banner/MaintenanceBanner.tsx
(1 hunks)src/config/routesUnderMaintenance.ts
(2 hunks)
Fix/usdt cashout
There was a problem hiding this 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/peanut/user/add-account/route.ts (2)
35-45
: Consider handling other common error status codes.While the addition of specific handling for 409 is good, consider extending this pattern to other common error status codes (e.g., 401 for unauthorized, 403 for forbidden) for more comprehensive error handling.
if (!response.ok) { if (response.status === 409) { return new NextResponse(JSON.stringify({ error: 'User already exists' }), { status: 409, headers: { 'Content-Type': 'application/json', }, }) } + if (response.status === 401) { + return new NextResponse(JSON.stringify({ error: 'Unauthorized access' }), { + status: 401, + headers: { + 'Content-Type': 'application/json', + }, + }) + } + if (response.status === 403) { + return new NextResponse(JSON.stringify({ error: 'Forbidden access' }), { + status: 403, + headers: { + 'Content-Type': 'application/json', + }, + }) + } throw new Error(`Failed to create user: ${response.status}`) }
44-45
: Consider extracting error response text.The error message currently only includes the status code. Consider adding the response text for more detailed error information.
- throw new Error(`Failed to create user: ${response.status}`) + const errorText = await response.text(); + throw new Error(`Failed to create user: ${response.status}. ${errorText}`);src/app/api/bridge/external-account/create-external-account/route.ts (4)
8-24
: Robust JSON parsing with clear error response.
Great job returning a structured JSON response for malformed requests. This ensures clients receive informative error details. As a minor improvement, consider logging the parse error details to assist troubleshooting.
47-57
: Handling missing API key.
Returning a 500 error with a clear message is appropriate, as this is a server configuration issue. Consider redacting or limiting sensitive environment details in error messages in production.
95-105
: Account type validation.
This explicit check for'iban'
or'us'
is clear. For extensibility, consider enumerating possible account types in a central config or constant to reduce duplication across the codebase.
142-229
: Comprehensive handling of duplicate accounts.
Well done detecting duplicate inputs, fetching existing accounts, and matching them by last 4 digits. Consider concurrency scenarios (e.g., race conditions if multiple requests come in quickly), though this is likely robust enough.src/utils/cashout.utils.ts (2)
4-4
: Combined imports.
ConsolidatinggenerateKeysFromString
andgetSquidRouteRaw
on a single line is neat. Keep consistent import grouping to maintain readability.
245-245
: Informative comment for account matching.
Explicitly mentioning the matching strategy helps future contributors maintain or extend the code.src/components/Global/LinkAccountComponent/index.tsx (2)
188-203
: Check console logs for PII.
Consider sanitizing or removing logs in production to prevent the accidental leak of sensitive user information likebridge_customer_id
.
586-604
: Consider a reusable KYC error component.
You replicate the reKYC link logic; extracting a small sub-component would reduce duplication.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/app/api/bridge/external-account/create-external-account/route.ts
(3 hunks)src/app/api/peanut/user/add-account/route.ts
(2 hunks)src/components/Global/KYCComponent/index.tsx
(2 hunks)src/components/Global/LinkAccountComponent/index.tsx
(13 hunks)src/constants/cashout.consts.ts
(2 hunks)src/interfaces/interfaces.ts
(1 hunks)src/utils/cashout.utils.ts
(5 hunks)
✅ Files skipped from review due to trivial changes (2)
- src/constants/cashout.consts.ts
- src/components/Global/KYCComponent/index.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/Global/LinkAccountComponent/index.tsx
[error] 334-334: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation
(lint/complexity/noExtraBooleanCast)
🔇 Additional comments (26)
src/app/api/peanut/user/add-account/route.ts (2)
3-4
: Import reorganization looks good.The imports for
NextRequest
andNextResponse
have been moved after the constants and cookies imports. While this is just a reorganization that doesn't affect functionality, it's a clean change.
36-43
: Good addition of specific error handling for conflict scenario.This change properly handles the 409 Conflict status code with a structured JSON response rather than throwing a generic error. This is a significant improvement as it:
- Returns the appropriate HTTP status code (409)
- Provides a clear, descriptive error message
- Uses proper JSON content type
This makes the API more robust and follows RESTful best practices.
src/interfaces/interfaces.ts (1)
9-15
: Good addition for comprehensive error messaging.
The optionaldetails
property in theIResponse
interface meaningfully encapsulates finer-grained information. This structured approach can help in providing clearer or more actionable feedback to the client.src/app/api/bridge/external-account/create-external-account/route.ts (8)
1-1
: Confirm usage of newly imported interface.
You’re importingIBridgeAccount
from@/interfaces
; verify it’s utilized somewhere below to avoid potential unused import flags in certain build configurations.
26-26
: Destructure request body fields carefully.
Destructuring is fine, but ensure you handle undefined fields if future validations rely on these properties.
30-31
: Fetch query param usage looks good.
RetrievingcustomerId
viaurl.searchParams.get()
is straightforward. Confirm for future extension if additional query parameters need stricter validation or fallback defaults.
33-43
: Useful 400 error for missing customerId.
Explicitly informing the client about the missingcustomerId
is helpful for debugging. This is consistent with your structured error responses.
112-112
: Idempotency handling.
Including anIdempotency-Key
is a good practice to prevent duplicate requests. Confirm the external service’s behavior aligns with your usage (e.g., does it store or purge keys over time?).
118-118
: JSON parsing of the Bridge response.
Storing the parsed response in a variable ensures subsequent error checks can reference it. This approach is solid for debugging or logging.
121-140
: Structured handling for invalid parameters.
Conditionally constructing a clear error message for missing parameters helps front-end developers and end users correct invalid requests faster. Good use ofdata.message
fallback when fields are absent.
255-276
: Centralized catch block.
Logging the error details and returning a 500 with structured JSON is consistent with the rest of the function’s approach to uniform error responses. Ensure sensitive error stack traces are not exposed in production.src/utils/cashout.utils.ts (6)
2-2
: Reorganized imports for clarity.
Importinginterfaces
earlier can help maintain a structured import style. No issues identified.
134-135
: New KYCStatus type.
Explicitly enumerating valid KYC states makes the code more self-documenting. This approach is flexible enough to accommodate future states.
143-143
: Seamless KYC status integration.
Refactoringkyc_status
to useKYCStatus
ensures consistency and avoids magic strings throughout the code.
224-225
: Storing parsed response in local variable.
Clear step to separate fetch operations from error handling. This approach is easier to debug than inline parsing.
228-229
: Duplicate account detection logic.
You’re checkingresponseData.code === 'duplicate_external_account'
to handle pre-existing accounts gracefully. This parallels the logic on the server side, providing consistent UX.
278-278
: Returning response data as final payload.
Exposing the raw response data can help in debugging dynamic scenarios. Confirm no sensitive fields are leaked.src/components/Global/LinkAccountComponent/index.tsx (9)
2-2
: All new imports look good.
No concerns identified here.Also applies to: 5-7, 9-9, 12-14
49-49
: NewreKYCUrl
state variable is well-introduced.
This addition cleanly accommodates the re-verification link.
113-113
: Verify the updated KYC status check.
Confirm thatuser.user.kycStatus === 'approved'
is indeed the correct final status, rather than'verified'
or other possible status values.
411-428
: Providing an immediate reKYC link is great for UX.
This conditional error message helps users complete KYC quickly.
522-522
: Layout change identified, no further feedback.
613-626
: User-friendly success screen.
Displaying a direct link to the profile after successful linking improves clarity.
636-636
: No issues identified.
653-653
: No issues identified.
663-663
: Conditional rendering of<KYCComponent />
seems correct.
This aligns nicely with requiringkycStatus === 'approved'
to skip KYC.
const createExternalAccountRes: IResponse = await utils.createExternalAccount( | ||
customerId, | ||
formData.type as 'iban' | 'us', | ||
accountDetails, | ||
// Only include address for US accounts | ||
formData.type === 'us' ? address : undefined, | ||
address, | ||
accountOwnerName | ||
) | ||
|
||
console.log('Create external account response:', response) | ||
// handle verification requirement first | ||
if (!createExternalAccountRes.data.success) { | ||
// check for verification URL | ||
|
||
if (!response.success) { | ||
setErrorState({ | ||
showError: true, | ||
errorMessage: response.message || 'Failed to create external account', | ||
}) | ||
return | ||
} | ||
if (createExternalAccountRes.data.details?.code === 'endorsement_requirements_not_met') { | ||
const verificationUrl = createExternalAccountRes.data.details.requirements.kyc_with_proof_of_address | ||
|
||
const data: IBridgeAccount = response.data | ||
setErrorState({ | ||
showError: true, | ||
errorMessage: | ||
createExternalAccountRes.data?.message || | ||
'Please complete the verification process to continue.', | ||
}) | ||
|
||
console.log('Creating account in database') | ||
await utils.createAccount( | ||
user?.user?.userId ?? '', | ||
customerId, | ||
data.id, | ||
formData.type, | ||
getIbanFormValue('accountNumber')?.replaceAll(/\s/g, '') ?? '', | ||
address | ||
) | ||
if (verificationUrl) { | ||
setReKYCUrl(verificationUrl) | ||
} | ||
return | ||
} | ||
|
||
console.log('Fetching updated user data') | ||
await fetchUser() | ||
const bridgeAccountId = createExternalAccountRes.data.id | ||
|
||
onCompleted ? onCompleted() : setCompletedLinking(true) | ||
} catch (error) { | ||
console.error('Error in handleSubmitLinkIban:', error) | ||
let errorMessage = 'Failed to link bank account' | ||
if (!!bridgeAccountId) { | ||
// add account to database | ||
await utils.createAccount( | ||
user.user.userId, | ||
customerId, | ||
bridgeAccountId, | ||
formData.type, | ||
accountDetails.accountNumber, | ||
createExternalAccountRes.data | ||
) | ||
|
||
if (error instanceof Error) { | ||
// Clean up error message by removing redundant "Error:" prefixes | ||
errorMessage = error.message.replace(/^Error:\s+/g, '') | ||
} | ||
// re-fetch user to get recently added accounts | ||
await fetchUser() | ||
|
||
onCompleted ? onCompleted() : setCompletedLinking(true) | ||
} | ||
} | ||
} catch (error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Simplify the double negation & consider splitting large function.
At line 334, avoid !!bridgeAccountId
in favor of if (bridgeAccountId)
. The entire handleSubmitLinkIban
method is quite large – consider extracting subfunctions for legibility and maintainability.
- if (!!bridgeAccountId) {
+ if (bridgeAccountId) {
📝 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.
const createExternalAccountRes: IResponse = await utils.createExternalAccount( | |
customerId, | |
formData.type as 'iban' | 'us', | |
accountDetails, | |
// Only include address for US accounts | |
formData.type === 'us' ? address : undefined, | |
address, | |
accountOwnerName | |
) | |
console.log('Create external account response:', response) | |
// handle verification requirement first | |
if (!createExternalAccountRes.data.success) { | |
// check for verification URL | |
if (!response.success) { | |
setErrorState({ | |
showError: true, | |
errorMessage: response.message || 'Failed to create external account', | |
}) | |
return | |
} | |
if (createExternalAccountRes.data.details?.code === 'endorsement_requirements_not_met') { | |
const verificationUrl = createExternalAccountRes.data.details.requirements.kyc_with_proof_of_address | |
const data: IBridgeAccount = response.data | |
setErrorState({ | |
showError: true, | |
errorMessage: | |
createExternalAccountRes.data?.message || | |
'Please complete the verification process to continue.', | |
}) | |
console.log('Creating account in database') | |
await utils.createAccount( | |
user?.user?.userId ?? '', | |
customerId, | |
data.id, | |
formData.type, | |
getIbanFormValue('accountNumber')?.replaceAll(/\s/g, '') ?? '', | |
address | |
) | |
if (verificationUrl) { | |
setReKYCUrl(verificationUrl) | |
} | |
return | |
} | |
console.log('Fetching updated user data') | |
await fetchUser() | |
const bridgeAccountId = createExternalAccountRes.data.id | |
onCompleted ? onCompleted() : setCompletedLinking(true) | |
} catch (error) { | |
console.error('Error in handleSubmitLinkIban:', error) | |
let errorMessage = 'Failed to link bank account' | |
if (!!bridgeAccountId) { | |
// add account to database | |
await utils.createAccount( | |
user.user.userId, | |
customerId, | |
bridgeAccountId, | |
formData.type, | |
accountDetails.accountNumber, | |
createExternalAccountRes.data | |
) | |
if (error instanceof Error) { | |
// Clean up error message by removing redundant "Error:" prefixes | |
errorMessage = error.message.replace(/^Error:\s+/g, '') | |
} | |
// re-fetch user to get recently added accounts | |
await fetchUser() | |
onCompleted ? onCompleted() : setCompletedLinking(true) | |
} | |
} | |
} catch (error) { | |
const createExternalAccountRes: IResponse = await utils.createExternalAccount( | |
customerId, | |
formData.type as 'iban' | 'us', | |
accountDetails, | |
address, | |
accountOwnerName | |
) | |
// handle verification requirement first | |
if (!createExternalAccountRes.data.success) { | |
// check for verification URL | |
if (createExternalAccountRes.data.details?.code === 'endorsement_requirements_not_met') { | |
const verificationUrl = createExternalAccountRes.data.details.requirements.kyc_with_proof_of_address | |
setErrorState({ | |
showError: true, | |
errorMessage: | |
createExternalAccountRes.data?.message || | |
'Please complete the verification process to continue.', | |
}) | |
if (verificationUrl) { | |
setReKYCUrl(verificationUrl) | |
} | |
return | |
} | |
const bridgeAccountId = createExternalAccountRes.data.id | |
if (bridgeAccountId) { | |
// add account to database | |
await utils.createAccount( | |
user.user.userId, | |
customerId, | |
bridgeAccountId, | |
formData.type, | |
accountDetails.accountNumber, | |
createExternalAccountRes.data | |
) | |
// re-fetch user to get recently added accounts | |
await fetchUser() | |
onCompleted ? onCompleted() : setCompletedLinking(true) | |
} | |
} | |
} catch (error) { |
🧰 Tools
🪛 Biome (1.9.4)
[error] 334-334: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation
(lint/complexity/noExtraBooleanCast)
[TASK-9242] fix: zero balance shown on token selector when balance is being fetched
PR just to check the diff
Summary by CodeRabbit
New Features
TryNow
component showcasing various cryptocurrency actions.FeeDescription
component for detailed transaction fee information.InfoRow
component for structured display of information.WrongPasswordClaimLink
component to enhance user feedback on password validation issues.generateMetadata
function for dynamic metadata generation across pages.robots
function to manage web crawler access to site paths.generateSitemap
function for improved SEO through sitemap generation.ValidatedInput
component with enhanced layout and loading indicators.MaintenanceBanner
component to manage maintenance notifications.Improvements
Style