feat: extra test txn step during signup to validate passkey and account setup#1490
feat: extra test txn step during signup to validate passkey and account setup#1490jjramirezn merged 11 commits intopeanut-walletfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughReplaces email collection with a test-transaction signing step in setup, removes automatic peanut-wallet creation on Home, adds account-setup redirect and finalize hooks, adjusts auth/logout and kernel client cleanup, introduces passkey debug tooling, and adds test-transaction UI handling in transaction details. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~70 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (5)
src/components/Setup/Setup.consts.tsx (1)
5-5: SignTestTransaction step swap looks consistent; consider centralizing copyReplacing the final
collect-emailstep withsign-test-transactionand wiringSignTestTransactionhere is consistent with the new finish-setup flow and the page atsetup/finish/page.tsx. The title/description are aligned with that page, which is good, but it does introduce duplicate copy/config across files—consider centralizing these strings or reusing this step definition from the finish page (or vice versa) to keep them in sync.Also applies to: 90-99
src/utils/passkeyDebug.ts (1)
7-64: Guard capturePasskeyDebugInfo for non-browser environments
capturePasskeyDebugInfoassumeswindowandnavigatorexist; it’s fine for the current call sites, but a future server-side or test usage would throw. A small early guard would make this more defensive:export const capturePasskeyDebugInfo = async (context: string) => { - try { + try { + if (typeof window === 'undefined' || typeof navigator === 'undefined') { + // Not in a browser context; nothing to capture + return null + }This keeps behavior unchanged in the browser while avoiding accidental crashes elsewhere.
src/components/Setup/Views/SignTestTransaction.tsx (1)
25-55: User prefetch and existing-account redirect behavior looks goodThe first effect proactively fetches the user when missing, and the second redirects straight to
/homewhen aPEANUT_WALLETaccount already exists, which matches the “finish-only-if-incomplete” intent. Consider addingrouterto the dependency array of the second effect if your hooks lint rule is strict, but functionally this logic is sound as-is givenrouter’s stable identity.src/hooks/useAccountSetup.ts (2)
26-46: Consider adding race condition guard.The
finalizeAccountSetupfunction can be called multiple times concurrently (e.g., double-click, rapid navigation). WhileisProcessingis tracked, it's not checked within this function to prevent duplicateaddAccountcalls, which could create race conditions or duplicate accounts.Add an early return guard:
const finalizeAccountSetup = async (address: string) => { console.log('[useAccountSetup] Starting account finalization', { address, userId: user?.user.userId }) if (!user) { console.error('[useAccountSetup] No user found') setError('User not found. Please refresh the page.') return false } + + if (isProcessing) { + console.log('[useAccountSetup] Already processing, skipping duplicate call') + return false + } setIsProcessing(true) setError(null)
76-86: Minor inconsistency: optional chaining when user is already verified.Line 82 uses
user?.user.userIdbut the user's existence is already verified at line 29. While functionally safe, this creates an inconsistency in how user is accessed throughout the function.For consistency, since user is guaranteed to exist here:
- clearAuthState(user?.user.userId) + clearAuthState(user.user.userId)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
src/app/(mobile-ui)/home/page.tsx(2 hunks)src/app/(mobile-ui)/layout.tsx(3 hunks)src/app/(setup)/setup/finish/page.tsx(1 hunks)src/components/Global/GuestLoginCta/index.tsx(0 hunks)src/components/Setup/Setup.consts.tsx(2 hunks)src/components/Setup/Setup.types.ts(2 hunks)src/components/Setup/Views/CollectEmail.tsx(0 hunks)src/components/Setup/Views/SetupPasskey.tsx(1 hunks)src/components/Setup/Views/SignTestTransaction.tsx(1 hunks)src/components/Setup/Views/index.ts(1 hunks)src/context/authContext.tsx(4 hunks)src/context/kernelClient.context.tsx(1 hunks)src/hooks/useAccountSetup.ts(1 hunks)src/hooks/useAccountSetupRedirect.ts(1 hunks)src/hooks/useLogin.tsx(2 hunks)src/utils/index.ts(1 hunks)src/utils/passkeyDebug.ts(1 hunks)
💤 Files with no reviewable changes (2)
- src/components/Setup/Views/CollectEmail.tsx
- src/components/Global/GuestLoginCta/index.tsx
🧰 Additional context used
🧠 Learnings (30)
📓 Common learnings
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1094
File: src/components/AddWithdraw/DynamicBankAccountForm.tsx:279-279
Timestamp: 2025-08-14T08:02:26.705Z
Learning: For hotfixes in the peanut-ui codebase, prefer generic error messages over specific validation error details until the copy can be reviewed with the team, even when the validation functions return detailed error messages.
Learnt from: kushagrasarathe
Repo: peanutprotocol/peanut-ui PR: 845
File: src/components/Request/link/views/Create.request.link.view.tsx:81-81
Timestamp: 2025-05-13T10:05:24.057Z
Learning: In the peanut-ui project, pages that handle request flows (like Create.request.link.view.tsx) are only accessible to logged-in users who will always have a username, making null checks for user?.user.username unnecessary in these contexts.
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 0
File: :0-0
Timestamp: 2025-07-05T16:58:25.340Z
Learning: Hugo0 successfully refactored sessionStorage usage to React Context in the onramp flow, demonstrating preference for centralized state management over browser storage for component-shared state in React applications.
📚 Learning: 2024-12-02T17:19:18.532Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Applied to files:
src/components/Setup/Views/SignTestTransaction.tsxsrc/app/(mobile-ui)/layout.tsxsrc/app/(setup)/setup/finish/page.tsxsrc/components/Setup/Views/SetupPasskey.tsxsrc/app/(mobile-ui)/home/page.tsxsrc/components/Setup/Setup.consts.tsx
📚 Learning: 2024-12-11T10:13:22.806Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 564
File: src/components/Request/Pay/Views/Initial.view.tsx:430-430
Timestamp: 2024-12-11T10:13:22.806Z
Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.
Applied to files:
src/components/Setup/Views/SignTestTransaction.tsx
📚 Learning: 2025-09-18T09:30:42.901Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1230
File: src/app/(mobile-ui)/withdraw/page.tsx:92-97
Timestamp: 2025-09-18T09:30:42.901Z
Learning: In src/app/(mobile-ui)/withdraw/page.tsx, the useEffect that calls setShowAllWithdrawMethods(true) when amountFromContext exists is intentionally designed to run only on component mount (empty dependency array), not when amountFromContext changes. This is the correct behavior for the withdraw flow where showing all methods should only happen on initial load when an amount is already present.
Applied to files:
src/app/(mobile-ui)/layout.tsxsrc/hooks/useAccountSetupRedirect.tssrc/hooks/useLogin.tsxsrc/app/(mobile-ui)/home/page.tsx
📚 Learning: 2025-05-13T10:05:24.057Z
Learnt from: kushagrasarathe
Repo: peanutprotocol/peanut-ui PR: 845
File: src/components/Request/link/views/Create.request.link.view.tsx:81-81
Timestamp: 2025-05-13T10:05:24.057Z
Learning: In the peanut-ui project, pages that handle request flows (like Create.request.link.view.tsx) are only accessible to logged-in users who will always have a username, making null checks for user?.user.username unnecessary in these contexts.
Applied to files:
src/app/(mobile-ui)/layout.tsxsrc/hooks/useAccountSetupRedirect.tssrc/hooks/useLogin.tsxsrc/app/(mobile-ui)/home/page.tsx
📚 Learning: 2025-07-24T13:26:10.290Z
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 1014
File: src/components/Claim/Link/Initial.view.tsx:413-413
Timestamp: 2025-07-24T13:26:10.290Z
Learning: In the peanut-ui repository, the change from `${SQUID_API_URL}/route` to `${SQUID_API_URL}/v2/route` in src/components/Claim/Link/Initial.view.tsx was a typo fix, not an API migration, as the codebase was already using Squid API v2.
Applied to files:
src/app/(mobile-ui)/layout.tsxsrc/hooks/useLogin.tsxsrc/app/(mobile-ui)/home/page.tsx
📚 Learning: 2025-09-05T07:31:11.396Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1185
File: src/components/Claim/useClaimLink.tsx:14-0
Timestamp: 2025-09-05T07:31:11.396Z
Learning: In the peanut-ui codebase, `window.history.replaceState` is preferred over `router.replace` when immediate/synchronous URL parameter updates are required, as `router.replace` is asynchronous and doesn't guarantee instant URL changes that subsequent code can rely on. This pattern is used consistently across usePaymentInitiator.ts, Confirm.payment.view.tsx, and useClaimLink.tsx.
Applied to files:
src/app/(mobile-ui)/layout.tsxsrc/hooks/useLogin.tsxsrc/app/(mobile-ui)/home/page.tsx
📚 Learning: 2025-08-07T12:53:50.946Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1072
File: src/app/(setup)/setup/page.tsx:173-175
Timestamp: 2025-08-07T12:53:50.946Z
Learning: In the peanut-ui setup flow at `src/app/(setup)/setup/page.tsx`, when handling unsupported scenarios, both device not supported and browser not supported cases should show the same "Unsupported browser" message using the `UnsupportedBrowserModal` component, rather than having distinct messaging for each scenario.
Applied to files:
src/app/(mobile-ui)/layout.tsxsrc/app/(setup)/setup/finish/page.tsx
📚 Learning: 2025-11-04T17:47:06.328Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1396
File: src/app/(mobile-ui)/home/page.tsx:295-304
Timestamp: 2025-11-04T17:47:06.328Z
Learning: In src/app/(mobile-ui)/home/page.tsx, when closing the KycCompletedModal, updateUserById is called without awaiting to provide instant feedback to the user. This fire-and-forget pattern for modal dismissals and UI preference updates is intentional and consistent across the codebase—user experience with instant UI feedback takes priority over waiting for backend sync operations.
Applied to files:
src/app/(mobile-ui)/layout.tsxsrc/app/(setup)/setup/finish/page.tsxsrc/hooks/useLogin.tsxsrc/app/(mobile-ui)/home/page.tsx
📚 Learning: 2024-10-29T16:06:38.812Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 495
File: src/components/Create/useCreateLink.tsx:647-657
Timestamp: 2024-10-29T16:06:38.812Z
Learning: In the React code for `useCreateLink` in `src/components/Create/useCreateLink.tsx`, the `switchNetwork` function used within `useCallback` hooks is stable and does not need to be included in the dependency arrays.
Applied to files:
src/app/(mobile-ui)/layout.tsxsrc/hooks/useAccountSetupRedirect.tssrc/hooks/useLogin.tsxsrc/context/authContext.tsx
📚 Learning: 2025-08-20T09:08:19.266Z
Learnt from: kushagrasarathe
Repo: peanutprotocol/peanut-ui PR: 1112
File: src/components/Claim/Link/views/BankFlowManager.view.tsx:336-343
Timestamp: 2025-08-20T09:08:19.266Z
Learning: In the KYC flow implementation, `setJustCompletedKyc` must be called after `await fetchUser()` in the `handleKycSuccess` callback. Setting `justCompletedKyc` before fetching the user would cause a re-fetching loop because `handleKycSuccess` is set in a useEffect inside the KYC hook, which would cause the UI flow to get stuck in one view.
Applied to files:
src/app/(mobile-ui)/layout.tsxsrc/hooks/useAccountSetupRedirect.tssrc/hooks/useAccountSetup.tssrc/components/Setup/Views/SetupPasskey.tsxsrc/hooks/useLogin.tsxsrc/app/(mobile-ui)/home/page.tsx
📚 Learning: 2025-08-12T17:44:04.268Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1089
File: src/components/LandingPage/dropLink.tsx:35-42
Timestamp: 2025-08-12T17:44:04.268Z
Learning: In the Peanut UI project, opening the `/setup` route in a new tab from landing page CTAs is intentional design behavior to keep users on the marketing page while they start the setup process.
Applied to files:
src/app/(setup)/setup/finish/page.tsx
📚 Learning: 2025-01-16T13:13:48.615Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 631
File: src/context/kernelClient.context.tsx:88-124
Timestamp: 2025-01-16T13:13:48.615Z
Learning: In React useEffect hooks, when there's an early return condition and async operations, it's correct to have cleanup functions in both the early return and the final return to ensure proper cleanup in all scenarios.
Applied to files:
src/hooks/useAccountSetupRedirect.tssrc/hooks/useAccountSetup.ts
📚 Learning: 2025-05-15T14:47:26.891Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 857
File: src/hooks/useWebSocket.ts:77-82
Timestamp: 2025-05-15T14:47:26.891Z
Learning: The useWebSocket hook in src/hooks/useWebSocket.ts is designed to provide raw history entries, while the components using it (such as HomeHistory.tsx) are responsible for implementing deduplication logic based on UUID to prevent duplicate entries when combining WebSocket data with other data sources.
Applied to files:
src/hooks/useAccountSetup.ts
📚 Learning: 2025-01-16T13:13:09.158Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 631
File: src/context/kernelClient.context.tsx:34-69
Timestamp: 2025-01-16T13:13:09.158Z
Learning: Error handling through try-catch blocks in the `createKernelClient` function in `src/context/kernelClient.context.tsx` is not required as per the team's preference.
Applied to files:
src/context/kernelClient.context.tsx
📚 Learning: 2024-10-08T20:13:42.967Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 413
File: src/context/tokenSelector.context.tsx:118-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Applied to files:
src/context/kernelClient.context.tsxsrc/context/authContext.tsx
📚 Learning: 2025-01-16T13:14:40.363Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 631
File: src/components/Create/Create.tsx:108-112
Timestamp: 2025-01-16T13:14:40.363Z
Learning: In the Peanut UI codebase, the `resetTokenContextProvider` function from `tokenSelectorContext` is a stable function reference that doesn't change, so it doesn't need to be included in useEffect dependencies.
Applied to files:
src/context/kernelClient.context.tsxsrc/app/(mobile-ui)/home/page.tsx
📚 Learning: 2025-01-13T17:45:04.539Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 623
File: src/context/walletContext/zeroDevContext.context.tsx:106-123
Timestamp: 2025-01-13T17:45:04.539Z
Learning: The promise chain for creating passkey validator and kernel client from webAuthnKey in ZeroDevContext is designed to be reliable and should not error, as the webAuthnKey is already validated before being stored in localStorage.
Applied to files:
src/context/kernelClient.context.tsxsrc/components/Setup/Views/SetupPasskey.tsx
📚 Learning: 2025-01-13T17:36:31.764Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 623
File: src/context/walletContext/zeroDevContext.context.tsx:91-93
Timestamp: 2025-01-13T17:36:31.764Z
Learning: In the peanut-ui project, the webAuthnKey stored in localStorage only contains public data and is safe to store there. This is used in the ZeroDevContext for passkey validation.
Applied to files:
src/context/kernelClient.context.tsxsrc/components/Setup/Views/SetupPasskey.tsxsrc/utils/passkeyDebug.ts
📚 Learning: 2024-10-25T11:33:46.776Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 484
File: src/components/Cashout/Components/Initial.view.tsx:273-274
Timestamp: 2024-10-25T11:33:46.776Z
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.
Applied to files:
src/components/Setup/Views/SetupPasskey.tsxsrc/app/(mobile-ui)/home/page.tsx
📚 Learning: 2024-10-18T08:54:22.142Z
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 458
File: src/components/Offramp/Confirm.view.tsx:96-96
Timestamp: 2024-10-18T08:54:22.142Z
Learning: In the `src/components/Offramp/Confirm.view.tsx` file, it's acceptable to include crass or informal language in code comments.
Applied to files:
src/hooks/useLogin.tsx
📚 Learning: 2025-10-08T17:13:13.155Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1299
File: src/app/(mobile-ui)/points/page.tsx:41-51
Timestamp: 2025-10-08T17:13:13.155Z
Learning: In `src/app/(mobile-ui)/points/page.tsx`, the icon name "invite-heart" is intentionally used (not "inviter-heart") when displaying who invited the current user, as this is a deliberate design choice despite semantic differences with UserHeader usage.
Applied to files:
src/hooks/useLogin.tsx
📚 Learning: 2025-09-29T18:34:33.596Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1251
File: src/components/Invites/JoinWaitlistPage.tsx:41-55
Timestamp: 2025-09-29T18:34:33.596Z
Learning: In the JoinWaitlistPage component, after successfully accepting an invite via invitesApi.acceptInvite(), calling fetchUser() is sufficient to update the user state and automatically display the app. No manual navigation to /home or other pages is required since the user is already on the home page and the app will be displayed once user.hasAppAccess is updated.
Applied to files:
src/hooks/useLogin.tsx
📚 Learning: 2025-07-07T20:22:11.092Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 958
File: src/app/actions/tokens.ts:266-266
Timestamp: 2025-07-07T20:22:11.092Z
Learning: In `src/app/actions/tokens.ts`, within the `fetchWalletBalances` function, using the non-null assertion operator `!` on `process.env.MOBULA_API_KEY!` is intentional and correct, and should not be flagged for replacement with explicit validation.
Applied to files:
src/app/(mobile-ui)/home/page.tsx
📚 Learning: 2025-10-29T11:27:59.248Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1368
File: src/components/Common/ActionList.tsx:109-111
Timestamp: 2025-10-29T11:27:59.248Z
Learning: In `src/components/Common/ActionList.tsx`, the `balance` from `useWallet()` hook is always in USDC (as a formatted string), making it directly comparable to USD amounts without conversion. The comparison `Number(balance) >= amountInUsd` is intentional and correct.
Applied to files:
src/app/(mobile-ui)/home/page.tsx
📚 Learning: 2025-07-05T16:58:25.340Z
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 0
File: :0-0
Timestamp: 2025-07-05T16:58:25.340Z
Learning: Hugo0 successfully refactored sessionStorage usage to React Context in the onramp flow, demonstrating preference for centralized state management over browser storage for component-shared state in React applications.
Applied to files:
src/context/authContext.tsx
📚 Learning: 2025-09-11T17:46:12.507Z
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 1200
File: src/app/(mobile-ui)/recover-funds/page.tsx:9-9
Timestamp: 2025-09-11T17:46:12.507Z
Learning: In Next.js applications, functions marked with "use server" are server actions that are safe to import in client components. Next.js generates proxy stubs for these functions, ensuring the actual implementation and any secrets (like process.env variables) remain on the server and are not bundled into the client JavaScript.
Applied to files:
src/context/authContext.tsx
📚 Learning: 2025-09-11T17:46:12.507Z
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 1200
File: src/app/(mobile-ui)/recover-funds/page.tsx:9-9
Timestamp: 2025-09-11T17:46:12.507Z
Learning: Functions in Next.js that are not marked with "use server" and contain secrets are unsafe to import in client components, as they get bundled into the client JavaScript and can leak environment variables to the browser.
Applied to files:
src/context/authContext.tsx
📚 Learning: 2025-09-15T17:25:12.198Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 1190
File: src/hooks/useCreateOnramp.ts:47-49
Timestamp: 2025-09-15T17:25:12.198Z
Learning: Server Actions in Next.js are specifically designed to be called from Client Components. They are asynchronous functions marked with 'use server' that run on the server but can be imported and invoked directly from client-side code. This is a core feature of the Next.js App Router, eliminating the need to create separate API routes for server-side operations called from the client.
Applied to files:
src/context/authContext.tsx
📚 Learning: 2025-05-02T19:14:25.010Z
Learnt from: kushagrasarathe
Repo: peanutprotocol/peanut-ui PR: 828
File: src/app/(mobile-ui)/request/[...username]/page.tsx:17-17
Timestamp: 2025-05-02T19:14:25.010Z
Learning: In Next.js App Router, catch-all routes (like `/request/[...username]`) will only match URLs with at least one parameter segment, ensuring that the page component only renders when there is at least one value in the params array.
Applied to files:
src/context/authContext.tsx
🧬 Code graph analysis (8)
src/components/Setup/Views/SignTestTransaction.tsx (5)
src/hooks/useZeroDev.ts (1)
useZeroDev(50-231)src/hooks/useAccountSetup.ts (1)
useAccountSetup(14-95)src/redux/slices/setup-slice.ts (1)
setupActions(69-69)src/constants/zerodev.consts.ts (2)
PEANUT_WALLET_TOKEN(20-20)PEANUT_WALLET_CHAIN(18-18)src/utils/passkeyDebug.ts (1)
capturePasskeyDebugInfo(7-64)
src/app/(mobile-ui)/layout.tsx (1)
src/hooks/useAccountSetupRedirect.ts (1)
useAccountSetupRedirect(11-35)
src/app/(setup)/setup/finish/page.tsx (2)
src/components/Setup/components/SetupWrapper.tsx (1)
SetupWrapper(168-255)src/components/Global/PeanutLoading/index.tsx (1)
PeanutLoading(4-28)
src/hooks/useAccountSetupRedirect.ts (1)
src/context/authContext.tsx (1)
useAuth(227-233)
src/hooks/useAccountSetup.ts (4)
src/context/authContext.tsx (1)
useAuth(227-233)src/utils/general.utils.ts (3)
getValidRedirectUrl(903-919)getRedirectUrl(796-798)clearRedirectUrl(800-804)src/components/Global/PostSignupActionManager/post-signup-action.consts.ts (1)
POST_SIGNUP_ACTIONS(3-24)src/utils/auth.utils.ts (1)
clearAuthState(13-33)
src/components/Setup/Views/SetupPasskey.tsx (2)
src/hooks/useZeroDev.ts (1)
useZeroDev(50-231)src/utils/webauthn.utils.ts (2)
withWebAuthnRetry(34-95)getWebAuthnErrorMessage(149-172)
src/app/(mobile-ui)/home/page.tsx (2)
src/hooks/wallet/useWallet.ts (1)
useWallet(15-101)src/context/authContext.tsx (1)
useAuth(227-233)
src/context/authContext.tsx (2)
src/utils/general.utils.ts (3)
updateUserPreferences(471-490)removeFromCookie(189-199)clearRedirectUrl(800-804)src/redux/slices/setup-slice.ts (1)
setupActions(69-69)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (22)
src/context/kernelClient.context.tsx (1)
166-172: LGTM! Proper cleanup on logout.The early-exit logic correctly resets kernel-related state when no user is present, ensuring webAuthnKey and kernel clients are cleared before any subsequent logic runs. This aligns well with the broader logout flow enhancements in this PR.
src/hooks/useLogin.tsx (2)
16-16: LGTM! Helpful documentation addition.The comment clarifies that the mobile-ui layout now handles redirecting users without PEANUT_WALLET accounts to /setup/finish, which aligns with the new account setup flow introduced in this PR.
32-36: LGTM! Comment improvements.The capitalization fixes and inline comment improve code readability without changing behavior.
src/app/(mobile-ui)/home/page.tsx (2)
53-53: LGTM! Removal aligns with new account setup flow.The removal of
addressfrom the useWallet hook is appropriate since the auto-account-creation logic has been moved to the dedicated setup flow (via useAccountSetupRedirect).
66-66: LGTM! Simplified auth usage.The removal of
addAccountaligns with moving account creation out of the home page and into the dedicated setup flow.src/hooks/useAccountSetupRedirect.ts (2)
17-22: LGTM! Well-structured redirect logic.The memoized needsRedirect computation correctly checks for:
- User presence and fetch completion
- Current path to prevent redirect loops on /setup/finish
- PEANUT_WALLET account presence
The logic ensures users without a completed account setup are consistently redirected to finish the process.
25-32: LGTM! Proper redirect side effect.The useEffect correctly performs the redirect only when needsRedirect becomes true, with appropriate logging and dependencies.
src/components/Setup/Views/index.ts (1)
3-3: LGTM! Export update aligns with setup flow refactor.The export change from CollectEmail to SignTestTransaction is consistent with the broader refactor replacing email collection with test transaction signing in the account setup flow.
src/utils/index.ts (1)
11-11: LGTM! Consistent barrel export pattern.Re-exporting the passkeyDebug module follows the established pattern and makes debugging utilities available alongside other utils.
src/app/(mobile-ui)/layout.tsx (3)
25-25: LGTM! New hook import for account setup gating.The import of useAccountSetupRedirect enables the layout to gate protected paths until account setup is complete.
84-85: LGTM! Clear documentation of redirect behavior.The comment and hook invocation clearly establish that logged-in users without a peanut wallet account will be redirected to complete setup.
104-105: LGTM! Comprehensive loading gate.The extended loading condition now properly waits for account setup completion (via needsRedirect and isCheckingAccount) in addition to existing auth checks, ensuring users complete the setup flow before accessing protected content.
src/components/Setup/Setup.types.ts (2)
14-14: LGTM! Type update aligns with flow refactor.The ScreenId change from 'collect-email' to 'sign-test-transaction' reflects the replacement of the CollectEmail component with SignTestTransaction.
34-34: LGTM! Consistent type mapping.The ScreenProps update maintains type consistency with the renamed screen identifier.
src/app/(setup)/setup/finish/page.tsx (2)
15-26: FinishSetupPageContent configuration looks correctSetupWrapper is correctly wired for the
sign-test-transactionstep (layout, image, copy, no back/skip), and embeddingSignTestTransactiondirectly keeps the flow simple and focused on the passkey check.
30-35: Suspense fallback choice is appropriateWrapping the content in
<Suspense>with a full-screenPeanutLoadingfallback is a good fit here, ensuring a clean loading experience if any child starts suspending.src/context/authContext.tsx (1)
5-8: Logout flow cleanup is thorough and correctly orderedThe enhanced
logoutUserflow looks solid: you only proceed after a successful API logout, then clear WebAuthn preferences, cookies (including the dedicated WebAuthn cookie and JWT), redirect URL, invalidate React Query caches, reset bothsetupandzerodevredux state, clear user-specific caches, sessionStorage flags, and Crisp sessions before refetching the user and navigating to/setup. The guards aroundwindow,sessionStorage, andcacheshelp avoid client-only API issues, and the existing try/catch around the whole block preserves robustness.Also applies to: 57-62, 128-196
src/components/Setup/Views/SignTestTransaction.tsx (2)
122-143: Error path resets state correctly and surfaces a generic support messageOn failure, you reset both local (
isSigning) and global (setupActions.setLoading(false)) loading flags, capture additional debug info, and show a generic “contact support” error, which is appropriate for a passkey-related hotfix. The flow avoids leaving the UI stuck in a loading state and provides enough guidance without exposing internal error details.
146-179: Loading/disabled state and UI rendering are coherent
isLoadingaggregates signing, account-setup processing, and user-fetching, andisDisabledadditionally guards on!user, which prevents premature interaction while state is resolving. ReusingisFetchingUser ? 'Loading...' : 'Sign test transaction'keeps the CTA clear, and wiringdisplayErrorinto a bold error line plus the Passkeys docs link is a good balance of guidance and escape hatch.src/components/Setup/Views/SetupPasskey.tsx (2)
23-28: LGTM: Simplified post-registration flow.The effect now cleanly moves to the next step once the address is available, removing complex redirect side effects. The dependency array correctly includes both
addressandhandleNext.
40-60: Improved error handling with WebAuthn retry wrapper.The error handling appropriately distinguishes between:
- WebAuthn errors (user-cancelable, no state clearing needed)
- Backend/network errors (clears auth state to prevent partial state corruption)
The use of
withWebAuthnRetryfor transient errors (NotReadableError, etc.) is a good pattern for the passkey registration issue mentioned in the PR title.src/hooks/useAccountSetup.ts (1)
44-44: Potential runtime error: telegramHandle null/undefined check missing.If
telegramHandleisnullorundefined, accessing.lengthwill throw a TypeError and crash the account setup flow.Apply this diff to add a safe check:
- telegramHandle: telegramHandle.length > 0 ? telegramHandle : undefined, + telegramHandle: telegramHandle && telegramHandle.length > 0 ? telegramHandle : undefined,⛔ Skipped due to learnings
Learnt from: jjramirezn Repo: peanutprotocol/peanut-ui PR: 564 File: src/components/Request/Pay/Views/Initial.view.tsx:430-430 Timestamp: 2024-12-11T10:13:22.806Z Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.Learnt from: kushagrasarathe Repo: peanutprotocol/peanut-ui PR: 915 File: src/hooks/useKycFlow.ts:96-124 Timestamp: 2025-06-22T16:10:53.167Z Learning: The `initiateKyc` function in `src/app/actions/users.ts` already includes comprehensive error handling with try-catch blocks and returns structured responses with either `{ data }` or `{ error }` fields, so additional try-catch blocks around its usage are not needed.Learnt from: kushagrasarathe Repo: peanutprotocol/peanut-ui PR: 915 File: src/hooks/useKycFlow.ts:96-124 Timestamp: 2025-06-22T16:10:53.167Z Learning: The `initiateKyc` function in `src/app/actions/users.ts` already includes comprehensive error handling with try-catch blocks and returns structured responses with either `{ data }` or `{ error }` fields, so additional try-catch blocks around its usage are not needed.Learnt from: Hugo0 Repo: peanutprotocol/peanut-ui PR: 413 File: src/components/Request/Pay/Views/Initial.view.tsx:71-72 Timestamp: 2024-10-04T13:10:49.199Z Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, it's acceptable to use the `!` operator in TypeScript to assert that `selectedTokenData` is not `null` or `undefined`, and potential runtime errors from accessing its properties without checks can be disregarded.Learnt from: Hugo0 Repo: peanutprotocol/peanut-ui PR: 413 File: src/components/Request/Pay/Views/Initial.view.tsx:71-72 Timestamp: 2024-10-08T20:13:42.967Z Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, it's acceptable to use the `!` operator in TypeScript to assert that `selectedTokenData` is not `null` or `undefined`, and potential runtime errors from accessing its properties without checks can be disregarded.
|
@coderabbitai review in depth. Evaluate:
Also, write a very concise testing guide for QA |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 21138 🏁 Script executed: Length of output: 877 🏁 Script executed: Length of output: 8036 🏁 Script executed: Length of output: 3750 🏁 Script executed: Length of output: 1351 🏁 Script executed: Length of output: 2383 🏁 Script executed: Length of output: 7451 🏁 Script executed: Length of output: 18968 🏁 Script executed: Length of output: 8200 🏁 Script executed: Length of output: 6960 🏁 Script executed: Length of output: 1281 🏁 Script executed: Length of output: 4149 @kushagrasarathe I've completed an in-depth review of PR #1490. Here's my analysis: 🔴 Risk Assessment: HIGH-MEDIUMCritical Risks - Breaking Functionality1. Race Condition in SignTestTransaction (Bug) // Line 59-63 - Missing 'router' in dependency array
useEffect(() => {
if (accountExists) {
console.log('[SignTestTransaction] Account exists, redirecting to home')
router.push('/home')
}
}, [accountExists]) // ❌ Should include 'router'2. Account Creation Failure Recovery Gap // SignTestTransaction.tsx:110-118
const success = await finalizeAccountSetup(address)
if (!success) {
// User is stuck - passkey works, but no account in DB
// Redux loading state is cleared but no retry mechanism
setError(setupError || 'Failed to complete account setup...')
return
}Recommendation: Add retry logic or allow users to retry the account creation step without re-signing. 3. Potential Redirect Loop
4. Removed Legacy Account Auto-Creation // Deleted from home/page.tsx:109-120
// This was fixing accounts for users who had incomplete signups
if (address && user && !user.accounts.some((a) => a.type === AccountType.PEANUT_WALLET)) {
addAccount({...})
}Impact: Users with incomplete accounts from previous bugs won't be auto-fixed anymore. Consider adding a one-time migration or keeping this as a safety net. 5. Production Debug Log // HomeHistory.tsx:98
console.log('combinedEntries', combinedEntries) // ❌ Remove before mergeMedium Risks6. User Fetch Without Error Boundary // SignTestTransaction.tsx:34-37
if (!user && !isFetchingUser) {
fetchUser() // No error handling if this fails
}7. Multiple User Fetch Calls
8. Complex State Management ⚡ Performance Impact: LOW-MEDIUMAdditions
Concerns
Recommendation: Ensure React Query (already in use) has proper cache/deduplication settings. 🧹 Code Quality: MEDIUM (DRY Violations)DRY Violations1. Account Existence Check Duplicated // SignTestTransaction.tsx:53
const accountExists = user?.accounts.some((a) => a.type === AccountType.PEANUT_WALLET)
// useAccountSetupRedirect.ts:17
const hasPeanutWalletAccount = user.accounts.some((a) => a.type === AccountType.PEANUT_WALLET)Fix: Create a helper function 2. Redirect Logic Scattered
Consider consolidating into a single 3. Loading State Management Positive Patterns✅ Good separation of concerns with 🧪 Concise QA Testing GuideTest Scenarios1. New User Signup (Happy Path)
2. Returning User Login (Happy Path)
3. Incomplete Signup Recovery
4. Test Transaction Failure
5. Network Failure During Account Creation
6. Redirect URL Handling
7. Legacy User Without Account (Regression)
8. Concurrent Sessions
Device-Specific Tests
Performance Checks
Recommendations
This is a substantial refactoring with good intent (verifying passkey functionality), but needs careful testing of edge cases, especially around the account creation timing and redirect logic. 🧠 Learnings used |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/components/Setup/Views/SignTestTransaction.tsx (1)
102-122: LetfinalizeAccountSetupown navigation (avoid double redirect)After a successful
finalizeAccountSetup(address), this component unconditionally callsrouter.push('/home').finalizeAccountSetupalready handles routing (includingredirect_uriand stored redirect URLs), so this extra push can cause double navigation and override custom redirects.Recommended change: remove the explicit
router.push('/home')in the!accountExistsbranch and just keep the failure handling:- if (!accountExists) { - console.log('[SignTestTransaction] Finalizing account setup') - const success = await finalizeAccountSetup(address) - if (!success) { - console.error('[SignTestTransaction] Failed to finalize account setup') - setError(setupError || 'Failed to complete account setup. Please try again.') - setIsSigning(false) - dispatch(setupActions.setLoading(false)) - return - } - // account added successfully, redirect to home - console.log('[SignTestTransaction] Account setup complete, redirecting to home') - router.push('/home') - // keep loading state active until redirect completes - } else { + if (!accountExists) { + console.log('[SignTestTransaction] Finalizing account setup') + const success = await finalizeAccountSetup(address) + if (!success) { + console.error('[SignTestTransaction] Failed to finalize account setup') + setError(setupError || 'Failed to complete account setup. Please try again.') + setIsSigning(false) + dispatch(setupActions.setLoading(false)) + return + } + console.log('[SignTestTransaction] Account setup complete') + // Navigation is handled inside finalizeAccountSetup + } else {Keep the existing
router.push('/home')in theaccountExistsbranch if login flow should still redirect directly.
🧹 Nitpick comments (5)
src/components/Home/HomeHistory.tsx (1)
98-99: Consider removing debug console.log before merging.This debugging statement should be removed before the code reaches production, or replaced with a proper conditional logging mechanism if debugging output is needed long-term.
- console.log('combinedEntries', combinedEntries) -src/components/TransactionDetails/transactionTransformer.ts (1)
495-515: Consider normalizingusdAmountwhen detecting test deposits
isTestDepositcurrently checksentry.extraData?.usdAmount === '0', while the actual amount parsing below uses a normalized string (String(...).replace(/[^\d.-]/g, '')→parseFloat). If the backend ever sends'0.00'or'0 USD', the amount would be0butisTestDepositwould befalse, and the special memo would not show.You could align detection with parsing, e.g.:
- const isTestDeposit = - entry.type === EHistoryEntryType.DEPOSIT && (String(entry.amount) === '0' || entry.extraData?.usdAmount === '0') + const normalizedUsdAmount = + entry.extraData?.usdAmount !== undefined + ? parseFloat(String(entry.extraData.usdAmount).replace(/[^\d.-]/g, '')) + : undefined + + const isTestDeposit = + entry.type === EHistoryEntryType.DEPOSIT && + (String(entry.amount) === '0' || normalizedUsdAmount === 0)and reuse
normalizedUsdAmountwhen computingamountto avoid double parsing.src/components/TransactionDetails/TransactionDetailsReceipt.tsx (1)
66-66: Nice contextualization of support vs passkey docs for test transactionsThe conditional
transaction.userName === 'Enjoy Peanut!'cleanly swaps the generic support CTA forPasskeyDocsLink, matching the test‑deposit naming used in the transformer, and the class overrides (border-t-0 pt-0) work correctly withtwMerge.To reduce future copy‑drift, consider extracting
'Enjoy Peanut!'into a shared constant used by the transformer, card, header, and receipt.Also applies to: 1388-1399
src/components/TransactionDetails/TransactionCard.tsx (1)
24-25: Test‑transaction card UX looks good; consider consolidating constants/importsThe card correctly special‑cases test transactions:
- Uses
PEANUTMAN_LOGOinstead of user avatar/perk icon.- Suppresses the usual action icon and shows
"Setup"as the label.- Leaves the amount/sign logic unchanged, so the row still conveys value.
Two minor follow‑ups:
- The
"Enjoy Peanut!"check is duplicated across multiple components; a sharedTEST_TRANSACTION_NAMEconstant would make later copy changes safer.PEANUTMAN_LOGOis imported from'@/assets/peanut'here but from'@/assets'inTransactionDetailsHeaderCard.tsx. It’s worth double‑checking that both exports exist and, if possible, standardizing on a single import path for consistency.Also applies to: 92-116, 131-141, 180-183, 201-212
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx (1)
16-17: Test‑transaction header branch is coherent; unify detection and avoid scattered magic stringsThe header card now:
- Detects test transactions via
userName === 'Enjoy Peanut!'.- Suppresses direction icons via the
isTestTransactionflag ingetIcon.- Renders a compact header with
PEANUTMAN_LOGOand “Enjoy Peanut!” instead of the usual avatar/title/status/amount block.For this temporary side fix, that’s a reasonable UX, and it lines up with the card/receipt behavior.
A few small improvements you might queue up:
- Detection of test transactions (
'Enjoy Peanut!') is repeated here and also insidegetTitleand other components. Consider a sharedisTestTransactionhelper orTEST_TRANSACTION_NAMEconstant to keep it in one place.- Since
getTitlealready computes anisTestTransactionboolean, you could pass a flag down from the component instead of recomputing based ondisplayName, which would simplify reasoning and avoid divergence if the naming ever changes.- If product/design later wants the amount or status visible for the test transaction header, it will be easy to reuse the existing non‑test branch markup with a conditional instead of a separate minimal block. For now, the current simplification is fine.
Also applies to: 52-84, 117-123, 152-180, 205-287
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/components/Home/HomeHistory.tsx(1 hunks)src/components/Setup/Views/SignTestTransaction.tsx(1 hunks)src/components/TransactionDetails/TransactionCard.tsx(4 hunks)src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx(6 hunks)src/components/TransactionDetails/TransactionDetailsReceipt.tsx(2 hunks)src/components/TransactionDetails/transactionTransformer.ts(3 hunks)
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1094
File: src/components/AddWithdraw/DynamicBankAccountForm.tsx:279-279
Timestamp: 2025-08-14T08:02:26.705Z
Learning: For hotfixes in the peanut-ui codebase, prefer generic error messages over specific validation error details until the copy can be reviewed with the team, even when the validation functions return detailed error messages.
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1089
File: src/components/LandingPage/dropLink.tsx:35-42
Timestamp: 2025-08-12T17:44:04.268Z
Learning: In the Peanut UI project, opening the `/setup` route in a new tab from landing page CTAs is intentional design behavior to keep users on the marketing page while they start the setup process.
📚 Learning: 2024-12-11T10:13:22.806Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 564
File: src/components/Request/Pay/Views/Initial.view.tsx:430-430
Timestamp: 2024-12-11T10:13:22.806Z
Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.
Applied to files:
src/components/TransactionDetails/TransactionDetailsReceipt.tsxsrc/components/Setup/Views/SignTestTransaction.tsx
📚 Learning: 2024-10-23T09:38:27.670Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 469
File: src/app/request/pay/page.tsx:32-64
Timestamp: 2024-10-23T09:38:27.670Z
Learning: In `src/app/request/pay/page.tsx`, if `linkRes` is not OK in the `generateMetadata` function, the desired behavior is to use the standard title and preview image without throwing an error.
Applied to files:
src/components/TransactionDetails/TransactionDetailsReceipt.tsx
📚 Learning: 2025-09-05T07:31:11.396Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1185
File: src/components/Claim/useClaimLink.tsx:14-0
Timestamp: 2025-09-05T07:31:11.396Z
Learning: In the peanut-ui codebase, `window.history.replaceState` is preferred over `router.replace` when immediate/synchronous URL parameter updates are required, as `router.replace` is asynchronous and doesn't guarantee instant URL changes that subsequent code can rely on. This pattern is used consistently across usePaymentInitiator.ts, Confirm.payment.view.tsx, and useClaimLink.tsx.
Applied to files:
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsxsrc/components/TransactionDetails/TransactionCard.tsxsrc/components/Setup/Views/SignTestTransaction.tsx
📚 Learning: 2025-05-23T19:26:58.220Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 873
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:95-95
Timestamp: 2025-05-23T19:26:58.220Z
Learning: The GeneralRecipientInput component supports username validation and resolution through the validateAndResolveRecipient function in src/lib/validation/recipient.ts. The function automatically detects usernames (inputs that don't contain '.' for ENS and don't start with '0x' for addresses), validates them via API HEAD request, fetches user data, and resolves them to Ethereum addresses from the user's PEANUT_WALLET account.
Applied to files:
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx
📚 Learning: 2025-11-07T11:51:58.900Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1419
File: src/components/Global/BalanceWarningModal/index.tsx:94-94
Timestamp: 2025-11-07T11:51:58.900Z
Learning: In `src/components/Global/BalanceWarningModal/index.tsx`, the casual and congratulatory phrase "You're rich! Congrats on having a high balance." is intentional and by design.
Applied to files:
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx
📚 Learning: 2025-10-08T17:13:13.155Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1299
File: src/app/(mobile-ui)/points/page.tsx:41-51
Timestamp: 2025-10-08T17:13:13.155Z
Learning: In `src/app/(mobile-ui)/points/page.tsx`, the icon name "invite-heart" is intentionally used (not "inviter-heart") when displaying who invited the current user, as this is a deliberate design choice despite semantic differences with UserHeader usage.
Applied to files:
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx
📚 Learning: 2025-06-18T19:56:55.443Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 919
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:87-87
Timestamp: 2025-06-18T19:56:55.443Z
Learning: In withdraw flows for Peanut Wallet, the PeanutActionDetailsCard should always display "USDC" as the token symbol because it shows the amount being withdrawn from the Peanut Wallet (which holds USDC), regardless of the destination token/chain selected by the user. The TokenSelector is used for choosing the withdrawal destination, not the source display.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsx
📚 Learning: 2024-12-02T17:19:18.532Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsxsrc/components/Setup/Views/SignTestTransaction.tsx
📚 Learning: 2025-07-24T13:26:10.290Z
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 1014
File: src/components/Claim/Link/Initial.view.tsx:413-413
Timestamp: 2025-07-24T13:26:10.290Z
Learning: In the peanut-ui repository, the change from `${SQUID_API_URL}/route` to `${SQUID_API_URL}/v2/route` in src/components/Claim/Link/Initial.view.tsx was a typo fix, not an API migration, as the codebase was already using Squid API v2.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsx
📚 Learning: 2025-08-14T12:46:10.706Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1089
File: src/components/LandingPage/noFees.tsx:282-285
Timestamp: 2025-08-14T12:46:10.706Z
Learning: In the peanutprotocol/peanut-ui project, loading states are implemented only after they have been properly designed by the design team to ensure consistency across the application.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsx
📚 Learning: 2025-11-04T17:47:06.328Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1396
File: src/app/(mobile-ui)/home/page.tsx:295-304
Timestamp: 2025-11-04T17:47:06.328Z
Learning: In src/app/(mobile-ui)/home/page.tsx, when closing the KycCompletedModal, updateUserById is called without awaiting to provide instant feedback to the user. This fire-and-forget pattern for modal dismissals and UI preference updates is intentional and consistent across the codebase—user experience with instant UI feedback takes priority over waiting for backend sync operations.
Applied to files:
src/components/Setup/Views/SignTestTransaction.tsx
📚 Learning: 2025-08-26T15:25:53.328Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.328Z
Learning: In `src/components/Common/ActionListDaimoPayButton.tsx`, the `handleCompleteDaimoPayment` function should not display error messages to users when DB update fails because the Daimo payment itself has succeeded - showing errors would be confusing since the payment was successful.
Applied to files:
src/components/Setup/Views/SignTestTransaction.tsx
📚 Learning: 2025-08-12T17:44:04.268Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1089
File: src/components/LandingPage/dropLink.tsx:35-42
Timestamp: 2025-08-12T17:44:04.268Z
Learning: In the Peanut UI project, opening the `/setup` route in a new tab from landing page CTAs is intentional design behavior to keep users on the marketing page while they start the setup process.
Applied to files:
src/components/Setup/Views/SignTestTransaction.tsx
📚 Learning: 2024-10-18T01:51:35.247Z
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 458
File: src/components/Offramp/Confirm.view.tsx:141-141
Timestamp: 2024-10-18T01:51:35.247Z
Learning: The `handleConfirm` function in `src/components/Create/Link/Confirm.view.tsx` is separate from the one in `src/components/Offramp/Confirm.view.tsx` and does not need to be renamed when refactoring `handleConfirm` in `src/components/Offramp/Confirm.view.tsx`.
Applied to files:
src/components/Setup/Views/SignTestTransaction.tsx
📚 Learning: 2025-05-15T14:47:26.891Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 857
File: src/hooks/useWebSocket.ts:77-82
Timestamp: 2025-05-15T14:47:26.891Z
Learning: The useWebSocket hook in src/hooks/useWebSocket.ts is designed to provide raw history entries, while the components using it (such as HomeHistory.tsx) are responsible for implementing deduplication logic based on UUID to prevent duplicate entries when combining WebSocket data with other data sources.
Applied to files:
src/components/Home/HomeHistory.tsx
📚 Learning: 2025-04-11T11:33:53.245Z
Learnt from: kushagrasarathe
Repo: peanutprotocol/peanut-ui PR: 798
File: src/components/Home/HomeHistory.tsx:138-192
Timestamp: 2025-04-11T11:33:53.245Z
Learning: In the HomeHistory component, infinite scrolling is intentionally not implemented despite the presence of useInfiniteQuery and IntersectionObserver code. The component is designed to only display the first 5 entries with a "View all transactions" link for viewing the complete history.
Applied to files:
src/components/Home/HomeHistory.tsx
🧬 Code graph analysis (3)
src/components/TransactionDetails/TransactionDetailsReceipt.tsx (2)
src/components/Setup/Views/SignTestTransaction.tsx (1)
PasskeyDocsLink(183-196)src/components/Global/Icons/Icon.tsx (1)
Icon(215-224)
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx (2)
src/components/Global/Icons/Icon.tsx (2)
IconName(71-138)Icon(215-224)src/components/UserHeader/index.tsx (1)
VerifiedUserLabel(44-122)
src/components/Setup/Views/SignTestTransaction.tsx (6)
src/hooks/useZeroDev.ts (1)
useZeroDev(50-231)src/hooks/useAccountSetup.ts (1)
useAccountSetup(14-95)src/context/authContext.tsx (1)
useAuth(227-233)src/redux/slices/setup-slice.ts (1)
setupActions(69-69)src/constants/zerodev.consts.ts (2)
PEANUT_WALLET_TOKEN(20-20)PEANUT_WALLET_CHAIN(18-18)src/utils/passkeyDebug.ts (1)
capturePasskeyDebugInfo(7-64)
🪛 Biome (2.1.2)
src/components/TransactionDetails/transactionTransformer.ts
[error] 322-322: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (1)
src/components/Setup/Views/SignTestTransaction.tsx (1)
147-165: Test‑transaction flow + error surface look consistentThe loading flags (
isSigning || isProcessing || isFetchingUser), disabled state, and combineddisplayError = error || setupErrorprovide a clear UX, and the generic error copy is appropriate for this hotfix while detailed context is sent to Sentry/passkey debug.
jjramirezn
left a comment
There was a problem hiding this comment.
Looks good, one question. Do not merge before testing in preview. Ideally with an user that is having issues
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/components/TransactionDetails/TransactionCard.tsx (3)
93-95: Avoid coupling test-transaction logic to a hard-coded display nameUsing
name === 'Enjoy Peanut!'to driveisTestTransactionis brittle (copy changes, localization, or backend naming tweaks will silently break this flow). The same flag is then used to override icon/text to "Setup".Consider instead:
- Deriving this from a dedicated field on
transaction(e.g.transaction.extraDataForDrawer?.isTestTransaction), or- At least centralizing the magic string in a shared constant with a short comment explaining the contract with the backend.
This keeps the setup/test-transaction behavior robust to UI copy changes.
Also applies to: 181-184
132-142: Align avatar sizing for test transactions with other branchesIn the test-transaction avatar branch, the wrapper uses
size-7while the inner image usessize-8, whereas other branches keep wrapper and image atsize-8. This may cause subtle layout jitter or overflow compared to normal avatars.If there’s no specific design requirement for a different size here, I’d align this branch with the others (same
size-*on wrapper and image) for consistency.
191-202: Confirm UX: replacing amount block withInvitesIconfor test transactionsFor
isTestTransaction, the card hides the amount/currency block and shows only anInvitesIcon, even thoughdisplayAmountandcurrencyDisplayAmountare still computed and passed to the drawer.If the product requirement is to avoid showing any monetary value for the setup/test transaction, this is fine; otherwise, you may want to:
- Keep the amount visible alongside the
InvitesIcon, or- Add a small label explaining that this is a setup check, not a real transfer.
Worth double-checking with design/PM so users don’t get confused by a transaction-like row with no visible amount.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/components/Setup/Views/SignTestTransaction.tsx(1 hunks)src/components/TransactionDetails/TransactionCard.tsx(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/Setup/Views/SignTestTransaction.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-06-18T19:56:55.443Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 919
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:87-87
Timestamp: 2025-06-18T19:56:55.443Z
Learning: In withdraw flows for Peanut Wallet, the PeanutActionDetailsCard should always display "USDC" as the token symbol because it shows the amount being withdrawn from the Peanut Wallet (which holds USDC), regardless of the destination token/chain selected by the user. The TokenSelector is used for choosing the withdrawal destination, not the source display.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsx
📚 Learning: 2025-10-29T11:27:59.248Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1368
File: src/components/Common/ActionList.tsx:109-111
Timestamp: 2025-10-29T11:27:59.248Z
Learning: In `src/components/Common/ActionList.tsx`, the `balance` from `useWallet()` hook is always in USDC (as a formatted string), making it directly comparable to USD amounts without conversion. The comparison `Number(balance) >= amountInUsd` is intentional and correct.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (1)
src/components/TransactionDetails/TransactionCard.tsx (1)
24-26: Nice addition of lazy loading + error boundary around the drawerImporting
LazyLoadErrorBoundaryand wrapping the lazyTransactionDetailsDrawerwithSuspenseimproves resilience to chunk-load failures without impacting the main list render.Just ensure
LazyLoadErrorBoundaryhas a user-friendly fallback for this context (e.g., silently failing to open the drawer vs. showing a generic error), but structurally this looks solid.Also applies to: 207-217
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/components/TransactionDetails/transactionTransformer.ts (1)
330-341: WrapDEPOSITcase body in a block to fixnoSwitchDeclarationsDeclaring
const isTestTransactiondirectly in thecase EHistoryEntryType.DEPOSITclause violates thenoSwitchDeclarationsrule and can leak the binding into other cases. Please wrap this case body in a block.- case EHistoryEntryType.DEPOSIT: - direction = 'add' - transactionCardType = 'add' - // check if this is a test transaction (0 amount deposit during account setup), ideally this should be handled in the backend, but for now we'll handle it here cuz its a quick fix, and in promisland of post devconnect this should be handled in the backend. - const isTestTransaction = String(entry.amount) === '0' || entry.extraData?.usdAmount === '0' - if (isTestTransaction) { - nameForDetails = 'Enjoy Peanut!' - } else { - nameForDetails = entry.senderAccount?.identifier || 'Deposit Source' - } - isPeerActuallyUser = false - break + case EHistoryEntryType.DEPOSIT: { + direction = 'add' + transactionCardType = 'add' + // check if this is a test transaction (0 amount deposit during account setup), ideally this should be handled in the backend, but for now we'll handle it here cuz its a quick fix, and in promisland of post devconnect this should be handled in the backend. + const isTestTransaction = String(entry.amount) === '0' || entry.extraData?.usdAmount === '0' + if (isTestTransaction) { + nameForDetails = 'Enjoy Peanut!' + } else { + nameForDetails = entry.senderAccount?.identifier || 'Deposit Source' + } + isPeerActuallyUser = false + break + }
🧹 Nitpick comments (3)
src/components/TransactionDetails/transactionTransformer.ts (1)
511-514: Centralize test‑deposit detection instead of re‑encoding the condition
isTestDeposithere repeats the same “amount/usdAmount is zero” condition already used in theDEPOSITcase (and related UI components infer test state fromuserName === 'Enjoy Peanut!'). This spreads the same business rule across multiple places and string literals.Consider deriving a single
isTestDepositflag once in this mapper (based onamount/usdAmount), attaching it totransactionDetails(e.g., asextraDataForDrawer.isTestDeposit), and reusing that flag for:
- Setting
nameForDetails('Enjoy Peanut!') in theDEPOSITcase.- Overriding
memohere.- Driving the test‑transaction UI in
TransactionCardandTransactionDetailsHeaderCard.That will keep the behavior consistent if the underlying condition or display copy ever changes.
Also applies to: 532-532
src/components/TransactionDetails/TransactionCard.tsx (1)
25-26: Test‑transaction card UI is clear; avoid relying on the'Enjoy Peanut!'magic stringThe new test‑transaction branch (Peanut logo avatar, "Setup" label, and InvitesIcon on the right) looks consistent and doesn’t disturb existing paths. However,
isTestTransactionis inferred vianame === 'Enjoy Peanut!', and the same literal is used again in the header component; this is brittle if copy or localization changes.Once you have a dedicated flag from the mapper (e.g.,
transaction.extraDataForDrawer.isTestDeposit), consider switching this check to that boolean (or at least centralizing the string in a shared constant) so card/header/test‑memo logic all stay in sync.Also applies to: 95-97, 134-144, 183-186, 193-204
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx (1)
16-16: Header test‑transaction UX works, but test detection should be centralizedThe dedicated test‑transaction header (Peanut logo + “Enjoy Peanut!” title, no arrow icon) is a nice, clear treatment and
getIconcorrectly suppresses arrows for link or test transactions. However:
isTestTransactionis inferred twice: once insidegetTitleviadisplayName === 'Enjoy Peanut!'and again in the component viauserName === 'Enjoy Peanut!', whileTransactionCardhas its ownname === 'Enjoy Peanut!'check.- That repeats the same magic string and slightly different inputs (displayName vs userName), and the TODO already notes this is a “bad check” temporary fix.
To reduce drift, consider driving all of this from a single boolean on the mapped transaction data (e.g.,
isTestDeposit) and optionally extracting a shared helper/constant for the label, so header, card, and memo behavior stay aligned when the backend or copy inevitably changes.Also applies to: 83-86, 121-125, 154-182, 212-215, 226-295
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/components/TransactionDetails/TransactionCard.tsx(4 hunks)src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx(6 hunks)src/components/TransactionDetails/TransactionDetailsReceipt.tsx(2 hunks)src/components/TransactionDetails/transactionTransformer.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/TransactionDetails/TransactionDetailsReceipt.tsx
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1089
File: src/components/LandingPage/dropLink.tsx:35-42
Timestamp: 2025-08-12T17:44:04.268Z
Learning: In the Peanut UI project, opening the `/setup` route in a new tab from landing page CTAs is intentional design behavior to keep users on the marketing page while they start the setup process.
📚 Learning: 2025-08-14T12:46:10.706Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1089
File: src/components/LandingPage/noFees.tsx:282-285
Timestamp: 2025-08-14T12:46:10.706Z
Learning: In the peanutprotocol/peanut-ui project, loading states are implemented only after they have been properly designed by the design team to ensure consistency across the application.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsx
📚 Learning: 2025-10-08T17:13:13.155Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1299
File: src/app/(mobile-ui)/points/page.tsx:41-51
Timestamp: 2025-10-08T17:13:13.155Z
Learning: In `src/app/(mobile-ui)/points/page.tsx`, the icon name "invite-heart" is intentionally used (not "inviter-heart") when displaying who invited the current user, as this is a deliberate design choice despite semantic differences with UserHeader usage.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsxsrc/components/TransactionDetails/TransactionDetailsHeaderCard.tsx
📚 Learning: 2025-05-23T19:26:58.220Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 873
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:95-95
Timestamp: 2025-05-23T19:26:58.220Z
Learning: The GeneralRecipientInput component supports username validation and resolution through the validateAndResolveRecipient function in src/lib/validation/recipient.ts. The function automatically detects usernames (inputs that don't contain '.' for ENS and don't start with '0x' for addresses), validates them via API HEAD request, fetches user data, and resolves them to Ethereum addresses from the user's PEANUT_WALLET account.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsxsrc/components/TransactionDetails/TransactionDetailsHeaderCard.tsx
📚 Learning: 2025-10-29T11:27:59.248Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1368
File: src/components/Common/ActionList.tsx:109-111
Timestamp: 2025-10-29T11:27:59.248Z
Learning: In `src/components/Common/ActionList.tsx`, the `balance` from `useWallet()` hook is always in USDC (as a formatted string), making it directly comparable to USD amounts without conversion. The comparison `Number(balance) >= amountInUsd` is intentional and correct.
Applied to files:
src/components/TransactionDetails/TransactionCard.tsx
📚 Learning: 2025-06-18T19:56:55.443Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 919
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:87-87
Timestamp: 2025-06-18T19:56:55.443Z
Learning: In withdraw flows for Peanut Wallet, the PeanutActionDetailsCard should always display "USDC" as the token symbol because it shows the amount being withdrawn from the Peanut Wallet (which holds USDC), regardless of the destination token/chain selected by the user. The TokenSelector is used for choosing the withdrawal destination, not the source display.
Applied to files:
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx
📚 Learning: 2025-09-05T07:31:11.396Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1185
File: src/components/Claim/useClaimLink.tsx:14-0
Timestamp: 2025-09-05T07:31:11.396Z
Learning: In the peanut-ui codebase, `window.history.replaceState` is preferred over `router.replace` when immediate/synchronous URL parameter updates are required, as `router.replace` is asynchronous and doesn't guarantee instant URL changes that subsequent code can rely on. This pattern is used consistently across usePaymentInitiator.ts, Confirm.payment.view.tsx, and useClaimLink.tsx.
Applied to files:
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx
📚 Learning: 2025-11-07T11:51:58.900Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1419
File: src/components/Global/BalanceWarningModal/index.tsx:94-94
Timestamp: 2025-11-07T11:51:58.900Z
Learning: In `src/components/Global/BalanceWarningModal/index.tsx`, the casual and congratulatory phrase "You're rich! Congrats on having a high balance." is intentional and by design.
Applied to files:
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx
📚 Learning: 2024-12-11T10:13:22.806Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 564
File: src/components/Request/Pay/Views/Initial.view.tsx:430-430
Timestamp: 2024-12-11T10:13:22.806Z
Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2024-11-18T21:36:11.486Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2025-07-07T20:22:11.092Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 958
File: src/app/actions/tokens.ts:266-266
Timestamp: 2025-07-07T20:22:11.092Z
Learning: In `src/app/actions/tokens.ts`, within the `fetchWalletBalances` function, using the non-null assertion operator `!` on `process.env.MOBULA_API_KEY!` is intentional and correct, and should not be flagged for replacement with explicit validation.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2025-09-18T09:30:42.901Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1230
File: src/app/(mobile-ui)/withdraw/page.tsx:92-97
Timestamp: 2025-09-18T09:30:42.901Z
Learning: In src/app/(mobile-ui)/withdraw/page.tsx, the useEffect that calls setShowAllWithdrawMethods(true) when amountFromContext exists is intentionally designed to run only on component mount (empty dependency array), not when amountFromContext changes. This is the correct behavior for the withdraw flow where showing all methods should only happen on initial load when an amount is already present.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2025-02-17T14:07:49.883Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 669
File: src/lib/validation/recipient.ts:21-56
Timestamp: 2025-02-17T14:07:49.883Z
Learning: In the peanut-ui repository, wrapping switch case blocks in braces to comply with linter rules and avoid variable leakage is considered a non-blocking style improvement.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2024-10-08T20:13:42.967Z
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 413
File: src/components/Request/Pay/Views/Initial.view.tsx:71-72
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, it's acceptable to use the `!` operator in TypeScript to assert that `selectedTokenData` is not `null` or `undefined`, and potential runtime errors from accessing its properties without checks can be disregarded.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
🧬 Code graph analysis (1)
src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx (2)
src/components/Global/Icons/Icon.tsx (2)
IconName(71-138)Icon(215-224)src/components/UserHeader/index.tsx (1)
VerifiedUserLabel(46-124)
🪛 Biome (2.1.2)
src/components/TransactionDetails/transactionTransformer.ts
[error] 334-334: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/components/TransactionDetails/transactionTransformer.ts (1)
512-515: Consider centralizing test-deposit detection and normalizingusdAmountYou’re effectively detecting “test deposits” twice: once via
isTestTransactionin the DEPOSIT branch and again viaisTestDeposithere with the same condition. That can drift over time and makes behavior harder to reason about.Two concrete tweaks to consider:
- Compute a single
const isTestDeposit = /* condition */once (outside the switch or just above) and reuse it in both the DEPOSIT case (fornameForDetails) and here (formemo).- Instead of
entry.extraData?.usdAmount === '0', normalize as you already do foramount, e.g.parseFloat(String(entry.extraData?.usdAmount ?? '').replace(/[^\d.-]/g, '')) === 0, so numeric0or"0.00"are also treated as test deposits.This keeps the “test transaction” behavior consistent and more robust if the backend ever changes the formatting of
usdAmount.Also applies to: 533-533
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/components/TransactionDetails/transactionTransformer.ts(3 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1089
File: src/components/LandingPage/dropLink.tsx:35-42
Timestamp: 2025-08-12T17:44:04.268Z
Learning: In the Peanut UI project, opening the `/setup` route in a new tab from landing page CTAs is intentional design behavior to keep users on the marketing page while they start the setup process.
📚 Learning: 2024-11-18T21:36:11.486Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2024-12-11T10:13:22.806Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 564
File: src/components/Request/Pay/Views/Initial.view.tsx:430-430
Timestamp: 2024-12-11T10:13:22.806Z
Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2025-07-07T20:22:11.092Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 958
File: src/app/actions/tokens.ts:266-266
Timestamp: 2025-07-07T20:22:11.092Z
Learning: In `src/app/actions/tokens.ts`, within the `fetchWalletBalances` function, using the non-null assertion operator `!` on `process.env.MOBULA_API_KEY!` is intentional and correct, and should not be flagged for replacement with explicit validation.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2025-09-18T09:30:42.901Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1230
File: src/app/(mobile-ui)/withdraw/page.tsx:92-97
Timestamp: 2025-09-18T09:30:42.901Z
Learning: In src/app/(mobile-ui)/withdraw/page.tsx, the useEffect that calls setShowAllWithdrawMethods(true) when amountFromContext exists is intentionally designed to run only on component mount (empty dependency array), not when amountFromContext changes. This is the correct behavior for the withdraw flow where showing all methods should only happen on initial load when an amount is already present.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2025-02-17T14:07:49.883Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 669
File: src/lib/validation/recipient.ts:21-56
Timestamp: 2025-02-17T14:07:49.883Z
Learning: In the peanut-ui repository, wrapping switch case blocks in braces to comply with linter rules and avoid variable leakage is considered a non-blocking style improvement.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
📚 Learning: 2024-10-08T20:13:42.967Z
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 413
File: src/components/Request/Pay/Views/Initial.view.tsx:71-72
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, it's acceptable to use the `!` operator in TypeScript to assert that `selectedTokenData` is not `null` or `undefined`, and potential runtime errors from accessing its properties without checks can be disregarded.
Applied to files:
src/components/TransactionDetails/transactionTransformer.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (1)
src/components/TransactionDetails/transactionTransformer.ts (1)
330-342: DEPOSIT case scoping and test-transaction label look correctWrapping the
EHistoryEntryType.DEPOSITcase body in a block correctly scopesisTestTransactionand satisfies the noSwitchDeclarations rule, and the zero-amount check cleanly switches the label to"Enjoy Peanut!"without affecting non-test deposits.
No description provided.