Skip to content

Conversation

kushagrasarathe
Copy link
Contributor

@kushagrasarathe kushagrasarathe commented May 20, 2025

  • contributes to TASK-11023
  • also contributes to TASK-11025
  • also contributes to TASK-10150

Copy link

vercel bot commented May 20, 2025

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

Name Status Preview Comments Updated (UTC)
peanut-ui ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 23, 2025 3:15pm

Copy link
Contributor

coderabbitai bot commented May 20, 2025

"""

Walkthrough

This update introduces a comprehensive add and withdraw money flow to the mobile UI, including country-specific and crypto deposit methods. It adds new components for handling multi-step add/withdraw flows, updates asset exports, generalizes card and search result components, and integrates new context providers for withdrawal state management. Several obsolete components are removed.

Changes

File(s) / Path(s) Change Summary
src/app/(mobile-ui)/add-money/[...country]/page.tsx, src/app/(mobile-ui)/add-money/crypto/page.tsx, src/app/(mobile-ui)/add-money/crypto/direct/page.tsx, src/app/(mobile-ui)/add-money/layout.tsx, src/app/(mobile-ui)/add-money/page.tsx, src/app/(mobile-ui)/withdraw/[...country]/page.tsx, src/app/(mobile-ui)/withdraw/crypto/page.tsx, src/app/(mobile-ui)/withdraw/layout.tsx, src/app/(mobile-ui)/withdraw/page.tsx Added new pages and layouts for add/withdraw money flows, including country and crypto-specific routes, with multi-step UI components.
src/app/(mobile-ui)/home/page.tsx Refactored "Add money" and "Withdraw" actions to use direct links and unified button components.
src/app/(mobile-ui)/pay/[...username]/page.tsx, src/app/[...recipient]/client.tsx, src/app/[...recipient]/page.tsx Refactored payment page flow to use a new flow prop, renamed components, and updated prop handling for add-money and direct-pay flows.
src/app/[...recipient]/payment-layout-wrapper.tsx, src/components/0_Bruddle/PageContainer.tsx Adjusted layout styling by removing or updating width/height-related CSS classes.
src/assets/exchanges/index.ts, src/assets/payment-apps/index.ts, src/assets/index.ts, src/assets/peanut/index.ts Added new asset export modules for exchanges and payment apps; removed wallets export; minor whitespace cleanup.
src/components/0_Bruddle/Button.tsx Extended ButtonProps with iconPosition, iconClassName, iconSize, and iconContainerClassName for icon placement and styling.
src/components/AddFunds/index.tsx, src/components/PeanutWalletActions/index.tsx Removed obsolete components related to the old add funds and wallet actions UI.
src/components/AddMoney/components/CryptoSourceListCard.tsx, src/components/AddMoney/components/DepositMethodList.tsx, src/components/AddMoney/consts/index.ts, src/components/AddMoney/views/CryptoDepositQR.view.tsx, src/components/AddMoney/views/NetworkSelection.view.tsx, src/components/AddMoney/views/TokenSelection.view.tsx Added new components, constants, and views for add-money crypto/country source selection, token/network selection, and QR code display.
src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx, src/components/AddWithdraw/components/AddWithdrawRouterView.tsx Added components for displaying country-specific add/withdraw methods and routing.
src/components/Global/ActionModal/index.tsx Refactored button prop handling, added ctaClassName, and updated modal/button styling and icon logic.
src/components/Global/AddressLink/index.tsx Added isLink prop to optionally render address as plain text instead of a link.
src/components/Global/Card/index.tsx Added getCardPosition utility for determining card position; removed overflow-hidden from base class.
src/components/Global/Icons/Icon.tsx, src/components/Global/Icons/alert.tsx, src/components/Global/Icons/check-circle.tsx, src/components/Global/Icons/exchange-arrows.tsx, src/components/Global/Icons/plus.tsx, src/components/Global/Icons/switch.tsx Added new SVG icon components and extended IconName type.
src/components/Global/PeanutActionDetailsCard/index.tsx Added support for "ADD_MONEY" and "WITHDRAW" transaction types and updated icon/title logic.
src/components/Global/TokenSelector/Components/NetworkListItem.tsx, src/components/Global/TokenSelector/TokenSelector.tsx Extended props for custom right content, title styling, disabled state; updated placeholder and icon logic.
src/components/Global/ValidatedInput/index.tsx Updated icon import, enforced white background, changed clear icon, and adjusted styling.
src/components/Home/HomeHistory.tsx Replaced manual card position logic with getCardPosition utility.
src/components/Payment/PaymentForm/index.tsx, src/components/Payment/Views/Confirm.payment.view.tsx, src/components/Payment/Views/Initial.payment.view.tsx, src/components/Payment/Views/Status.payment.view.tsx Extended payment form and views to support add-money and withdraw flows, including new props and conditional logic.
src/components/Payment/PaymentInfoRow.tsx Added z-40 class to info icon container for higher stacking context.
src/components/Request/direct-request/views/Initial.direct.request.view.tsx Added redirectTo prop to success view for custom redirect after completion.
src/components/SearchUsers/SearchInput.tsx, src/components/SearchUsers/SearchResultCard.tsx, src/components/SearchUsers/SearchResults.tsx Generalized search result card props, added placeholder prop, and refactored rendering for flexibility and decoupling from routing.
src/components/Withdraw/views/Confirm.withdraw.view.tsx, src/components/Withdraw/views/Initial.withdraw.view.tsx Added new components for initial and confirmation steps in the withdrawal flow.
src/context/WithdrawFlowContext.tsx, src/context/contextProvider.tsx Introduced withdrawal flow context and provider; integrated into global context hierarchy.
src/hooks/usePaymentInitiator.ts Extended hook and payloads to support add-money flow, requiring external wallet connection and updating transaction preparation logic.
src/styles/globals.css Changed tap highlight color for buttons/inputs from transparent to white.
src/components/Global/TokenAmountInput/index.tsx Added optional prop to hide currency toggle UI in token amount input component.

Possibly related PRs

Suggested reviewers

  • jjramirezn
    """
✨ 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: 13

🔭 Outside diff range comments (1)
src/app/(mobile-ui)/add-money/[...country]/page.tsx (1)

1-6: 🛠️ Refactor suggestion

Page stub needs to handle dynamic country param.
This catch-all route should use useParams from next/navigation to retrieve the country and render the appropriate UI. For instance:

+ import { useParams } from 'next/navigation'
  const AddMoneyCountryPage = () => {
+    const { country } = useParams()
    return <div>AddMoneyCountryPage: {country}</div>
  }
🧹 Nitpick comments (25)
src/assets/exchanges/index.ts (1)

1-3: Add module-level comment for context.
Per the cursor rules, include a brief lowercase comment summarizing the file’s purpose:

// exports SVG logos for supported exchanges
src/components/Global/Icons/exchange-arrows.tsx (2)

4-9: Allow dynamic icon coloring.
Replace the hardcoded fill="black" with fill="currentColor" so that the icon inherits CSS color and respects the passed fill prop.
Apply this diff:

-            <path
-                d="M2.66 4.33325L0 6.99992L2.66 9.66658V7.66658H7.33333V6.33325H2.66V4.33325ZM12 2.99992L9.34 0.333252V2.33325H4.66667V3.66658H9.34V5.66658L12 2.99992Z"
-                fill="black"
-            />
+            <path
+                d="M2.66 4.33325L0 6.99992L2.66 9.66658V7.66658H7.33333V6.33325H2.66V4.33325ZM12 2.99992L9.34 0.333252V2.33325H4.66667V3.66658H9.34V5.66658L12 2.99992Z"
+                fill="currentColor"
+            />

1-2: Consider adding a brief comment above the component.
Per cursor rules, include a simple lowercase comment explaining the icon’s purpose, e.g.:

// arrows indicating fund exchange flow
src/app/(mobile-ui)/add-money/page.tsx (1)

1-5: Add a simple lowercase comment at the top.
Per cursor rules, include a brief description above the component, e.g.:

// entry page for the add money flow
src/app/(mobile-ui)/withdraw/page.tsx (1)

1-7: This is a placeholder component that needs implementation.

This component is currently just a minimal placeholder with a heading. As this PR is marked WIP, consider enhancing this component with actual withdraw functionality in subsequent iterations.

A more complete implementation might include:

 export default function WithdrawPage() {
     return (
-        <div>
+        <div className="h-full w-full space-y-6 p-5">
             <h1>Withdraw</h1>
+            <form className="space-y-4">
+                <div>
+                    <label htmlFor="amount" className="block mb-2 text-sm font-medium">Amount</label>
+                    <input type="number" id="amount" className="w-full p-3 border rounded-lg" placeholder="0.00" />
+                </div>
+                <button type="submit" className="w-full p-3 bg-blue-600 text-white rounded-lg">Withdraw Funds</button>
+            </form>
         </div>
     )
 }
src/components/SearchUsers/SearchResults.tsx (2)

52-56: Search result card props refactored appropriately.

The component has been updated to use the new SearchResultCard interface.

Consider using optional chaining for a cleaner syntax:

-onClick={() => onUserSelect && onUserSelect(user.username)}
+onClick={() => onUserSelect?.(user.username)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 56-56: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


91-97: Recent transactions card props updated consistently.

The refactoring has been consistently applied to the recent transactions list as well.

Consider using optional chaining for a cleaner syntax:

-onClick={() => onUserSelect && onUserSelect(user.username)}
+onClick={() => onUserSelect?.(user.username)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 96-96: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/components/AddMoney/views/TokenSelection.view.tsx (2)

22-33: Consider extracting position calculation logic.

The position calculation logic could be extracted into a separate utility function, especially if this pattern is used in multiple components.

-                        const isFirst = index === 0
-                        const isLast = index === DEPOSIT_CRYPTO_TOKENS.length - 1
-                        let position: CardPosition = 'middle'
-                        if (DEPOSIT_CRYPTO_TOKENS.length === 1) {
-                            position = 'single'
-                        } else if (isFirst) {
-                            position = 'first'
-                        } else if (isLast) {
-                            position = 'last'
-                        }
+                        const position = getCardPosition(index, DEPOSIT_CRYPTO_TOKENS.length)

You could create a utility function like:

function getCardPosition(index: number, totalItems: number): CardPosition {
    if (totalItems === 1) return 'single';
    if (index === 0) return 'first';
    if (index === totalItems - 1) return 'last';
    return 'middle';
}

34-34: Consider adding a comment explaining the token availability logic.

It's not immediately clear why only tokens matching PEANUT_WALLET_TOKEN_SYMBOL are enabled. A brief comment would help clarify this business rule.

-                        const isDisabled = token.symbol.toLowerCase() !== PEANUT_WALLET_TOKEN_SYMBOL.toLowerCase()
+                        // Only enable the default wallet token (USDT), others are coming soon
+                        const isDisabled = token.symbol.toLowerCase() !== PEANUT_WALLET_TOKEN_SYMBOL.toLowerCase()
src/components/AddMoney/views/AddMoneyRouter.view.tsx (2)

16-38: Consider memoizing the filtered list separately from sorting.

The current implementation filters and sorts the list in a single useMemo. Consider separating these operations to avoid unnecessary sorting when only filtering changes.

-    const filteredAllMethods = useMemo(() => {
+    const filteredMethods = useMemo(() => {
        let methodsToShow
        if (!searchTerm) {
            methodsToShow = [...ALL_DEPOSIT_METHODS]
        } else {
            methodsToShow = ALL_DEPOSIT_METHODS.filter(
                (method) =>
                    method.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
                    method.currency?.toLowerCase().includes(searchTerm.toLowerCase()) ||
                    method.description?.toLowerCase().includes(searchTerm.toLowerCase())
            )
        }
+        return methodsToShow;
+    }, [searchTerm]);
 
+    const sortedFilteredMethods = useMemo(() => {
+        return [...filteredMethods].sort((a, b) => {
            if (a.type === 'crypto' && b.type !== 'crypto') {
                return -1
            }
            if (b.type === 'crypto' && a.type !== 'crypto') {
                return 1
            }
            return a.title.toLowerCase().localeCompare(b.title.toLowerCase())
        })
-    }, [searchTerm])
+    }, [filteredMethods])

84-94: Add aria labels for better accessibility.

The empty state and results list should have appropriate ARIA attributes for better screen reader support.

    {searchTerm && filteredAllMethods.length === 0 ? (
        <EmptyState
            title="No results found"
            description="Try searching with a different term."
            icon="search"
+           aria-live="polite"
        />
    ) : (
-        <div className="flex-1 overflow-y-auto">
+        <div className="flex-1 overflow-y-auto" role="list" aria-label="Deposit methods">
            <DepositMethodList methods={filteredAllMethods} />
        </div>
    )}
src/components/AddMoney/components/CryptoSourceListCard.tsx (2)

12-18: Consider extracting the Icon component to a separate file.

The Icon component could be reused in other parts of the application. Consider moving it to a separate file if it's likely to be used elsewhere.


20-57: Consider adding support for loading and error states.

The component doesn't handle loading or error states. Consider adding props and rendering logic for these scenarios.

interface CryptoSourceListCardProps {
    sources: CryptoSource[]
    onItemClick: (source: CryptoSource) => void
+   isLoading?: boolean
+   error?: string
}

export const CryptoSourceListCard = ({ 
    sources, 
    onItemClick,
+   isLoading = false,
+   error
}: CryptoSourceListCardProps) => {
    return (
        <div className="flex flex-col">
+           {isLoading && (
+               <div className="flex justify-center p-4">
+                   <span>Loading...</span>
+               </div>
+           )}
+           {error && (
+               <div className="flex justify-center p-4 text-red-500">
+                   {error}
+               </div>
+           )}
+           {!isLoading && !error && sources.length === 0 && (
+               <div className="flex justify-center p-4">
+                   <span>No sources available</span>
+               </div>
+           )}
            {sources.map((source, index) => (
                // Existing code...
            ))}
        </div>
    )
}
src/components/AddMoney/views/CryptoDepositQR.view.tsx (2)

41-43: Consider specifying QR code dimensions for better readability

The QR code wrapper doesn't have explicit dimensions, which might lead to inconsistent sizing across different screen sizes, affecting readability.

<div className="flex items-center justify-center">
-   <QRCodeWrapper url={depositAddress} />
+   <QRCodeWrapper url={depositAddress} size={200} />
</div>

49-58: Add error handling for clipboard operations

The current implementation doesn't handle potential clipboard API failures. Consider showing an error message if the copy operation fails.

<Button
    variant="purple"
    onClick={handleCopyAddress}
    className="w-full"
    icon={copied ? 'check' : 'copy'}
    shadowSize="4"
>
    {copied ? 'Copied!' : 'Copy'}
</Button>

You could modify the handleCopyAddress function to capture errors:

const handleCopyAddress = useCallback(async () => {
    try {
        await copyTextToClipboardWithFallback(depositAddress)
        setCopied(true)
        setTimeout(() => setCopied(false), 2000)
    } catch (error) {
        // Handle error - perhaps with a toast notification
        console.error('Failed to copy address:', error)
    }
}, [depositAddress])
src/components/AddMoney/views/NetworkSelection.view.tsx (2)

15-15: Simplify interface definition

The SelectedNetwork interface extends NetworkConfig without adding any properties, which doesn't provide additional value.

-export interface SelectedNetwork extends NetworkConfig {}
+export type SelectedNetwork = NetworkConfig;

45-54: Simplify card position calculation logic

The position calculation logic can be simplified for better readability.

-const isFirst = index === 0
-const isLast = index === allNetworks.length - 1
-let position: CardPosition = 'middle'
-if (allNetworks.length === 1) {
-    position = 'single'
-} else if (isFirst) {
-    position = 'first'
-} else if (isLast) {
-    position = 'last'
-}
+let position: CardPosition = 'middle'
+if (allNetworks.length === 1) {
+    position = 'single'
+} else if (index === 0) {
+    position = 'first'
+} else if (index === allNetworks.length - 1) {
+    position = 'last'
+}
src/components/SearchUsers/SearchResultCard.tsx (2)

28-30: Simplify the click handler logic

The handleCardClick function just calls onClick directly, which doesn't add any value and could be removed.

-const handleCardClick = () => {
-    onClick()
-}

<Card
-    onClick={isDisabled ? undefined : handleCardClick}
+    onClick={isDisabled ? undefined : onClick}
    position={position}
    className={twMerge('cursor-pointer hover:bg-gray-50', isDisabled ? 'bg-grey-4' : '', className)}
>

33-36: Enhance disabled state styling for better accessibility

The current disabled state only changes the background color, which might not be sufficient for accessibility. Consider adding more visual cues and the proper ARIA attributes.

<Card
    onClick={isDisabled ? undefined : handleCardClick}
    position={position}
-   className={twMerge('cursor-pointer hover:bg-gray-50', isDisabled ? 'bg-grey-4' : '', className)}
+   className={twMerge(
+       'cursor-pointer hover:bg-gray-50', 
+       isDisabled ? 'bg-grey-4 cursor-not-allowed opacity-70' : '', 
+       className
+   )}
+   aria-disabled={isDisabled}
>
src/components/AddMoney/components/DepositMethodList.tsx (4)

35-50: Consider extracting the icon logic into a separate function.

The conditional logic for determining the left icon is complex and nested. Extracting this into a dedicated function would improve readability and maintainability.

export const DepositMethodList = ({ methods }: DepositMethodListProps) => {
    const router = useRouter()

    const handleMethodClick = (path: string) => {
        router.push(path)
    }

+   const renderMethodIcon = (method: DepositMethod) => {
+       if (method.type === 'crypto') {
+           return <AvatarWithBadge icon="wallet-outline" size="extra-small" className="bg-yellow-5" />
+       } else if (method.type === 'country') {
+           return (
+               <Image
+                   src={`https://flagcdn.com/w320/${method.id.toLowerCase()}.png`}
+                   alt={`${method.title} flag`}
+                   width={32}
+                   height={32}
+                   className="min-h-8 min-w-8 rounded-full object-fill object-center shadow-sm"
+                   loading="lazy"
+                   onError={(e) => {
+                       // Fallback to text avatar if image fails to load
+                       e.currentTarget.style.display = 'none'
+                   }}
+               />
+           )
+       } else {
+           return <AvatarWithBadge name={method.title} size="extra-small" className="bg-yellow-5" />
+       }
+   }

    return (
        <div className="flex flex-col">
            {methods.map((method, index) => (
                <SearchResultCard
                    key={method.id}
                    title={method.title}
                    description={method.description || method.currency}
-                   leftIcon={
-                       method.type === 'crypto' ? (
-                           <AvatarWithBadge icon="wallet-outline" size="extra-small" className="bg-yellow-5" />
-                       ) : method.type === 'country' ? (
-                           <Image
-                               src={`https://flagcdn.com/w320/${method.id.toLowerCase()}.png`}
-                               alt={`${method.title} flag`}
-                               width={32}
-                               height={32}
-                               className="min-h-8 min-w-8 rounded-full object-fill object-center shadow-sm"
-                               loading="lazy"
-                           />
-                       ) : (
-                           <AvatarWithBadge name={method.title} size="extra-small" className="bg-yellow-5" />
-                       )
-                   }
+                   leftIcon={renderMethodIcon(method)}
                    // ...rest of the component

39-46: Add error handling for country flag images.

The Image component for country flags lacks error handling if a flag image fails to load. Consider adding an onError handler to display a fallback.

<Image
    src={`https://flagcdn.com/w320/${method.id.toLowerCase()}.png`}
    alt={`${method.title} flag`}
    width={32}
    height={32}
    className="min-h-8 min-w-8 rounded-full object-fill object-center shadow-sm"
    loading="lazy"
+   onError={(e) => {
+       // Fallback to text avatar if image fails to load
+       e.currentTarget.style.display = 'none'
+       // Create a fallback element
+       const fallback = document.createElement('div');
+       fallback.className = "flex items-center justify-center size-8 bg-yellow-5 rounded-full";
+       fallback.textContent = method.title.charAt(0).toUpperCase();
+       e.currentTarget.parentNode?.appendChild(fallback);
+   }}
/>

52-60: Simplify the position calculation logic.

The position calculation can be simplified with a more concise approach.

-position={
-    methods.length === 1
-        ? 'single'
-        : index === 0
-          ? 'first'
-          : index === methods.length - 1
-            ? 'last'
-            : 'middle'
-}
+position={
+    methods.length === 1 ? 'single' : 
+    index === 0 ? 'first' : 
+    index === methods.length - 1 ? 'last' : 'middle'
+}

28-64: Consider handling empty methods array explicitly.

The component doesn't provide explicit handling for an empty methods array. Consider adding a fallback UI or message when no methods are available.

return (
    <div className="flex flex-col">
+       {methods.length === 0 && (
+           <div className="p-4 text-center text-grey-1">
+               No deposit methods available
+           </div>
+       )}
        {methods.map((method, index) => (
            // Existing code
        ))}
    </div>
)
src/components/AddMoney/consts/index.ts (2)

23-61: Consider moving temporary code to a separate file.

The comment about DEPOSIT_CRYPTO_TOKENS being temporary is informative. Consider moving temporary code to a dedicated file to make it easier to replace later.

-// @dev: this is a temporary list of tokens for the deposit screen, using this for a couple of weeks, once x-chain is ready, we will use the x-chain tokens and remove this list, only useful token is USDC here for now
+// @dev: this is a temporary list of tokens for the deposit screen.
+// TODO: Replace with x-chain tokens once ready

118-1876: Consider moving the large country list to a separate file.

The ALL_DEPOSIT_METHODS array is extremely large and dominates this file. Consider moving it to a dedicated file for better maintainability and organization.

// In a new file: src/components/AddMoney/consts/countries.ts
+import { DepositMethod } from '../components/DepositMethodList'
+
+export const COUNTRY_DEPOSIT_METHODS: DepositMethod[] = [
+    {
+        id: 'AD',
+        type: 'country',
+        title: 'Andorra',
+        currency: 'EUR',
+        path: '/add-money/andorra',
+    },
+    // ... rest of the countries
+]

// In the original file
+import { COUNTRY_DEPOSIT_METHODS } from './countries'
+
-export const ALL_DEPOSIT_METHODS: DepositMethod[] = [
+export const ALL_DEPOSIT_METHODS: DepositMethod[] = [
+    {
+        id: 'crypto',
+        type: 'crypto',
+        title: 'Crypto Deposit',
+        description: 'Use an exchange or your wallet',
+        path: '/add-money/crypto',
+    },
+    ...COUNTRY_DEPOSIT_METHODS
+]
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f8cc691 and eb770b5.

⛔ Files ignored due to path filters (3)
  • src/assets/exchanges/binance.svg is excluded by !**/*.svg
  • src/assets/exchanges/lemon.svg is excluded by !**/*.svg
  • src/assets/exchanges/ripio.svg is excluded by !**/*.svg
📒 Files selected for processing (26)
  • .cursorrules (1 hunks)
  • src/app/(mobile-ui)/add-money/[...country]/page.tsx (1 hunks)
  • src/app/(mobile-ui)/add-money/crypto/page.tsx (1 hunks)
  • src/app/(mobile-ui)/add-money/layout.tsx (1 hunks)
  • src/app/(mobile-ui)/add-money/page.tsx (1 hunks)
  • src/app/(mobile-ui)/home/page.tsx (1 hunks)
  • src/app/(mobile-ui)/withdraw/page.tsx (1 hunks)
  • src/assets/exchanges/index.ts (1 hunks)
  • src/components/AddFunds/index.tsx (0 hunks)
  • src/components/AddMoney/components/CryptoSourceListCard.tsx (1 hunks)
  • src/components/AddMoney/components/DepositMethodList.tsx (1 hunks)
  • src/components/AddMoney/consts/index.ts (1 hunks)
  • src/components/AddMoney/views/AddMoneyRouter.view.tsx (1 hunks)
  • src/components/AddMoney/views/CryptoDepositQR.view.tsx (1 hunks)
  • src/components/AddMoney/views/NetworkSelection.view.tsx (1 hunks)
  • src/components/AddMoney/views/TokenSelection.view.tsx (1 hunks)
  • src/components/Global/ActionModal/index.tsx (3 hunks)
  • src/components/Global/Icons/Icon.tsx (6 hunks)
  • src/components/Global/Icons/alert.tsx (1 hunks)
  • src/components/Global/Icons/exchange-arrows.tsx (1 hunks)
  • src/components/Global/Icons/plus.tsx (1 hunks)
  • src/components/Global/TokenSelector/Components/NetworkListItem.tsx (3 hunks)
  • src/components/PeanutWalletActions/index.tsx (0 hunks)
  • src/components/SearchUsers/SearchInput.tsx (2 hunks)
  • src/components/SearchUsers/SearchResultCard.tsx (1 hunks)
  • src/components/SearchUsers/SearchResults.tsx (3 hunks)
💤 Files with no reviewable changes (2)
  • src/components/PeanutWalletActions/index.tsx
  • src/components/AddFunds/index.tsx
🧰 Additional context used
🧬 Code Graph Analysis (7)
src/app/(mobile-ui)/add-money/page.tsx (1)
src/components/AddMoney/views/AddMoneyRouter.view.tsx (1)
  • AddMoneyRouterView (11-98)
src/components/Global/Icons/Icon.tsx (3)
src/components/Global/Icons/plus.tsx (1)
  • PlusIcon (3-10)
src/components/Global/Icons/exchange-arrows.tsx (1)
  • ExchangeArrowsIcon (3-10)
src/components/Global/Icons/alert.tsx (1)
  • AlertIcon (3-10)
src/components/Global/ActionModal/index.tsx (1)
src/components/0_Bruddle/Button.tsx (1)
  • ButtonProps (21-29)
src/components/AddMoney/views/CryptoDepositQR.view.tsx (2)
src/utils/general.utils.ts (1)
  • copyTextToClipboardWithFallback (384-410)
src/components/0_Bruddle/Button.tsx (1)
  • Button (65-97)
src/components/AddMoney/components/CryptoSourceListCard.tsx (2)
src/components/AddMoney/consts/index.ts (1)
  • CryptoSource (7-14)
src/components/SearchUsers/SearchResultCard.tsx (1)
  • SearchResultCard (18-62)
src/components/AddMoney/components/DepositMethodList.tsx (1)
src/components/SearchUsers/SearchResultCard.tsx (1)
  • SearchResultCard (18-62)
src/components/AddMoney/consts/index.ts (1)
src/components/AddMoney/components/DepositMethodList.tsx (1)
  • DepositMethod (7-15)
🪛 Biome (1.9.4)
src/components/SearchUsers/SearchResults.tsx

[error] 56-56: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 96-96: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

5-12: Good enhancement to make the component more reusable!

Adding the optional placeholder prop to the SearchInputProps interface is a good improvement that enhances the component's flexibility and reusability across different contexts.


14-21: Clean implementation with backwards compatibility.

The prop destructuring with default value ensures backward compatibility while allowing customization where needed. This is a good practice.


32-32: Properly utilizes the new placeholder prop.

The placeholder prop is correctly applied to the BaseInput component, replacing the previously hardcoded value.

Since this PR is related to "add/withdraw funds" functionality, consider whether the default value "Name or username" remains appropriate if this component will be used in financial contexts. If you plan to reuse this component for searching transactions or payment methods, you might want a more generic default or context-specific placeholders.

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

1-3: Centralized export of exchange logos.
Named exports align with usage in UI components and improve maintainability.

src/components/Global/Icons/exchange-arrows.tsx (1)

3-10: Icon component implementation is correct.
The SVG structure and typing align with other icon components, and spreading props allows flexibility.

.cursorrules (1)

8-8: Update adds clear comment guideline.
This new rule ensures any added or updated code includes simple, lowercase comments, improving clarity.

src/app/(mobile-ui)/add-money/page.tsx (1)

3-5: Component properly delegates to the add money router view.
Exporting <AddMoneyRouterView /> as the default aligns with Next.js conventions for page routing.

src/components/Global/Icons/alert.tsx (1)

1-10: Well-implemented SVG icon component.

The AlertIcon component is correctly implemented, following React best practices for SVG icons with proper TypeScript typing.

src/components/Global/Icons/plus.tsx (1)

1-10: Well-implemented SVG icon component.

The PlusIcon component is correctly implemented, following React best practices for SVG icons with proper TypeScript typing.

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

1-6: Clean and focused layout component.

This layout component provides consistent styling for the "Add Money" feature in the mobile UI. The implementation is straightforward and follows React best practices.

src/components/Global/Icons/Icon.tsx (3)

3-3: Icons are properly imported.

The new icons have been correctly imported at the top of the file.

Also applies to: 20-20, 33-33


48-48: Icon names correctly added to the type definition.

The new icon names have been properly added to the IconName type definition, which ensures type safety when using these icons.

Also applies to: 89-90


138-140: Icon components correctly mapped.

The new icons have been properly mapped to their respective components in the iconComponents object.

src/components/SearchUsers/SearchResults.tsx (1)

7-7: New avatar component imported.

The AvatarWithBadge component is imported to replace the previous avatar implementation.

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

1-1: Button props interface simplified.

The ActionModalButtonProps now extends ButtonProps directly, which reduces code duplication and makes the interface more maintainable. Good refactoring.

Also applies to: 8-11


99-99: Modal background styling updated.

The modal panel background has been changed to a solid white background. This ensures consistent appearance across the application.


128-131: Checkbox container and label alignment improved.

The spacing and alignment of the checkbox container and label have been adjusted for better visual appearance.

src/components/Global/TokenSelector/Components/NetworkListItem.tsx (4)

18-19: Props extension enhances component flexibility.

Adding rightContent and titleClassName props improves the component's reusability by allowing customization of both the title styling and right side content.


64-64: Simplified image styling logic.

Removing the conditional styling for the image's rounded-full class makes the code more consistent and easier to maintain.


72-74: Enhanced title styling flexibility.

Using twMerge to combine default styling with custom classes passed via titleClassName is a good practice, allowing for styling customization while maintaining baseline styles.


77-83: Improved right content rendering logic.

The conditional rendering now properly handles three cases: showing a "soon" badge for upcoming networks, displaying custom right content when provided, or falling back to the default chevron icon.

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

10-13: Well-defined props interface.

The props interface clearly defines the component's contract with its parent, making it easier to understand how to use this component.

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

56-72: 🛠️ Refactor suggestion

Add null/undefined checks for network data

The code accesses properties from squidChainDetails without checking if it exists first, which could lead to runtime errors if a network ID isn't found in the context data.

const squidChainDetails = supportedSquidChainsAndTokens[network.chainId]
+const networkName = squidChainDetails?.axelarChainName ?? network.name
+const networkIcon = squidChainDetails?.chainIconURI ?? network.iconUrl
+const networkId = squidChainDetails?.chainId ?? network.chainId

return (
    <NetworkListItem
        key={index}
-       chainId={squidChainDetails?.chainId ?? network.chainId}
-       name={squidChainDetails?.axelarChainName ?? network.name}
-       iconUrl={squidChainDetails?.chainIconURI ?? network.iconUrl}
+       chainId={networkId}
+       name={networkName}
+       iconUrl={networkIcon}
        isComingSoon={isComingSoon}
        onClick={() =>
            onNetworkSelect({
-               chainId: squidChainDetails?.chainId ?? network.chainId,
-               name: squidChainDetails?.axelarChainName ?? network.name,
-               iconUrl: squidChainDetails?.chainIconURI ?? network.iconUrl,
+               chainId: networkId,
+               name: networkName,
+               iconUrl: networkIcon,
            })
        }

Likely an incorrect or invalid review comment.

src/app/(mobile-ui)/add-money/crypto/page.tsx (1)

70-76: Inconsistent back navigation behavior from QR screen

The function handleBackToNetworkSelectionFromQR has inconsistent behavior: for exchanges, it goes back to source selection, but for other sources, it goes back to network selection. This might be confusing for users.

Consider making the back navigation more consistent, or providing a clearer explanation for this differentiated behavior:

const handleBackToNetworkSelectionFromQR = () => {
-    if (selectedSource?.type === 'exchange') {
-        setCurrentStep('sourceSelection')
-    } else {
-        setCurrentStep('networkSelection')
-    }
+    // Always go back to the previous step
+    setCurrentStep('riskModal')
+    
+    // Alternative: Add a comment explaining the different behavior
+    // For exchanges, we go back to the beginning because [reason]
+    // if (selectedSource?.type === 'exchange') {
+    //    setCurrentStep('sourceSelection')
+    // } else {
+    //    setCurrentStep('networkSelection')
+    // }
}
src/components/SearchUsers/SearchResultCard.tsx (1)

46-58: Clarify the purpose of the Button in the right content

The Button inside the right side doesn't have a clear purpose or behavior; it's styled like a button but doesn't have its own click handler. Consider either making it functional or using a simpler visual element if it's just for decoration.

{rightContent ? (
    rightContent
) : (
    <Button
        shadowSize="4"
        size="small"
        className="h-6 w-6 rounded-full p-0 shadow-[0.12rem_0.12rem_0_#000000]"
+       onClick={(e) => {
+           e.stopPropagation(); // Prevent triggering the card's onClick
+           onClick(); // Trigger the same action as clicking the card
+       }}
    >
        <div className="flex size-7 items-center justify-center">
            <Icon name="chevron-up" className="h-9 rotate-90" />
        </div>
    </Button>
)}

Alternatively, if this is purely decorative:

{rightContent ? (
    rightContent
) : (
-   <Button
-       shadowSize="4"
-       size="small"
-       className="h-6 w-6 rounded-full p-0 shadow-[0.12rem_0.12rem_0_#000000]"
-   >
-       <div className="flex size-7 items-center justify-center">
-           <Icon name="chevron-up" className="h-9 rotate-90" />
-       </div>
-   </Button>
+   <div className="flex size-7 items-center justify-center">
+       <Icon name="chevron-up" className="h-9 rotate-90" />
+   </div>
)}
src/components/AddMoney/components/DepositMethodList.tsx (2)

1-6: LGTM - Proper imports and client directive.

The imports are appropriate for the component needs and the 'use client' directive is correctly placed at the top of the file.


7-15: Well-structured interface definition.

The DepositMethod interface is well-defined with clear property types and proper export for reuse. The optional properties are correctly marked with ?.

src/components/AddMoney/consts/index.ts (3)

7-21: Well-structured interface definitions.

The interfaces for CryptoSource and CryptoToken are well-defined with appropriate property types and optional flags.


63-116: Good organization of crypto sources.

The separation into exchanges and wallets is well-structured and the inclusion of generic "other" options is a good practice.


187-188: Missing currency for Antarctica.

Antarctica doesn't have its own currency, but the empty string could cause display issues. Consider using a placeholder or the currency of the relevant administrative territory.

{
    id: 'AQ',
    type: 'country',
    title: 'Antarctica',
-   currency: '',
+   currency: 'USD',  // Or another appropriate fallback
    path: '/add-money/antarctica',
},

setSearchTerm('')
}

// todo: save recent methods in local storage
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Implement the TODO item for persisting recent methods.

The TODO comment about saving recent methods in local storage should be addressed for a complete implementation.


🏁 Script executed:

#!/bin/bash
# Check if there are other TODOs related to local storage in the codebase
rg -i "todo.*local storage" --glob "*.{ts,tsx,js,jsx}"

Length of output: 160


Implement persistence for recent payment methods
The // todo: save recent methods in local storage comment in
src/components/AddMoney/views/AddMoneyRouter.view.tsx (line 48) remains unaddressed. Please implement full support for persisting and retrieving the user’s recent methods:

• On component mount, read any stored methods from localStorage (or a wrapper) and initialize state.
• On adding/selecting a method, update both state and localStorage.
• Handle JSON serialization, missing or malformed data, and storage errors gracefully.
• Add unit tests (or integration tests) to verify load/save behavior.

🤖 Prompt for AI Agents
In src/components/AddMoney/views/AddMoneyRouter.view.tsx at line 48, implement
the TODO for saving recent methods in local storage by adding logic to load
stored methods from localStorage when the component mounts and initialize the
state accordingly. Update the state and localStorage whenever a method is added
or selected, ensuring JSON serialization and deserialization are handled safely
with error checks for missing or malformed data. Also, add unit or integration
tests to verify that loading and saving recent methods to localStorage works
correctly.

Comment on lines 111 to 112
<CryptoSourceListCard sources={CRYPTO_WALLETS} onItemClick={() => {}} />
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Empty click handler on crypto wallets

The click handler for wallet items is an empty function, which means clicking on wallets does nothing. If these options are "coming soon" and not functional yet, consider disabling them or showing a message to improve user experience.

<div className="mt-1 flex flex-col gap-2">
-    <CryptoSourceListCard sources={CRYPTO_WALLETS} onItemClick={() => {}} />
+    <CryptoSourceListCard 
+        sources={CRYPTO_WALLETS.map(wallet => ({ ...wallet, disabled: true }))} 
+        onItemClick={(source) => {
+            // Show a "coming soon" toast or modal
+            console.log('Wallet deposits coming soon:', source.name);
+        }} 
+    />
</div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<CryptoSourceListCard sources={CRYPTO_WALLETS} onItemClick={() => {}} />
</div>
<div className="mt-1 flex flex-col gap-2">
<CryptoSourceListCard
sources={CRYPTO_WALLETS.map(wallet => ({ ...wallet, disabled: true }))}
onItemClick={(source) => {
// Show a "coming soon" toast or modal
console.log('Wallet deposits coming soon:', source.name);
}}
/>
</div>
🤖 Prompt for AI Agents
In src/app/(mobile-ui)/add-money/crypto/page.tsx around lines 111 to 112, the
onItemClick handler for CryptoSourceListCard is an empty function, resulting in
no action when wallet items are clicked. Update this by either disabling the
clickable wallet items or implementing a handler that shows a "coming soon"
message or notification to inform users that the feature is not yet available.

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

🔭 Outside diff range comments (2)
src/components/Payment/Views/Status.payment.view.tsx (1)

145-153: 🛠️ Refactor suggestion

Use the supplied redirectTo prop for the “Done” button as well
handleDone always pushes /home, ignoring the caller-provided navigation target.
This breaks the new add-money flow which expects to land on /add-money.

-    const handleDone = () => {
-        if (!!authUser?.user.userId) {
-            // reset payment state when done
-            router.push('/home')
+    const handleDone = () => {
+        if (!!authUser?.user.userId) {
+            // reset payment state when done
+            router.push(redirectTo || '/home')
🧰 Tools
🪛 Biome (1.9.4)

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

src/components/Payment/PaymentForm/index.tsx (1)

175-191: ⚠️ Potential issue

Recipient check blocks Add-Money flow

canInitiatePayment unconditionally requires a recipient even when isAddMoneyFlow is true, but the Add-Money journey has no external recipient.
As a result the “Review / Connect Wallet” button may stay disabled, and handleInitiatePayment might later pass an undefined recipient down-stream, causing runtime errors in the initiator hook / backend.

-        const recipientExists = !!recipient
+        // No recipient is needed when the user is adding money to their own wallet
+        const recipientExists =
+            isAddMoneyFlow ? true : !!recipient
🧹 Nitpick comments (11)
src/components/0_Bruddle/Button.tsx (1)

29-30: Consider adding documentation for the new props

These new props enhance the flexibility of the Button component, but they lack documentation comments that explain their purpose and usage. Adding JSDoc comments would help other developers understand how to use these features properly.

 export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
     variant?: ButtonVariant
     size?: ButtonSize
     shape?: ButtonShape
     shadowSize?: ShadowSize
     shadowType?: ShadowType
     loading?: boolean
     icon?: IconName
+    /** Position of the icon relative to the button text ('left' or 'right') */
     iconPosition?: 'left' | 'right'
+    /** Additional classes to apply to the icon for custom styling */
     iconClassName?: string
 }
src/components/Payment/Views/Initial.payment.view.tsx (1)

6-13: Improved JSX formatting and explicit prop passing.

The multi-line JSX formatting improves readability. Explicitly passing isAddMoneyFlow and isWithdrawFlow makes the prop forwarding more obvious, even though these props are already included in {...props}.

While functionally correct, there's some redundancy in explicitly setting props that are already included in the props spread. Consider either:

  1. Removing the explicit props if they're purely for clarity:
<PaymentForm
  {...props}
  isPintaReq={isPintaReq}
- isAddMoneyFlow={props.isAddMoneyFlow}
- isWithdrawFlow={props.isWithdrawFlow}
/>
  1. Or using object destructuring for cleaner code:
-export default function InitialPaymentView(props: PaymentFormProps) {
-  const isPintaReq = props.token?.symbol === 'PNT' || props.isPintaReq
+export default function InitialPaymentView({
+  token, isPintaReq: propIsPintaReq, isAddMoneyFlow, isWithdrawFlow, ...otherProps
+}: PaymentFormProps) {
+  const isPintaReq = token?.symbol === 'PNT' || propIsPintaReq

  return (
    <PaymentForm
-     {...props}
+     {...otherProps}
+     token={token}
      isPintaReq={isPintaReq}
      isAddMoneyFlow={isAddMoneyFlow}
      isWithdrawFlow={isWithdrawFlow}
    />
  )
}
src/components/Global/PeanutActionDetailsCard/index.tsx (2)

70-75: Complex conditional rendering for avatar icon.

The nested ternary operators make the logic harder to read and maintain.

Consider extracting this logic to a separate helper function for better readability:

+const getAvatarIcon = () => {
+  if (viewType === 'SUCCESS') return 'check'
+  if (recipientType !== 'USERNAME' || transactionType === 'ADD_MONEY') return 'wallet-outline'
+  return undefined
+}

<AvatarWithBadge
-  icon={
-    viewType === 'SUCCESS'
-      ? 'check'
-      : recipientType !== 'USERNAME' || transactionType === 'ADD_MONEY'
-        ? 'wallet-outline'
-        : undefined
-  }
+  icon={getAvatarIcon()}
  size={avatarSize}
  // ... other props
/>

79-85: Complex conditional for avatar background color.

Similar to the icon logic, the nested ternary makes the code harder to read.

Extract this logic to a helper function:

+const getAvatarBackgroundColor = () => {
+  if (viewType === 'SUCCESS') return '#29CC6A'
+  if (transactionType === 'ADD_MONEY') return '#FFC900'
+  return getColorForUsername(recipientName).backgroundColor
+}

<AvatarWithBadge
  // ... other props
  inlineStyle={{
-    backgroundColor:
-      viewType === 'SUCCESS'
-        ? '#29CC6A'
-        : transactionType === 'ADD_MONEY'
-          ? '#FFC900'
-          : getColorForUsername(recipientName).backgroundColor,
+    backgroundColor: getAvatarBackgroundColor(),
  }}
/>
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx (1)

33-36: Guard against a null recipient before invoking PaymentPage
If, for any reason, recipientUsername is still null here (e.g., race condition, delayed search-param hydration) we pass [''] to PaymentPage, which will inevitably fail URL validation.
Add an early return to be extra safe:

-const recipientPathSegments = [recipientUsername ?? '']
+if (!recipientUsername) return null            // safety-net
+const recipientPathSegments = [recipientUsername]
src/components/Payment/Views/Status.payment.view.tsx (1)

181-192: Micro-copy: clarify the success message
For the add-money flow the sentence reads “You successfully added” without specifying what was added.
Consider appending “funds” (or similar) for clarity:

-You {isAddMoneyFlow ? 'successfully added' :
+You {isAddMoneyFlow ? 'successfully added funds' :
src/app/[...recipient]/client.tsx (1)

28-33: Unused isDirectPay flag – clean up for readability
isDirectPay is only referenced once (line 88) to decide whether to show the public profile view.
All other logic now hinges on the flow prop directly. Removing the redundant boolean will simplify mental parsing.

-    const isDirectPay = flow === 'direct_pay'
-    const isWithdrawFlow = flow === 'withdraw'
-    const isAddMoneyFlow = flow === 'add_money'
+    const isWithdrawFlow = flow === 'withdraw'
+    const isAddMoneyFlow = flow === 'add_money'

Remember to change the check on line 88 from !isDirectPay to flow !== 'direct_pay'.

src/hooks/usePaymentInitiator.ts (1)

788-798: Hard stop when wagmiAddress is undefined may block non-EVM add-money wallets
initiatePayment throws if wagmiAddress is falsy. This prevents alternative external-wallet integrations that don’t surface an address via wagmi (e.g., WalletConnect on non-EVM chains in future).
Gracefully fall back to handleExternalWalletPayment and let it fail only if an address is truly required.

-                    if (!wagmiAddress) {
-                        console.error('Add Money flow requires an external wallet (WAGMI) to be connected.')
-                        throw new Error('External wallet not connected for Add Money flow.')
-                    }
+                    if (!wagmiAddress) {
+                        console.warn('No wagmi address – attempting external-wallet flow anyway.')
+                    }
src/components/Payment/PaymentForm/index.tsx (1)

429-434: Dead code ‑ isTokenSelectorDisabled always returns false

The memoised function returns false in every branch, yet tracks six dependencies.
Either remove the computation entirely or implement the intended disabling rule; otherwise this causes unnecessary re-renders.

src/components/Payment/Views/Confirm.payment.view.tsx (2)

251-257: Header still reads “Send” during Add-Money / Withdraw confirmation

The flow-specific header was updated in PaymentForm, but the confirmation view keeps a static “Send” title, leading to UX inconsistency.

-<NavHeader title="Send" ... />
+<NavHeader title={isAddMoneyFlow ? 'Add Money' : isPintaReq ? 'Pay' : 'Send'} ... />

311-312: Hide “From” row when no wagmi address

wagmiAddress may be undefined immediately after a refresh; showing an empty address looks broken.

-{isAddMoneyFlow && <PaymentInfoRow label="From" value={printableAddress(wagmiAddress ?? '')} />}
+{isAddMoneyFlow && wagmiAddress && (
+    <PaymentInfoRow label="From" value={printableAddress(wagmiAddress)} />
+)}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between eb770b5 and 678f137.

📒 Files selected for processing (24)
  • src/app/(mobile-ui)/add-money/crypto/direct/page.tsx (1 hunks)
  • src/app/(mobile-ui)/add-money/crypto/page.tsx (1 hunks)
  • src/app/(mobile-ui)/pay/[...username]/page.tsx (1 hunks)
  • src/app/[...recipient]/client.tsx (6 hunks)
  • src/app/[...recipient]/page.tsx (2 hunks)
  • src/components/0_Bruddle/Button.tsx (3 hunks)
  • src/components/AddMoney/components/CryptoSourceListCard.tsx (1 hunks)
  • src/components/AddMoney/components/DepositMethodList.tsx (1 hunks)
  • src/components/AddMoney/consts/index.ts (1 hunks)
  • src/components/Global/ActionModal/index.tsx (6 hunks)
  • src/components/Global/AddressLink/index.tsx (2 hunks)
  • src/components/Global/Icons/Icon.tsx (6 hunks)
  • src/components/Global/Icons/alert.tsx (1 hunks)
  • src/components/Global/Icons/exchange-arrows.tsx (1 hunks)
  • src/components/Global/Icons/plus.tsx (1 hunks)
  • src/components/Global/Icons/switch.tsx (1 hunks)
  • src/components/Global/PeanutActionDetailsCard/index.tsx (4 hunks)
  • src/components/Global/TokenSelector/TokenSelector.tsx (3 hunks)
  • src/components/Payment/PaymentForm/index.tsx (16 hunks)
  • src/components/Payment/Views/Confirm.payment.view.tsx (10 hunks)
  • src/components/Payment/Views/Initial.payment.view.tsx (1 hunks)
  • src/components/Payment/Views/Status.payment.view.tsx (5 hunks)
  • src/components/Request/direct-request/views/Initial.direct.request.view.tsx (1 hunks)
  • src/hooks/usePaymentInitiator.ts (7 hunks)
✅ Files skipped from review due to trivial changes (4)
  • src/components/Request/direct-request/views/Initial.direct.request.view.tsx
  • src/components/Global/Icons/switch.tsx
  • src/app/[...recipient]/page.tsx
  • src/components/AddMoney/consts/index.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/components/Global/Icons/exchange-arrows.tsx
  • src/components/Global/Icons/plus.tsx
  • src/app/(mobile-ui)/add-money/crypto/page.tsx
  • src/components/Global/Icons/alert.tsx
  • src/components/Global/Icons/Icon.tsx
  • src/components/Global/ActionModal/index.tsx
  • src/components/AddMoney/components/DepositMethodList.tsx
  • src/components/AddMoney/components/CryptoSourceListCard.tsx
🧰 Additional context used
🧬 Code Graph Analysis (7)
src/components/0_Bruddle/Button.tsx (1)
src/components/Global/Icons/Icon.tsx (1)
  • Icon (146-155)
src/components/Payment/Views/Initial.payment.view.tsx (1)
src/components/Payment/PaymentForm/index.tsx (2)
  • PaymentFormProps (51-51)
  • PaymentForm (53-594)
src/app/[...recipient]/client.tsx (1)
src/redux/hooks.ts (2)
  • useAppDispatch (5-5)
  • usePaymentStore (12-12)
src/app/(mobile-ui)/pay/[...username]/page.tsx (1)
src/app/[...recipient]/client.tsx (1)
  • PaymentPage (28-320)
src/components/Global/TokenSelector/TokenSelector.tsx (1)
src/components/Global/Icons/Icon.tsx (1)
  • Icon (146-155)
src/components/Global/PeanutActionDetailsCard/index.tsx (2)
src/utils/color.utils.ts (1)
  • getColorForUsername (30-47)
src/constants/zerodev.consts.ts (1)
  • PEANUT_WALLET_TOKEN_SYMBOL (21-21)
src/hooks/usePaymentInitiator.ts (1)
src/services/services.types.ts (1)
  • TRequestChargeResponse (165-197)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview
🔇 Additional comments (20)
src/components/Global/TokenSelector/TokenSelector.tsx (5)

53-53: Good addition of the disabled prop to the interface.

Adding the optional disabled property to the NewTokenSelectorProps interface improves component flexibility, allowing it to be controlled in various contexts throughout the "Add Money" flow.


56-56: LGTM on function signature update.

The component signature has been correctly updated to accept the new disabled prop, maintaining proper TypeScript typing.


522-522: Good implementation of the disabled state.

The disabled prop is correctly passed down to the underlying Button component, enabling proper control of the interactivity state.


537-537: Appropriate icon change for the "Add Money" context.

Changing the icon from "currency" to "plus" is more intuitive for the add money flow, creating better visual affordance for users.


542-542: Improved text clarity.

Updating the placeholder text from "Select Token" to "Select a token" improves readability and grammar.

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

107-113: Good implementation of conditional icon positioning

The implementation cleanly handles the positioning of icons either before or after the button text, and properly merges default icon styling with custom classes. This adds flexibility while maintaining a consistent look and feel.

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

12-12: Good addition of the isLink prop.

This new prop adds flexibility to the component, allowing for non-clickable address displays when needed.


15-15: The function signature correctly includes the new prop.

The default value of true for isLink ensures backward compatibility with existing usage.


45-51: Clean implementation of conditional rendering.

The conditional rendering between a Link and a span element is well implemented, maintaining consistent styling between both variants.

src/app/(mobile-ui)/pay/[...username]/page.tsx (3)

1-1: Good component import update.

The import has been correctly updated to match the renamed component from the client module.


9-9: Descriptive component renaming.

Renaming from PayPage to DirectPaymentPage improves clarity about the component's specific purpose.


17-17: Improved prop API with flow-based approach.

Changing from the boolean isDirectPay to a string-based flow="direct_pay" is a good design choice that:

  1. Makes the code more self-documenting
  2. Provides more flexibility for future flow types
  3. Aligns with the updated PaymentPage implementation

This matches the implementation in src/app/[...recipient]/client.tsx which now handles multiple flow types.

src/components/Payment/Views/Initial.payment.view.tsx (1)

1-3: Simplified prop typing with reused type.

Good refactoring to directly reuse the PaymentFormProps type rather than creating a custom type.

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

11-11: Added support for the new 'ADD_MONEY' transaction type.

This change aligns with the broader "Add Money" feature implementation.


42-42: Appropriate icon selection for 'ADD_MONEY' transaction type.

The 'arrow-down' icon is a good choice for representing money being added to an account.


57-57: Clear title for the new transaction type.

"Add money to Peanut" clearly communicates the purpose of the transaction.


92-96: Improved token amount formatting.

The logic has been refined to handle different token display formats consistently.

src/hooks/usePaymentInitiator.ts (1)

318-325: prepareTransactionDetails early-return can mask errors when Peanut Wallet is connected
If the user has Peanut Wallet connected and chooses an external-wallet add-money flow, the current condition works as intended.
However, in all other cases where Peanut Wallet is connected but the transaction still needs preparation (e.g., token swap / x-chain), the early return prevents gas-fee estimation and leaves the UI in an inconsistent state.

Consider tightening the guard:

-if (isPeanutWallet && !isAddMoneyFlowContext) {
+// Skip preparation only when we are _both_ using Peanut Wallet
+// _and_ the chain & token match (no x-chain / swap).
+if (isPeanutWallet && !isAddMoneyFlowContext && !(_isXChain || _diffTokens)) {

Make sure _isXChain / _diffTokens are computed before this check.

src/components/Payment/PaymentForm/index.tsx (1)

264-274: Payload may carry an undefined recipient

Even after the guard above is fixed, recipient can still legally be undefined for the Add-Money flow.
usePaymentInitiator (and any backend validation) should not expect a recipient in this case. Make the field optional or omit it entirely when adding funds:

-        const payload = {
-            recipient: recipient,
+        const payload = {
+            ...(recipient && { recipient }),   // only include when present

(or adjust the initiator signature accordingly).

src/components/Payment/Views/Confirm.payment.view.tsx (1)

78-86: External-wallet modal may appear at the wrong time

showExternalWalletConfirmationModal forces the modal to show whenever isAddMoneyFlow is true, even if the transaction is processed via Peanut Wallet:

return isProcessing && (!isPeanutWallet || isAddMoneyFlow)

If a future release supports “Add Money” from Peanut Wallet, this condition will mis-fire.
Consider:

-(!isPeanutWallet || isAddMoneyFlow)
+(!isPeanutWallet && !isAddMoneyFlow) || (isAddMoneyFlow && !isPeanutWallet)

or split the logic for clarity.

@jjramirezn
Copy link
Contributor

Looking good, only thing is country page seems to not be implemented yet

signal-2025-05-21-151459.mp4

@kushagrasarathe kushagrasarathe changed the title [WIP] feat: add/withdraw funds feat: add and withdraw funds to peanut wallet May 21, 2025
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: 1

♻️ Duplicate comments (1)
src/components/Payment/PaymentForm/index.tsx (1)

427-463: isButtonDisabled logic can be simplified

The button disabled state logic has significant overlap with canInitiatePayment and could be simplified to reduce duplication.

Consider simplifying this logic to derive from canInitiatePayment:

 const isButtonDisabled = useMemo(() => {
     if (isProcessing) return true
     if (!!error) return true

     if (isAddMoneyFlow) {
         if (!isWagmiConnected) return false // "Connect Wallet" button should be active
-        return (
-            !inputTokenAmount ||
-            parseFloat(inputTokenAmount) <= 0 ||
-            !selectedTokenAddress ||
-            !selectedChainID ||
-            isProcessing
-        )
+        return isProcessing || !inputTokenAmount || parseFloat(inputTokenAmount) <= 0 || !selectedTokenAddress || !selectedChainID
     }

-    // Existing logic for non-AddMoneyFlow / non-Pinta (Pinta has its own button logic)
-    if (!isPintaReq) {
-        if (!inputTokenAmount || parseFloat(inputTokenAmount) <= 0) return true
-        if (!isConnected) return true // If not connected at all, disable (covers guest non-Peanut scenarios)
-        if (isActivePeanutWallet && isXChainPeanutWalletReq) return true // Peanut wallet x-chain restriction
-        if (!selectedTokenAddress || !selectedChainID) return true // Must have token/chain
-    }
-    // Fallback for Pinta or other cases if not explicitly handled above
-    return false
+    // For non-add money flows, use canInitiatePayment with additional checks
+    return !canInitiatePayment || (isActivePeanutWallet && isXChainPeanutWalletReq)
 }, [
     isProcessing,
     isAddMoneyFlow,
     isWagmiConnected,
     inputTokenAmount,
     selectedTokenAddress,
     selectedChainID,
+    canInitiatePayment,
     isConnected,
     isActivePeanutWallet,
     isXChainPeanutWalletReq,
     isPintaReq,
-    // Removed canInitiatePayment as it's too broad here
 ])
🧰 Tools
🪛 Biome (1.9.4)

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

🧹 Nitpick comments (1)
src/components/Payment/PaymentForm/index.tsx (1)

429-429: Fix redundant double negation

The static analysis detected unnecessary double negation.

-        if (!!error) return true
+        if (error) return true
🧰 Tools
🪛 Biome (1.9.4)

[error] 429-429: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 678f137 and 2a4588f.

📒 Files selected for processing (2)
  • src/components/Global/TokenSelector/TokenSelector.tsx (5 hunks)
  • src/components/Payment/PaymentForm/index.tsx (17 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/Global/TokenSelector/TokenSelector.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/Payment/PaymentForm/index.tsx

[error] 429-429: 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 (9)
src/components/Payment/PaymentForm/index.tsx (9)

38-41: Good addition of flow-specific prop types

The addition of isAddMoneyFlow and isWithdrawFlow flags to the PaymentFlowProps interface clearly defines the different payment flow modes the component now supports.


234-238: Wallet connection logic properly handles add money flow

The conditional check prevents users from proceeding without a connected wallet when in the add money flow, which is essential for funding operations.


312-312: Feature flag correctly passed to payment initiation

The isAddMoneyFlow flag is properly passed to the payment initiator, ensuring the correct payment flow path is followed.


348-355: Clear button text logic for different flows

The button text appropriately adapts to the current state - showing "Connect Wallet" when disconnected in add money flow, and "Review" for add/withdraw flows.


368-374: Button icon logic adds clear visual indicators

The wallet icon for the connect button in add money flow provides helpful visual context for users.


512-514: Dynamic UI header adapts to current flow

The header text now properly changes based on whether the user is adding money, withdrawing, or sending - providing clear context to the user.


516-536: Well-implemented wallet disconnect button

The wallet address display with disconnect option is cleanly implemented, appearing only when relevant (connected in add money flow).


573-575: Appropriate token selector for add money flow

The token selector appropriately appears only when needed for the add money flow with Wagmi connected.


602-628: Well-designed wallet disconnect modal

The ActionModal implementation for wallet disconnection provides clear user feedback and confirmation options, enhancing the user experience.

Copy link
Contributor

@jjramirezn jjramirezn left a comment

Choose a reason for hiding this comment

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

When depositing with an external wallet the following happens: the Insufficient balance message shows even when we have enough balance, and in some cases it does not show when we dont have enough balance. Check the pay flow to see how we are doing it currently:
signal-2025-05-22-103605_006

signal-2025-05-22-103605_008.mp4

signal-2025-05-22-103605_002

Also on pay flow from an external wallet, the button doesn't disable even when the error shows correctly (this works on staging)

signal-2025-05-22-103605_009

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

♻️ Duplicate comments (3)
src/components/Payment/PaymentForm/index.tsx (2)

488-530: Comprehensive button disabled logic but address past review feedback.

The current implementation addresses the logic requirements well, but there's a past review comment about duplicating logic with canInitiatePayment. Consider the previous suggestion to derive the disabled state from the existing helper.

Additionally, there's a static analysis hint about redundant double-negation:

-        if (!!error) return true
+        if (error) return true
🧰 Tools
🪛 Biome (1.9.4)

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


643-645: 🛠️ Refactor suggestion

Address token selector disabled logic issue.

This matches a previous review comment about the disabled prop logic being ineffective.

The component is only rendered when isWagmiConnected is true, but the disabled condition !isWagmiConnected && isAddMoneyFlow would never be true in this context.

-<TokenSelector viewType="add" disabled={!isWagmiConnected && isAddMoneyFlow} />
+<TokenSelector viewType="add" />
src/components/AddMoney/consts/index.ts (1)

1852-1857: ⚠️ Potential issue

Fix URL-unfriendly characters in path (duplicate issue).

The path for U.S. Minor Outlying Islands still contains periods which are URL-unfriendly, despite being flagged in previous reviews.

    {
        id: 'UM',
        type: 'country',
        title: 'U.S. Minor Outlying Islands',
        currency: 'USD',
-        path: 'u.s.-minor-outlying-islands',
+        path: 'us-minor-outlying-islands',
    },
🧹 Nitpick comments (2)
src/components/AddMoney/consts/index.ts (2)

23-23: Update or remove outdated temporary comment.

The comment indicates this crypto tokens list is temporary "for a couple of weeks" until x-chain is ready. Since this appears to be in active development, consider updating the timeline or removing the comment if the temporary nature is no longer accurate.


226-1984: Consider using an external data source for country information.

The large static country data array contains information that can become outdated (as evidenced by the currency code issues). Consider using a maintained external library or API for country data to ensure accuracy and reduce maintenance burden.

Some options:

  • world-countries npm package
  • country-data npm package
  • REST Countries API for dynamic updates

This would help prevent currency code drift and reduce the size of this constants file.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c2b841e and 3d986b5.

📒 Files selected for processing (17)
  • src/app/(mobile-ui)/add-money/crypto/direct/page.tsx (1 hunks)
  • src/app/(mobile-ui)/add-money/crypto/page.tsx (1 hunks)
  • src/components/0_Bruddle/Button.tsx (3 hunks)
  • src/components/AddMoney/consts/index.ts (1 hunks)
  • src/components/Claim/Link/Initial.view.tsx (2 hunks)
  • src/components/Global/ErrorAlert/index.tsx (1 hunks)
  • src/components/Global/PeanutActionCard/index.tsx (1 hunks)
  • src/components/Payment/PaymentForm/index.tsx (18 hunks)
  • src/components/Request/direct-request/views/Initial.direct.request.view.tsx (2 hunks)
  • src/components/Request/link/views/Create.request.link.view.tsx (2 hunks)
  • src/components/Send/link/views/Initial.link.send.view.tsx (2 hunks)
  • src/components/TransactionDetails/TransactionCard.tsx (2 hunks)
  • src/components/TransactionDetails/TransactionDetailsDrawer.tsx (4 hunks)
  • src/components/Withdraw/views/Confirm.withdraw.view.tsx (1 hunks)
  • src/hooks/usePaymentInitiator.ts (12 hunks)
  • src/hooks/useTransactionHistory.ts (1 hunks)
  • src/styles/globals.css (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • src/components/Global/PeanutActionCard/index.tsx
  • src/components/Request/link/views/Create.request.link.view.tsx
  • src/components/Global/ErrorAlert/index.tsx
  • src/hooks/useTransactionHistory.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/styles/globals.css
  • src/components/Request/direct-request/views/Initial.direct.request.view.tsx
  • src/components/Claim/Link/Initial.view.tsx
  • src/components/0_Bruddle/Button.tsx
  • src/app/(mobile-ui)/add-money/crypto/page.tsx
  • src/app/(mobile-ui)/add-money/crypto/direct/page.tsx
  • src/components/Withdraw/views/Confirm.withdraw.view.tsx
🧰 Additional context used
🧠 Learnings (1)
src/components/Payment/PaymentForm/index.tsx (1)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#424
File: src/components/Global/TokenSelector/TokenSelector.tsx:197-211
Timestamp: 2024-10-11T01:14:15.489Z
Learning: In `src/components/Global/TokenSelector/TokenSelector.tsx`, when the calculation within functions like `byChainAndText` is not computationally expensive, it's acceptable to avoid using `useCallback` for memoization.
🧬 Code Graph Analysis (2)
src/hooks/usePaymentInitiator.ts (1)
src/services/services.types.ts (1)
  • TRequestChargeResponse (165-197)
src/components/AddMoney/consts/index.ts (1)
src/components/Global/Icons/Icon.tsx (1)
  • IconName (49-94)
🪛 Biome (1.9.4)
src/components/Payment/PaymentForm/index.tsx

[error] 490-490: 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 (23)
src/components/Send/link/views/Initial.link.send.view.tsx (2)

132-133: LGTM! Good UI improvements for the file upload input.

The addition of the h-11 class provides consistent height styling, and changing the placeholder to "Comment" makes the input's purpose clearer to users.


145-145: LGTM! Improved button text provides better user feedback.

Changing from the dynamic loadingState to the static "Creating link" text provides more specific and actionable feedback to users about what operation is being performed.

src/components/Payment/PaymentForm/index.tsx (9)

40-53: LGTM! Clean type definitions for new payment flows.

The new PaymentFlowProps type clearly defines the optional boolean flags for different payment flows, and the extension of PaymentFormProps maintains good type safety.


152-232: Well-structured balance validation refactor with improved error handling.

The balance validation logic has been significantly improved with:

  • Clear separation between add money flow and regular payment flows
  • Proper error handling with try-catch blocks
  • Descriptive error messages for different scenarios
  • Comprehensive checks for token decimals and balance data

The logic correctly handles the add money flow by strictly checking external wallet balance when connected.


295-299: Good wallet connection check for add money flow.

The early return when Wagmi wallet is not connected in add money flow properly guides users to connect their wallet before proceeding.


373-373: Payload enhancement for add money flow tracking.

The addition of isAddMoneyFlow flag to the payment payload enables proper flow tracking in downstream handlers.


409-435: Well-designed conditional button text and icon logic.

The button text and icon logic properly handles different states:

  • Shows "Connect Wallet" with wallet icon when disconnected in add money flow
  • Shows "Review" for add money and withdraw flows
  • Shows "Send" for active Peanut wallet users

The logic is clear and covers all necessary states.


573-584: Excellent navigation integration for different flows.

The NavHeader component properly handles navigation back to the appropriate pages based on the flow type, and the dynamic title setting enhances user experience.


586-606: Well-implemented wallet disconnect functionality.

The switch button for Wagmi wallet disconnection is properly designed:

  • Only shows during add money flow when Wagmi is connected
  • Clear visual styling and interaction handling
  • Proper integration with AddressLink component

608-608: Correct conditional rendering for recipient card.

The recipient card is appropriately hidden during add money and withdraw flows since these don't involve sending to specific recipients.


673-699: Excellent modal implementation for wallet disconnection.

The ActionModal for Wagmi wallet disconnection is well-designed:

  • Clear title and description explaining the action
  • Proper button layout with disconnect and cancel options
  • Good UX with appropriate styling and callbacks
  • Prevents accidental disconnection with explicit confirmation
src/hooks/usePaymentInitiator.ts (8)

48-48: Good interface extension for add money flow tracking.

The addition of the optional isAddMoneyFlow boolean to the InitiatePaymentPayload interface enables proper flow differentiation throughout the payment process.


93-93: Appropriate state tracking for add money operations.

The currentOperationIsAddMoney state variable provides necessary context for gas estimation and transaction preparation logic.


163-185: Well-designed gas estimation logic with proper wallet routing.

The gas estimation logic correctly determines the appropriate estimator account based on transaction type:

  • Cross-chain transactions always use Wagmi wallet
  • Add money operations use Wagmi wallet
  • Regular operations fallback to connected wallet type

The error handling provides clear feedback when no valid estimator account is found.


322-324: Good context setting for transaction preparation.

The function signature update and state setting properly tracks the add money flow context for downstream logic.


344-351: Correct early return for Peanut Wallet in add money flow.

The logic correctly identifies that add money flow mandates external wallet usage, even when Peanut Wallet is connected, and skips Peanut Wallet-specific preparation.


799-811: Enhanced charge state handling for multiple flow types.

The charge creation logic properly handles the transition to Confirm view for Pinta requests, add money flow, and external wallet scenarios.


814-823: Robust add money flow execution with proper validation.

The add money flow execution includes:

  • Proper validation that Wagmi address is connected
  • Clear error messaging for missing external wallet
  • Appropriate routing to external wallet payment handler
  • Good logging for debugging purposes

948-951: Useful callback for operation cancellation.

The cancelOperation callback provides a way to handle user cancellation scenarios with appropriate error messaging and state management.

src/components/TransactionDetails/TransactionCard.tsx (2)

9-9: Good import organization.

Moving the import statement to be grouped with other imports improves code organization and readability.


125-125: Theme consistency improvement approved.

The color change from bg-pink-1 to bg-primary-1 for the pending indicator aligns with the primary theme colors, improving UI consistency.

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

141-141: Verify the sourceView condition change.

The condition was changed from transaction.sourceView === 'status' to transaction.sourceView === 'history'. This changes when the "Token and network" information is displayed, which could affect user experience.

Please ensure this change is intentional and aligns with the expected behavior for different transaction views.


301-303: UI consistency improvement approved.

The button components are now using the consistent icon prop pattern with proper styling instead of manually rendering Icon components. This improves UI consistency and maintainability.

Also applies to: 345-347

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

♻️ Duplicate comments (3)
src/components/AddMoney/consts/index.ts (3)

1698-1702: Update outdated currency code for São Tomé and Príncipe.

This currency code issue was flagged in previous reviews but remains unaddressed.

 {
     id: 'ST',
     type: 'country',
     title: 'São Tomé and Príncipe',
-    currency: 'STD',
+    currency: 'STN',
     path: 'sao-tome-and-principe',
 },

1901-1905: Update outdated currency code for Venezuela.

This currency code issue was flagged in previous reviews but remains unaddressed.

 {
     id: 'VE',
     type: 'country',
     title: 'Venezuela',
-    currency: 'VEF',
+    currency: 'VES',
     path: 'venezuela',
 },

1860-1864: Fix URL-unfriendly path for U.S. Minor Outlying Islands.

This path issue was flagged in previous reviews but remains unaddressed.

 {
     id: 'UM',
     type: 'country',
     title: 'U.S. Minor Outlying Islands',
     currency: 'USD',
-    path: 'u.s.-minor-outlying-islands',
+    path: 'us-minor-outlying-islands',
 },
🧹 Nitpick comments (1)
src/components/AddMoney/consts/index.ts (1)

1993-2035: Consider extracting country-specific method generation logic.

While the current implementation works, consider extracting this initialization logic into a separate function or utility for better maintainability and testability.

function buildCountrySpecificMethods(countryData: CountryData[]): Record<string, CountrySpecificMethods> {
    const methods: Record<string, CountrySpecificMethods> = {}
    
    countryData.forEach((country) => {
        if (country.type === 'country') {
            // existing logic here
        }
    })
    
    return methods
}

export const COUNTRY_SPECIFIC_METHODS = buildCountrySpecificMethods(countryData)
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 045c77f and 5c46e2c.

📒 Files selected for processing (3)
  • src/app/(mobile-ui)/add-money/crypto/page.tsx (1 hunks)
  • src/components/AddMoney/components/CryptoSourceListCard.tsx (1 hunks)
  • src/components/AddMoney/consts/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/components/AddMoney/components/CryptoSourceListCard.tsx
  • src/app/(mobile-ui)/add-money/crypto/page.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/components/AddMoney/consts/index.ts (1)
src/components/Global/Icons/Icon.tsx (1)
  • IconName (49-94)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview
🔇 Additional comments (2)
src/components/AddMoney/consts/index.ts (2)

7-150: Well-structured interface definitions.

The type definitions and interfaces are clean, properly typed, and well-organized. Good use of union types and optional properties.


1-6: Clean imports and file organization.

Good organization of imports and proper separation of concerns throughout the file.

Comment on lines +110 to +115
id: 'trust-wallet',
name: 'Trust Wallet',
type: 'wallet',
icon: TRUST_WALLET_LOGO,
path: '/add-money/crypto/rainbow',
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix incorrect path for Trust Wallet.

Trust Wallet's path incorrectly points to 'rainbow' instead of 'trust-wallet', which will cause incorrect routing.

 {
     id: 'trust-wallet',
     name: 'Trust Wallet',
     type: 'wallet',
     icon: TRUST_WALLET_LOGO,
-    path: '/add-money/crypto/rainbow',
+    path: '/add-money/crypto/trust-wallet',
 },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
id: 'trust-wallet',
name: 'Trust Wallet',
type: 'wallet',
icon: TRUST_WALLET_LOGO,
path: '/add-money/crypto/rainbow',
},
{
id: 'trust-wallet',
name: 'Trust Wallet',
type: 'wallet',
icon: TRUST_WALLET_LOGO,
path: '/add-money/crypto/trust-wallet',
},
🤖 Prompt for AI Agents
In src/components/AddMoney/consts/index.ts between lines 110 and 115, the path
for the Trust Wallet entry is incorrectly set to '/add-money/crypto/rainbow'.
Update this path to '/add-money/crypto/trust-wallet' to ensure correct routing
for Trust Wallet.

Comment on lines +2004 to +2012
specificWithdrawals.forEach((method) => {
withdrawList.push({
id: `${countryCode.toLowerCase()}-${method.title.toLowerCase()}-withdraw`,
icon: method.icon as IconName,
title: method.title,
description: method.description,
isSoon: true,
})
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Address potential type safety issue with icon property.

The code assumes method.icon exists when casting to IconName, but the countrySpecificWithdrawMethods type allows icon to be optional. This could cause runtime issues.

 specificWithdrawals.forEach((method) => {
     withdrawList.push({
         id: `${countryCode.toLowerCase()}-${method.title.toLowerCase()}-withdraw`,
-        icon: method.icon as IconName,
+        icon: (method.icon || 'bank') as IconName,
         title: method.title,
         description: method.description,
         isSoon: true,
     })
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
specificWithdrawals.forEach((method) => {
withdrawList.push({
id: `${countryCode.toLowerCase()}-${method.title.toLowerCase()}-withdraw`,
icon: method.icon as IconName,
title: method.title,
description: method.description,
isSoon: true,
})
})
specificWithdrawals.forEach((method) => {
withdrawList.push({
id: `${countryCode.toLowerCase()}-${method.title.toLowerCase()}-withdraw`,
icon: (method.icon || 'bank') as IconName,
title: method.title,
description: method.description,
isSoon: true,
})
})
🤖 Prompt for AI Agents
In src/components/AddMoney/consts/index.ts around lines 2004 to 2012, the icon
property is cast to IconName without checking if method.icon exists, which risks
runtime errors due to its optional type. Fix this by adding a conditional check
to ensure method.icon is defined before casting, or provide a safe fallback
value when method.icon is undefined to maintain type safety.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants