Skip to content

Conversation

jjramirezn
Copy link
Contributor

No description provided.

kushagrasarathe and others added 30 commits May 30, 2025 20:31
feat: standalone receipts without drawer + share receipt
Copy link

Sprint 94 prod release

Copy link

vercel bot commented Jun 6, 2025

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

Name Status Preview Comments Updated (UTC)
peanut-ui (peanut-wallet-staging) ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 6, 2025 4:54pm

Copy link
Contributor

coderabbitai bot commented Jun 6, 2025

Walkthrough

This update introduces new PWA support features, device/browser environment detection utilities, and UI enhancements for onboarding and transaction flows. Major changes include assetlinks for Android app association, improved setup and install flows for PWAs, new modal components for iOS install and add-money prompts, expanded color utilities, avatar styling updates, and enhancements to user profile and transaction details displays.

Changes

Files / Areas Change Summary
public/.well-known/assetlinks.json Added assetlinks.json for web-app association and permissions.
src/app/(mobile-ui)/history/layout.tsx, src/app/(mobile-ui)/layout.tsx, src/app/sitemap.ts Updated page metadata titles and base URLs; fixed return block scoping.
src/app/(mobile-ui)/home/page.tsx, src/components/Home/AddMoneyPromptModal/index.tsx Added AddMoneyPromptModal and IOSInstallPWAModal with state and effects controlling visibility based on device and user state.
src/app/(setup)/setup/page.tsx, src/components/Setup/Setup.consts.tsx, src/components/Setup/Setup.types.ts, src/components/Setup/Setup.utils.ts, src/components/Setup/components/SetupWrapper.tsx, src/components/Setup/Views/InstallPWA.tsx, src/components/Setup/Views/Signup.tsx, src/components/Setup/Views/Welcome.tsx, src/components/Setup/Views/SetupPasskey.ts Refactored setup flow for improved device/browser detection, added Android PWA install step, updated UI/layouts and error handling, removed deprecated components (ContactInfo, StepTransition), and enhanced login error handling.
src/app/[...recipient]/client.tsx, src/components/Claim/Claim.tsx, src/components/Claim/Link/Initial.view.tsx, src/components/Claim/Claim.consts.ts Refined claim flow by adding claimToExternalWallet state and setter, updated transaction details rendering from drawer to receipt, enhanced recipient handling, and passed new props accordingly.
src/components/Global/IOSInstallPWAModal/index.tsx, src/components/Global/UnsupportedBrowserModal/index.tsx Added new modal components for iOS PWA install instructions and unsupported browser detection with copy-to-clipboard and toast feedback.
src/components/Global/ErrorAlert/index.tsx Refactored ErrorAlert component for flexible styling and icon customization.
src/components/Global/PeanutActionDetailsCard/index.tsx, src/components/Profile/AvatarWithBadge.tsx, src/components/User/UserCard.tsx, src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx, src/components/TransactionDetails/TransactionAvatarBadge.tsx Updated avatar and badge color logic to use new dual-shade color model (lightShade and darkShade) instead of single background color.
src/components/TransactionDetails/TransactionDetailsDrawer.tsx Modularized drawer and receipt UI into separate components, added dynamic height handling, and refined conditional rendering and button behaviors for pending transactions.
src/components/Profile/components/ProfileHeader.tsx, src/components/Profile/components/PublicProfile.tsx Added optional share button prop, displayed total sent/received USD amounts, updated UI logic and API calls with authorization headers.
src/components/Global/TokenSelector/TokenSelector.tsx, src/components/AddMoney/views/NetworkSelection.view.tsx, src/components/0_Bruddle/Button.tsx, src/components/Request/direct-request/views/Initial.direct.request.view.tsx Minor UI and logic adjustments including button variant colors, container alignment, and input reset behavior.
src/app/manifest.ts Added icons with both "maskable" and "any" purposes to manifest.
src/assets/peanut/index.ts Exported new asset PEANUTMAN_WAVING SVG.
src/context/authContext.tsx, src/context/kernelClient.context.tsx Improved logout behavior by clearing session flags and explicitly logging out when auth keys are missing; enhanced error handling with Sentry reporting.
src/hooks/useTransactionHistory.ts, src/hooks/useZeroDev.ts Enhanced transaction link construction and centralized passkey login error handling with custom error class.
src/services/users.ts, src/interfaces/interfaces.ts, src/utils/general.utils.ts Extended user and API types with PWA installation and transaction statistics properties; added authorization headers to user API calls.
src/utils/color.utils.ts Changed color mapping to dual-shade objects, updated related constants and color utility functions accordingly.

Possibly related PRs

  • peanutprotocol/peanut-ui#894: Refactors setup page and adds device/browser detection utilities, directly related to this PR’s setup flow and environment checks.
  • peanutprotocol/peanut-ui#893: Adds AddMoneyPromptModal and integrates it into the Home page, matching the same modal and logic introduced here.
  • peanutprotocol/peanut-ui#883: Updates PublicProfile and usersApi to handle/display total sent/received USD, paralleling the same user profile enhancements in this PR.

Suggested reviewers

  • jjramirezn

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a24082d and 7319afd.

📒 Files selected for processing (1)
  • src/components/Setup/Views/SetupPasskey.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/Setup/Views/SetupPasskey.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 15

🧹 Nitpick comments (10)
src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx (1)

64-65: Good transition to new color utility structure, but simplify redundant conditional.

The update to use lightShade from the new color utility structure is correct. However, the color assignment can be simplified since both conditions set the color to 'black'.

Apply this diff to simplify the redundant conditional:

-                                            color: method.icon === ('bank' as IconName) ? 'black' : 'black',
+                                            color: 'black',
src/components/Global/PeanutActionDetailsCard/index.tsx (1)

88-100: Optimize duplicate getColorForUsername calls for better performance.

The logic correctly implements the dual-shade color system and properly handles the ENS recipient type. However, getColorForUsername(recipientName) is called twice with the same arguments, which could impact performance.

Consider memoizing the color result:

+                const userColors = useMemo(() => getColorForUsername(recipientName), [recipientName])
                 inlineStyle={{
                     backgroundColor:
                         viewType === 'SUCCESS'
                             ? '#29CC6A'
                             : transactionType === 'ADD_MONEY' ||
                                 recipientType === 'ADDRESS' ||
                                 recipientType === 'ENS'
                               ? '#FFC900'
-                              : getColorForUsername(recipientName).lightShade,
+                              : userColors.lightShade,
                     color:
                         viewType === 'SUCCESS'
                             ? AVATAR_TEXT_DARK
                             : transactionType === 'ADD_MONEY' ||
                                 recipientType === 'ADDRESS' ||
                                 recipientType === 'ENS'
                               ? AVATAR_TEXT_DARK
-                              : getColorForUsername(recipientName).darkShade,
+                              : userColors.darkShade,
                 }}

Don't forget to import useMemo from React if not already imported.

src/components/Profile/AvatarWithBadge.tsx (1)

73-76: Optimize duplicate getColorForUsername calls and approve styling logic.

The dual-shade color implementation is excellent - using lightShade for background and darkShade for border/text provides good visual hierarchy and contrast. However, getColorForUsername(name) is called multiple times with the same argument.

Consider memoizing the color result:

+    const userColors = useMemo(() => name ? getColorForUsername(name) : null, [name])
+
     return (
         <div className={'relative'}>
             {/* the main avatar circle */}
             <div
                 className={twMerge(
                     `flex items-center justify-center rounded-full font-bold`,
                     sizeClasses[size],
                     className
                 )}
                 style={{
-                    background: name ? getColorForUsername(name).lightShade : undefined,
-                    border: name && !icon ? `1px solid ${getColorForUsername(name).darkShade}` : undefined,
-                    color: name ? getColorForUsername(name).darkShade : !icon ? textColor : undefined,
+                    background: userColors?.lightShade,
+                    border: name && !icon ? `1px solid ${userColors?.darkShade}` : undefined,
+                    color: userColors?.darkShade || (!icon ? textColor : undefined),
                     ...inlineStyle,
                 }}
             >
src/components/TransactionDetails/TransactionDetailsDrawer.tsx (1)

225-235: Remove unnecessary Fragment wrapper

The Fragment is redundant here since it only contains conditional content that can be rendered directly.

-                    {transaction.status === 'cancelled' &&
-                        transaction.extraDataForDrawer?.originalUserRole === EHistoryUserRole.BOTH &&
-                        transaction.cancelledDate && (
-                            <>
-                                {transaction.cancelledDate && (
-                                    <PaymentInfoRow
-                                        label="Cancelled"
-                                        value={formatDate(transaction.cancelledDate as Date)}
-                                        hideBottomBorder={
-                                            !transaction.fee && !transaction.memo && !transaction.attachmentUrl
-                                        }
-                                    />
-                                )}
-                            </>
-                        )}
+                    {transaction.status === 'cancelled' &&
+                        transaction.extraDataForDrawer?.originalUserRole === EHistoryUserRole.BOTH &&
+                        transaction.cancelledDate && (
+                            <PaymentInfoRow
+                                label="Cancelled"
+                                value={formatDate(transaction.cancelledDate as Date)}
+                                hideBottomBorder={
+                                    !transaction.fee && !transaction.memo && !transaction.attachmentUrl
+                                }
+                            />
+                        )}
🧰 Tools
🪛 Biome (1.9.4)

[error] 225-235: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

src/components/Setup/Views/Welcome.tsx (1)

61-61: Minor: Consider consistent capitalization.

The button text "Log In" uses title case while most other buttons use sentence case. Consider using "Log in" for consistency with common UI patterns.

-                    Log In
+                    Log in
src/components/Setup/Setup.utils.ts (1)

1-1: Consider potential import path fragility.

The relative import path '../Global/UnsupportedBrowserModal' could break if the file structure changes. Consider using an absolute import or exporting inAppSignatures from a constants file.

-import { inAppSignatures } from '../Global/UnsupportedBrowserModal'
+import { inAppSignatures } from '@/constants/browser-detection'

Or create a centralized constants file to avoid coupling this utility to a modal component.

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

47-82: Consider explicit handling for Firefox browser

Firefox is detected in getIOSBrowserType but falls into the else block (lines 66-81) with instructions to open in Safari. If this is intentional because Firefox on iOS doesn't support PWA installation, consider making this more explicit for better code clarity.

-    // default to standard instructions (Chrome, Safari, Arc)
-    if (browserType === 'safari' || browserType === 'chrome' || browserType === 'other') {
+    // browsers that support PWA installation on iOS
+    if (browserType === 'safari' || browserType === 'chrome') {
         descriptionTextJsx = (
             <p className="flex flex-col items-center gap-1 text-sm text-grey-1">
                 <span className="flex items-center gap-2">
                     Tap the
                     <span className="flex items-center gap-1 font-bold">
                         <Icon name="share" size={16} /> Share icon
                     </span>
                 </span>
                 <span>
                     {' '}
                     then on <span className="font-bold"> "Add To Home Screen"</span>
                 </span>
             </p>
         )
-    } else {
-        // fallback for Brave and potentially other non-standard WebKit browsers
+    } else if (browserType === 'firefox' || browserType === 'brave' || browserType === 'other') {
+        // browsers that don't support PWA installation on iOS
         descriptionTextJsx = (
src/components/Global/UnsupportedBrowserModal/index.tsx (1)

107-124: Remove redundant visible prop

The visible={true} prop on line 109 is redundant since the component already handles visibility by returning null on lines 71-73 when the modal shouldn't be shown.

         <ActionModal
-            visible={true}
             onClose={handleModalClose}
             title="Open this link in your browser"
src/app/(setup)/setup/page.tsx (1)

176-177: Document the intentionally empty onClose handler

The empty function for onClose might be confusing to other developers. Consider adding a comment to clarify that this modal is intentionally not closeable.

                 visible={true}
-                onClose={() => {}} // no action on close for this modal
+                onClose={() => {
+                    // Intentionally empty - this modal cannot be closed by the user
+                }}
                 title="Device not supported!"
src/components/Setup/Views/InstallPWA.tsx (1)

104-113: Consider alternative to opening new tab after PWA installation.

Opening a new tab to /setup after installation might confuse users. Consider:

  • Showing instructions to open the installed PWA from home screen
  • Using a more descriptive button label
  • Avoiding multiple tabs with the same content

Instead of automatically opening a new tab, consider showing instructions:

-} else {
-    const link = document.createElement('a')
-    link.href = '/setup'
-    link.target = '_blank'
-    document.body.appendChild(link)
-    link.click()
-    document.body.removeChild(link)
-}
+} else {
+    // Show instructions to user to open PWA from home screen
+    toast.info('Please open Peanut from your home screen to continue in the app')
+}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 81c6944 and a24082d.

⛔ Files ignored due to path filters (1)
  • src/assets/peanut/peanutman-waving.svg is excluded by !**/*.svg
📒 Files selected for processing (46)
  • public/.well-known/assetlinks.json (1 hunks)
  • src/app/(mobile-ui)/history/layout.tsx (1 hunks)
  • src/app/(mobile-ui)/home/page.tsx (6 hunks)
  • src/app/(mobile-ui)/layout.tsx (1 hunks)
  • src/app/(setup)/setup/page.tsx (4 hunks)
  • src/app/[...recipient]/client.tsx (4 hunks)
  • src/app/manifest.ts (1 hunks)
  • src/app/sitemap.ts (1 hunks)
  • src/assets/peanut/index.ts (1 hunks)
  • src/components/0_Bruddle/Button.tsx (1 hunks)
  • src/components/AddMoney/views/NetworkSelection.view.tsx (1 hunks)
  • src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx (1 hunks)
  • src/components/Claim/Claim.consts.ts (1 hunks)
  • src/components/Claim/Claim.tsx (3 hunks)
  • src/components/Claim/Link/Initial.view.tsx (8 hunks)
  • src/components/Global/ErrorAlert/index.tsx (1 hunks)
  • src/components/Global/IOSInstallPWAModal/index.tsx (1 hunks)
  • src/components/Global/PeanutActionDetailsCard/index.tsx (2 hunks)
  • src/components/Global/TokenSelector/TokenSelector.tsx (0 hunks)
  • src/components/Global/UnsupportedBrowserModal/index.tsx (1 hunks)
  • src/components/Home/AddMoneyPromptModal/index.tsx (1 hunks)
  • src/components/Profile/AvatarWithBadge.tsx (1 hunks)
  • src/components/Profile/components/ProfileHeader.tsx (2 hunks)
  • src/components/Profile/components/PublicProfile.tsx (5 hunks)
  • src/components/Request/direct-request/views/Initial.direct.request.view.tsx (0 hunks)
  • src/components/Setup/Setup.consts.tsx (2 hunks)
  • src/components/Setup/Setup.types.ts (3 hunks)
  • src/components/Setup/Setup.utils.ts (1 hunks)
  • src/components/Setup/Views/ContactInfo.tsx (0 hunks)
  • src/components/Setup/Views/InstallPWA.tsx (2 hunks)
  • src/components/Setup/Views/SetupPasskey.tsx (2 hunks)
  • src/components/Setup/Views/Signup.tsx (4 hunks)
  • src/components/Setup/Views/Welcome.tsx (3 hunks)
  • src/components/Setup/components/SetupWrapper.tsx (6 hunks)
  • src/components/Setup/components/StepTransition.tsx (0 hunks)
  • src/components/TransactionDetails/TransactionAvatarBadge.tsx (1 hunks)
  • src/components/TransactionDetails/TransactionDetailsDrawer.tsx (5 hunks)
  • src/components/User/UserCard.tsx (2 hunks)
  • src/context/authContext.tsx (2 hunks)
  • src/context/kernelClient.context.tsx (1 hunks)
  • src/hooks/useTransactionHistory.ts (1 hunks)
  • src/hooks/useZeroDev.ts (5 hunks)
  • src/interfaces/interfaces.ts (1 hunks)
  • src/services/users.ts (3 hunks)
  • src/utils/color.utils.ts (3 hunks)
  • src/utils/general.utils.ts (1 hunks)
💤 Files with no reviewable changes (4)
  • src/components/Request/direct-request/views/Initial.direct.request.view.tsx
  • src/components/Global/TokenSelector/TokenSelector.tsx
  • src/components/Setup/Views/ContactInfo.tsx
  • src/components/Setup/components/StepTransition.tsx
🧰 Additional context used
🧠 Learnings (1)
src/components/Claim/Link/Initial.view.tsx (1)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#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.
🧬 Code Graph Analysis (15)
src/hooks/useTransactionHistory.ts (1)
src/constants/general.consts.ts (1)
  • BASE_URL (43-43)
src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx (2)
src/utils/color.utils.ts (1)
  • getColorForUsername (51-69)
src/components/Global/Icons/Icon.tsx (1)
  • IconName (51-98)
src/context/kernelClient.context.tsx (2)
src/context/authContext.tsx (1)
  • useAuth (202-208)
src/utils/general.utils.ts (1)
  • getFromLocalStorage (108-123)
src/components/Setup/Views/SetupPasskey.tsx (2)
src/components/0_Bruddle/Button.tsx (1)
  • Button (69-130)
src/redux/slices/setup-slice.ts (1)
  • setupActions (50-50)
src/components/User/UserCard.tsx (1)
src/utils/color.utils.ts (2)
  • getColorForUsername (51-69)
  • AVATAR_TEXT_DARK (44-44)
src/services/users.ts (2)
src/utils/sentry.utils.ts (1)
  • fetchWithSentry (11-89)
src/constants/general.consts.ts (1)
  • PEANUT_API_URL (37-41)
src/components/Profile/AvatarWithBadge.tsx (1)
src/utils/color.utils.ts (1)
  • getColorForUsername (51-69)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
src/utils/color.utils.ts (2)
  • getColorForUsername (51-69)
  • AVATAR_TEXT_DARK (44-44)
src/components/Setup/Setup.utils.ts (1)
src/components/Global/UnsupportedBrowserModal/index.tsx (1)
  • inAppSignatures (9-35)
src/app/[...recipient]/client.tsx (1)
src/components/TransactionDetails/TransactionDetailsDrawer.tsx (1)
  • TransactionDetailsReceipt (80-445)
src/components/Profile/components/PublicProfile.tsx (2)
src/context/authContext.tsx (1)
  • useAuth (202-208)
src/utils/general.utils.ts (1)
  • formatExtendedNumber (998-1046)
src/components/Global/ErrorAlert/index.tsx (1)
src/components/Global/Icons/Icon.tsx (1)
  • Icon (155-164)
src/components/Home/AddMoneyPromptModal/index.tsx (1)
src/components/Global/ActionModal/index.tsx (1)
  • ActionModalButtonProps (8-11)
src/app/(setup)/setup/page.tsx (4)
src/components/Setup/Setup.utils.ts (3)
  • getDeviceTypeForLogic (31-40)
  • isDeviceOsSupported (15-28)
  • isLikelyWebview (4-12)
src/components/Setup/Setup.types.ts (2)
  • ScreenId (1-11)
  • BeforeInstallPromptEvent (51-58)
src/redux/slices/setup-slice.ts (1)
  • setupActions (50-50)
src/components/Global/Icons/Icon.tsx (1)
  • IconName (51-98)
src/components/Global/IOSInstallPWAModal/index.tsx (2)
src/components/Global/Icons/Icon.tsx (1)
  • Icon (155-164)
src/components/Global/ActionModal/index.tsx (1)
  • ActionModalButtonProps (8-11)
🪛 Biome (1.9.4)
src/components/Setup/Views/InstallPWA.tsx

[error] 46-46: 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)


[error] 182-221: This case is falling through to the next case.

Add a break or return statement to the end of this case to prevent fallthrough.

(lint/suspicious/noFallthroughSwitchClause)

src/components/TransactionDetails/TransactionDetailsDrawer.tsx

[error] 225-235: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

src/components/Setup/components/SetupWrapper.tsx

[error] 101-101: 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)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview
🔇 Additional comments (79)
src/components/Profile/components/ProfileHeader.tsx (1)

18-18: Well-implemented conditional share button feature.

The addition of the showShareButton prop with a default value of true maintains backward compatibility while allowing fine-grained control over the share button visibility. The conditional rendering is clean and follows React best practices.

Also applies to: 21-27, 46-62

src/services/users.ts (1)

28-29: LGTM: Type extension for transaction totals.

The addition of totalUsdSent and totalUsdReceived properties to the ApiUser type is well-aligned with the UI requirements in PublicProfile.tsx.

src/components/Profile/components/PublicProfile.tsx (3)

35-37: LGTM: State management for transaction totals.

The state variables are properly initialized and the useAuth hook integration follows the established pattern.


52-53: LGTM: API data integration.

The transaction totals are correctly set from the API response data.


73-79: LGTM: Proper use of ProfileHeader with disabled share button.

The integration correctly utilizes the new showShareButton={false} prop to disable the share functionality in the public profile context.

src/components/0_Bruddle/Button.tsx (1)

43-43: LGTM! Button variant styling update looks good.

The change from 'bg-primary-3' to 'bg-white' for the 'primary-soft' variant aligns with the broader UI updates mentioned in the PR.

src/components/TransactionDetails/TransactionAvatarBadge.tsx (1)

83-84: Excellent implementation of the new dual-shade color model.

The transition from single background color to using lightShade for background and darkShade for text color maintains proper contrast while aligning with the refactored color utility structure.

src/components/User/UserCard.tsx (2)

2-2: Good addition of color constant import for maintainability.

Adding AVATAR_TEXT_DARK to the imports improves code maintainability by replacing hardcoded color values with named constants.


55-59: Excellent implementation of the dual-shade color model with improved consistency.

The transition to using lightShade/darkShade from the new color utility structure is well-implemented. The use of the AVATAR_TEXT_DARK constant instead of hardcoded #FFD700 improves maintainability and provides better semantic meaning.

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

5-5: LGTM: Import addition aligns with dual-shade color system.

The import of AVATAR_TEXT_DARK is consistent with the new color utility structure.

src/utils/color.utils.ts (3)

7-35: Excellent refactor to dual-shade color system.

The transition from single hex colors to objects with lightShade and darkShade properties is a well-designed improvement that provides better flexibility for creating consistent color hierarchies across the UI.


51-69:

✅ Verification successful

Approve function refactor with return type change.

The updated getColorForUsername function correctly implements the dual-shade system. This is a breaking change that requires updating all call sites to use the new object structure instead of the previous single string return value.

Verify that all existing usages of getColorForUsername have been updated to handle the new return type:


🏁 Script executed:

#!/bin/bash
# Search for any remaining usages that might expect the old string return type
rg -A 5 -B 2 "getColorForUsername.*\." --type ts --type tsx

Length of output: 89


🏁 Script executed:

#!/bin/bash
# Search for all usages of getColorForUsername across .ts and .tsx files
rg "getColorForUsername" -g '*.ts' -g '*.tsx' -n

Length of output: 2032


🏁 Script executed:

#!/bin/bash
# Show context around usage in TransactionAvatarBadge to verify handling of returned object
rg -A5 -B5 "getColorForUsername" -n src/components/TransactionDetails/TransactionAvatarBadge.tsx

Length of output: 981


All usages updated to the new return type

I’ve verified that every call site now accesses the returned object’s darkShade and lightShade properties instead of expecting a single string. No instances of getColorForUsername(...) being used as a plain string remain.

Checked files:

  • src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx
  • src/components/Profile/AvatarWithBadge.tsx
  • src/components/Global/PeanutActionDetailsCard/index.tsx
  • src/components/User/UserCard.tsx
  • src/components/TransactionDetails/TransactionAvatarBadge.tsx

38-39:

❓ Verification inconclusive

Verify hardcoded color values align with design system.

The hardcoded AVATAR_LINK_BG value #FF90E8 and the use of yellow.darkShade for AVATAR_WALLET_BG should be consistent with the design system.


🏁 Script executed:

#!/bin/bash
# Search for any remaining references to old color constants that might need updating
rg -A 3 -B 3 "AVATAR_(LINK|WALLET)_BG|backgroundColor.*getColorForUsername" --type ts --type tsx

Length of output: 126


To catch all occurrences and inspect your color tokens, let’s broaden the search (the previous --type tsx flag isn’t recognized here).


🏁 Script executed:

#!/bin/bash
# 1) Look for any usage of the AVATAR constants or getColorForUsername across .ts/.tsx
rg 'AVATAR_(LINK|WALLET)_BG|backgroundColor.*getColorForUsername' -g '*.ts' -g '*.tsx' -A 3 -B 3

# 2) Locate where COLORS_MAPPING is defined to confirm the yellow.darkShade value
rg 'export const COLORS_MAPPING' -g '*.ts' -A 5

# 3) Check if the hardcoded hex #FF90E8 appears elsewhere (e.g. design tokens JSON)
rg '#FF90E8' -g '*.json' -g '*.ts' -g '*.tsx'

Length of output: 6803


Verify avatar background colors against design tokens

Please confirm that both hardcoded and mapped values align with the design system:

  • In src/utils/color.utils.ts:
    • AVATAR_LINK_BG = '#FF90E8' (also used as the caret color in src/components/SearchUsers/SearchInput.tsx). Ensure this hex matches the official “link” color token, and if so, replace it with that token instead of hardcoding.
    • AVATAR_WALLET_BG = COLORS_MAPPING.yellow.darkShade. Verify that yellow.darkShade corresponds to the spec’d wallet/avatar background color and update the mapping if it doesn’t.
src/hooks/useTransactionHistory.ts (1)

169-173: LGTM! Consistent link generation for DIRECT_SEND transactions.

The addition of link generation for DIRECT_SEND transactions follows the exact same pattern as the REQUEST case, ensuring consistency in how transaction links are constructed across different transaction types.

src/components/Claim/Claim.consts.ts (1)

59-60: LGTM! Clean interface extension for external wallet functionality.

The addition of claimToExternalWallet state and setter follows standard React patterns and clearly extends the interface to support external wallet claiming functionality.

src/components/Claim/Claim.tsx (3)

54-54: LGTM! External wallet state added consistently.

The new claimToExternalWallet state variable aligns with the interface changes and follows React state management patterns.


273-274: LGTM! Props correctly passed to FlowManager.

The new claimToExternalWallet state and setter are properly passed to the FlowManager component, maintaining the data flow consistency.


281-281: LGTM! Component replacement aligns with UI refactor.

The replacement of TransactionDetailsDrawer with TransactionDetailsReceipt is consistent with the component restructuring seen across multiple files, properly separating the drawer container from the receipt content.

src/app/[...recipient]/client.tsx (4)

258-262: LGTM! Improved username resolution with fallback chain.

The enhanced username resolution provides a robust fallback chain: recipientAccount?.user?.usernamerecipientAccount?.identifierchargeDetails.requestLink.recipientAddress, ensuring a display value is always available.


262-262: LGTM! Clear user role determination.

The originalUserRole variable clearly determines whether the current user is the recipient or sender, improving code readability and logic clarity.


274-276: LGTM! Refined link transaction logic.

The isLinkTransaction flag is now more precise, only set to true when the original user role is SENDER and matches the current user. The explicit setting of originalUserRole improves transaction context tracking.


402-403: LGTM! Proper conditional rendering with new component.

The conditional rendering correctly checks if the drawer is open and the selected transaction matches before rendering the TransactionDetailsReceipt component, maintaining the intended UI behavior.

src/components/TransactionDetails/TransactionDetailsDrawer.tsx (1)

31-78: Well-structured component separation

The refactoring to separate the drawer container from the receipt content is a good architectural improvement. The addition of dynamic height calculation and internal loading state management enhances the user experience.

src/components/Claim/Link/Initial.view.tsx (1)

571-573: Good UX improvements for username recipients

The disabled state for TokenSelector and the informative text for username recipients clearly communicate the constraints to users. This improves the user experience by setting proper expectations.

Also applies to: 605-609

src/components/Global/ErrorAlert/index.tsx (6)

1-1: Good addition of twMerge for flexible styling.

The import of twMerge supports the enhanced styling flexibility introduced in this refactor.


5-7: Enhanced props interface with better typing.

The updated props interface improves the component's flexibility by:

  • Removing the unused label prop
  • Adding className with proper TypeScript typing
  • Adding iconSize and iconClassName for icon customization

11-11: Good default value for iconSize.

The default iconSize of 16 provides a reasonable baseline while allowing customization.


13-13: Proper use of twMerge for class composition.

The implementation correctly uses twMerge to combine default classes with optional custom classes, allowing for proper Tailwind CSS class overrides.


14-14: Good icon styling implementation.

The icon implementation properly:

  • Uses the configurable iconSize prop
  • Applies twMerge for flexible class composition
  • Maintains proper spacing with mt-0.5 min-w-fit

15-15: Simplified description styling is appropriate.

Removing explicit font classes from the description div allows it to inherit styling from the container, which is cleaner and more maintainable.

src/app/(mobile-ui)/history/layout.tsx (1)

6-6: Title shortened appropriately for mobile UI.

The change from "Transaction History | Peanut" to "History | Peanut" is appropriate for mobile UI, providing a more concise title while maintaining clarity. The description on line 7-8 still provides the full context for SEO purposes.

src/assets/peanut/index.ts (1)

10-10: New asset export follows established pattern.

The addition of PEANUTMAN_WAVING follows the established naming convention and export pattern used for other Peanut assets in this file.

src/components/AddMoney/views/NetworkSelection.view.tsx (1)

38-38: LGTM! Layout alignment improvement.

The addition of self-start class improves the component's alignment behavior within its parent flex/grid container, ensuring consistent layout positioning.

src/interfaces/interfaces.ts (1)

377-377: LGTM! Well-structured PWA tracking addition.

The hasPwaInstalled boolean property provides clear tracking of PWA installation status in the user profile, supporting the new PWA functionality being introduced.

src/app/(mobile-ui)/layout.tsx (1)

75-81: LGTM! Code quality improvement.

Adding curly braces around the return statement improves code readability and ensures proper block scoping while maintaining the same functional behavior.

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

707-707: LGTM! Consistent PWA preference tracking.

The optional isPwaInstalled property appropriately extends user preferences to track PWA installation status, complementing the similar addition to the user profile interface.

src/context/kernelClient.context.tsx (2)

125-125: LGTM: Correct import addition for logout functionality.

The addition of logoutUser to the destructuring is necessary for the new logout call below and follows the existing pattern.


132-135:

✅ Verification successful

Good defensive programming to prevent mixed authentication states.

Explicitly calling logoutUser() when no WebAuthn key is found prevents inconsistent authentication state. The logic is sound and the comment clearly explains the intent.

Verify that this logout call doesn't create any circular dependencies or infinite loops:


🏁 Script executed:

#!/bin/bash
# Description: Check for potential circular dependencies between KernelClientProvider and logout functionality

# Search for logoutUser implementations and calls to understand the flow
ast-grep --pattern 'const logoutUser = $_'
echo "=== logoutUser implementations ==="

# Search for any useEffect or initialization that might conflict
rg -A 5 -B 5 "logoutUser\(\)" src/context/
echo "=== logoutUser calls in context files ==="

# Check if logout clears localStorage items that might trigger this useEffect again
rg -A 3 -B 3 "removeItem.*web.*authn" src/

Length of output: 3663


Logout logic is safe and free of loops

The useEffect in kernelClient.context.tsx runs only once on mount (empty dependency array), so calling logoutUser() won’t re-trigger that effect. Additionally, logoutUser ends with a router.replace('/setup') rather than a state change in this component, so the provider won’t remount and no infinite loop or circular dependency occurs.

Great work—this change can be approved.

src/app/manifest.ts (1)

34-45: Excellent PWA best practice implementation.

Adding icons with purpose: 'any' alongside the existing purpose: 'maskable' icons ensures optimal compatibility across different platforms and devices. This follows PWA manifest best practices where:

  • maskable icons work well with Android's adaptive/themed icons
  • any purpose icons serve as fallbacks for other platforms
public/.well-known/assetlinks.json (1)

1-16:

✅ Verification successful

Correctly implemented Android Digital Asset Links for PWA support.

The assetlinks.json file is properly structured for Android PWA integration:

  • query_webapk permission enables checking WebAPK installation status
  • handle_all_urls permission allows the PWA to handle domain URLs
  • JSON syntax and structure follow Google's Digital Asset Links specification

Verify that the manifest URL is accessible and matches the actual manifest location:


🏁 Script executed:

#!/bin/bash
# Description: Verify the manifest URL referenced in assetlinks.json is accessible

# Check if the manifest URL returns a valid response
curl -s -o /dev/null -w "%{http_code}" "https://peanut.me/manifest.webmanifest"
echo "HTTP status code for manifest URL"

# Also check the site URL
curl -s -o /dev/null -w "%{http_code}" "https://peanut.me"
echo "HTTP status code for main site URL"

Length of output: 300


Asset Links Validated – PWA Integration Approved

The assetlinks.json file is correctly structured for Android PWA support, and the referenced URLs are accessible:

No further changes required.

src/context/authContext.tsx (3)

2-2: LGTM: Necessary imports for enhanced logout functionality.

The added imports support the logout improvements:

  • useToast - ensures toast notifications work properly
  • useQueryClient - for query cache invalidation during logout
  • captureException - for improved error reporting with Sentry

Also applies to: 9-9, 12-12


160-163: Good session management for PWA prompt state.

Clearing the iOS PWA prompt session flag on logout ensures that the prompt can be shown again in new sessions. The browser environment check prevents SSR issues.


172-172: Enhanced error reporting with Sentry integration.

Adding captureException(error) improves error observability for logout failures while maintaining existing user feedback through console logs and toast notifications.

src/hooks/useZeroDev.ts (3)

22-31: LGTM! Excellent addition of custom error class.

The PasskeyError class provides structured error handling with error codes, which will improve error reporting and user experience throughout the authentication flow.


42-42: Good catch fixing the typo.

Fixed DOMAIM to DOMAIN in the comment.


89-101: Excellent error handling improvements.

The enhanced error handling provides better user experience by:

  • Specifically handling NotAllowedError (user canceled) with a helpful message and LOGIN_CANCELED code
  • Providing generic error handling with LOGIN_ERROR code for other failures
  • Maintaining consistent error structure with the new PasskeyError class

This aligns well with the error handling patterns mentioned in the AI summary for setup flow components.

src/components/Setup/Views/SetupPasskey.tsx (1)

53-76: LGTM! Good UI restructuring and button text improvement.

The nested div structure provides better layout control and spacing. Changing the button text from "Add a Passkey" to "Set it up" is more concise and user-friendly.

src/components/Setup/Setup.types.ts (4)

8-8: LGTM! Good addition of new screen type.

Adding the 'android-initial-pwa-install' screen type supports the new Android PWA installation flow.


13-13: LGTM! Layout type update aligns with new flow.

Removing 'welcome' and adding 'android-initial-pwa-install' to the LayoutType properly supports the updated setup flow structure.


27-27: LGTM! Consistent ScreenProps update.

Adding the corresponding ScreenProps entry maintains type consistency.


47-48: LGTM! Useful addition of styling class properties.

The optional titleClassName and contentClassName properties provide flexibility for customizing setup step styling.

src/app/(mobile-ui)/home/page.tsx (5)

8-8: LGTM! Clean import additions for new modal components.

The imports for IOSInstallPWAModal and AddMoneyPromptModal are properly added.

Also applies to: 26-26


43-44: LGTM! Appropriate state management for modals.

Clean state initialization for both modal visibility controls.


81-97: LGTM! Comprehensive iOS PWA install detection.

The detection logic is well-implemented:

  • Proper iOS device detection including iPad with MacIntel platform
  • Checks standalone mode to avoid showing in PWA
  • Uses session storage to prevent showing multiple times
  • Respects user preference hasPwaInstalled

This provides a good user experience without being intrusive.


99-115: LGTM! Smart add money prompt logic with proper prioritization.

The logic is well-designed:

  • Shows only when balance is zero
  • Respects session storage to avoid spam
  • Properly prioritizes iOS PWA modal over add money prompt
  • Works across all devices/display modes when appropriate

The comments clearly explain the conditions, making the code maintainable.


171-175: LGTM! Clean modal rendering with proper controls.

Both modals are properly integrated with their respective visibility state and close handlers.

src/components/Setup/Views/Welcome.tsx (4)

1-1: LGTM: Correct Next.js client directive.

The 'use client' directive is properly placed for a component using client-side hooks.


22-22: Good fix: Complete useEffect dependency array.

Adding push to the dependency array resolves the React Hook exhaustive-deps ESLint warning and ensures proper behavior if the router instance changes.


24-33: Excellent centralized error handling implementation.

The handleError function properly:

  • Provides user-friendly error messages for specific error codes
  • Includes fallback for unexpected errors
  • Integrates with Sentry for error tracking with contextual information

This is a significant improvement over inline error handling.


38-46: UI improvements with consistent styling.

The button updates improve the user experience:

  • Consistent shadowSize="4" and h-11 height across buttons
  • New variant="primary-soft" provides visual hierarchy
  • "Create your wallet" text is more descriptive than generic "Sign up"
src/components/Setup/Views/Signup.tsx (7)

1-2: Good component swap for improved error UX.

Replacing the generic Card import with the specialized ErrorAlert component will provide better error presentation with consistent styling across the app.


103-105: UI simplification improves maintainability.

Removing the Card wrapper and using fragment with styled divs creates a cleaner, more flexible layout structure.


108-108: Improved placeholder text for clarity.

"Enter a username" is more direct and actionable than "Choose your username".


115-122: Good button improvements.

The changes enhance UX:

  • Consistent width (w-4/12) and height (h-12)
  • Loading state tied to actual operation (isLoading instead of isChanging)
  • "Next" is more appropriate for a multi-step flow than "Create"

124-128: Enhanced error presentation.

Using ErrorAlert with customizable props (className, iconSize) provides consistent error styling and better visual hierarchy than plain paragraphs.


138-140: Improved link accessibility.

Separating "T&C" and "Privacy Policy" into individual underlined spans makes it clearer that both are clickable links, improving user understanding.


42-44:

❓ Verification inconclusive

Breaking change: Username validation regex excludes underscores.

The regex change from presumably allowing underscores to explicitly disallowing them (^[a-z][a-z0-9]{3,11}$) could affect existing users with underscore-containing usernames.

Please verify that this change is intentional and that existing users with underscores in their usernames are properly handled:


🏁 Script executed:

#!/bin/bash
# Search for any existing user validation or migration logic
rg -A 5 -B 5 "username.*underscore|underscore.*username" 
rg -A 5 -B 5 "^[a-z][a-z0-9_]" 

Length of output: 91951


Please confirm underscore handling in username validation

I see the signup form now uses username.match(/^[a-z][a-z0-9]{3,11}$/), which prohibits underscores. I did not find any migration, normalization, or backend‐aligned logic to handle existing usernames containing underscores. This may block current users whose usernames include _.

• File: src/components/Setup/Views/Signup.tsx (lines 42–44)
• Regex now disallows _, but no fallback or migration exists
• No other validation or normalization for _ in the codebase

Can you verify that:

  1. The backend validation rule also forbids underscores?
  2. Any existing underscore‐based usernames are migrated or otherwise handled?
  3. Documentation and UI error messages are updated to reflect this stricter rule?
src/components/Home/AddMoneyPromptModal/index.tsx (5)

8-11: Clean and appropriate interface design.

The AddMoneyPromptModalProps interface is well-defined with the essential props for modal control (visible for state, onClose for callback).


16-19: Proper navigation and cleanup logic.

The handleAddMoney function correctly:

  • Navigates to the add-money page
  • Closes the modal to prevent UI conflicts
  • Uses Next.js router push for client-side navigation

21-34: Well-structured CTA button configuration.

The button array follows the ActionModalButtonProps interface correctly with:

  • Clear action-oriented text ("Add money now" vs "I'll do it later")
  • Appropriate styling variants (primary vs transparent)
  • Proper event handlers for each action

36-45: User-friendly content structure.

The title and description provide clear context:

  • Direct title explains the action needed
  • Description explains why funding is necessary
  • Line breaks improve readability

48-61: Comprehensive ActionModal configuration.

The modal is properly configured with:

  • Custom icon styling to remove default container constraints
  • Appropriate text styling classes
  • Hidden close button to enforce CTA interaction
  • Content padding adjustments for better visual presentation
src/components/Setup/Setup.utils.ts (3)

4-12: Robust webview detection with PWA consideration.

The isLikelyWebview function correctly:

  • Handles undefined navigator (SSR scenarios)
  • Excludes standalone PWAs from webview classification
  • Uses case-insensitive regex matching against known signatures
  • Provides proper fallback behavior

This prevents false positives for legitimate PWA usage.


15-28: Comprehensive OS version validation.

The isDeviceOsSupported function properly:

  • Handles missing user agent gracefully
  • Parses Android versions correctly with flexible decimal handling
  • Supports both iPhone OS and iPad CPU OS patterns for iOS
  • Uses appropriate minimum version requirements (Android 9+, iOS 16+)
  • Defaults to supported for unknown OS types

The regex patterns cover the common user agent variations.


31-40: Thorough device type detection.

The getDeviceTypeForLogic function correctly:

  • Handles missing user agent with desktop fallback
  • Detects iPad with touch support (important for newer iPads reporting as Mac)
  • Uses case-insensitive Android detection
  • Provides clear return type options

The MacIntel check for iPad is essential since newer iPads can report as Mac in their user agent.

src/components/Setup/Views/InstallPWA.tsx (2)

16-96: Well-structured PWA installation handling.

Good implementation with:

  • Device-specific installation flows
  • Proper error handling and user feedback
  • Clean state management for installation progress
🧰 Tools
🪛 Biome (1.9.4)

[error] 46-46: 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)


179-182: ⚠️ Potential issue

Add missing break statement to prevent unintended fallthrough.

The android-initial-pwa-install case is missing a break statement, causing it to fall through to the pwa-install case.

case 'android-initial-pwa-install':
    return <AndroidPWASpecificInstallFlow />
+    break
case 'pwa-install':

Likely an incorrect or invalid review comment.

src/components/Setup/components/SetupWrapper.tsx (2)

38-42: Good addition of Android-specific layout type.

The new android-initial-pwa-install layout type is well-integrated with appropriate responsive styling.


21-25: Excellent addition of granular styling controls.

The new titleClassName, contentClassName, and refined imageClassName props provide good flexibility for component customization while maintaining backward compatibility.

Also applies to: 224-231

Copy link
Contributor

@kushagrasarathe kushagrasarathe left a comment

Choose a reason for hiding this comment

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

LFG

@jjramirezn jjramirezn merged commit 1820d35 into peanut-wallet Jun 6, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants