Skip to content

Conversation

Zishan-7
Copy link
Contributor

No description provided.

Copy link

vercel bot commented Sep 10, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
peanut-wallet Ready Ready Preview Comment Sep 16, 2025 5:22pm

Copy link

Copy link
Contributor

coderabbitai bot commented Sep 10, 2025

Walkthrough

Introduces a MercadoPago/Manteca flow across claim and request fulfillment. Adds new context flags, components, API methods, and types to support deposit/withdraw steps. Gates ActionList and PaymentForm based on new flags. Replaces previous onramp usage with mantecaApi. Adds UI components for displaying account details and logos.

Changes

Cohort / File(s) Summary
Fulfillment flow integration
src/app/[...recipient]/client.tsx, src/components/Common/ActionList.tsx, src/components/Payment/PaymentForm/index.tsx, src/components/Payment/Views/MantecaFulfillment.view.tsx, src/context/RequestFulfillmentFlowContext.tsx, src/constants/actionlist.consts.ts
Adds fulfilUsingManteca flag and setter; gates ActionList and PaymentForm; triggers flag from ActionList for 'mercadopago'; introduces MantecaFulfillment view; flips MercadoPago method soon=false.
Claim flow: MercadoPago path
src/components/Claim/Link/Initial.view.tsx, src/components/Claim/Link/MantecaFlowManager.tsx, src/components/Claim/Link/views/MantecaDetailsStep.view.tsx, src/components/Claim/Link/views/MantecaReviewStep.tsx, src/context/ClaimBankFlowContext.tsx, src/components/Global/PeanutActionDetailsCard/index.tsx, src/components/Profile/AvatarWithBadge.tsx
Adds claimToMercadoPago flag/setter; short-circuits Initial view to new MantecaFlowManager with DETAILS/REVIEW/SUCCESS steps; extends PeanutActionDetailsCard with REGIONAL_METHOD_CLAIM and logo passthrough; Avatar supports logo prop.
Manteca API, types, and constants
src/types/manteca.types.ts, src/services/manteca.ts, src/app/actions/manteca.ts, src/constants/manteca.consts.ts, src/constants/index.ts, src/app/actions/onramp.ts, src/components/AddMoney/components/RegionalMethods/MercadoPago/index.tsx
Adds withdraw data/response types, enum steps, and onramp params; implements mantecaApi.deposit/withdraw and server action mantecaWithdraw; exports MANTECA_DEPOSIT_ADDRESS; re-exports constants; removes createMantecaOnramp and updates flows to use mantecaApi.deposit.
Details card and related UI
src/components/Global/MantecaDetailsCard/index.tsx, src/components/AddMoney/components/MantecaDepositCard.tsx, src/components/Payment/PaymentInfoRow.tsx, src/components/Global/CopyToClipboard/index.tsx
Introduces MantecaDetailsCard and row interfaces; refactors MantecaDepositCard to use MantecaDetailsCard with conditional rows; extracts PaymentInfoRowProps; adds cursor-pointer to copy icon.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • jjramirezn
  • kushagrasarathe
  • Hugo0

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description Check ❓ Inconclusive No pull request description was provided by the author, so there is insufficient information in the PR description field to determine whether it summarizes the changes; although the provided raw_summary documents the changes in detail, the absent author description makes this check inconclusive. Request the author to add a short PR description summarizing the purpose, the main user-facing behavior changes (e.g., added Manteca claim/fulfillment flows), key files or public API changes (new context flags, services, and exported types), and any migration or runtime considerations.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "[TASK-14307] Feat/manteca claim request" succinctly identifies the primary work—adding Manteca-related claim/request functionality—and matches the changes in the diff (new Manteca components, context flags, services, and types); it is concise, focused, and includes the task ID for traceability.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/manteca-claim-request

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)

170-189: Fix logo rendering and alt text when using provider logos (Mercado Pago).

Image only renders if countryCodeForFlag is present, even when logo is provided, and the alt references a flag while a logo may be shown. Render when either is present and set an appropriate alt.

   const withdrawBankIcon = () => {
-        const imgSrc = logo ? logo : `https://flagcdn.com/w320/${countryCodeForFlag}.png`
-        if (isWithdrawBankAccount || isAddBankAccount || isClaimLinkBankAccount)
+        const imgSrc = logo ?? (countryCodeForFlag ? `https://flagcdn.com/w320/${countryCodeForFlag}.png` : undefined)
+        if (isWithdrawBankAccount || isAddBankAccount || isClaimLinkBankAccount)
             return (
                 <div className="relative mr-1 h-12 w-12">
-                    {countryCodeForFlag && (
+                    {imgSrc && (
                         <Image
                             src={imgSrc}
-                            alt={`${countryCodeForFlag} flag`}
+                            alt={logo ? 'Provider logo' : `${countryCodeForFlag} flag`}
                             width={160}
                             height={160}
                             className="h-12 w-12 rounded-full object-cover"
                         />
                     )}
                     <div className="absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full bg-yellow-400 p-1.5">
                         <Icon name="bank" className="h-full w-full text-black" />
                     </div>
                 </div>
             )
         return undefined
     }
🧹 Nitpick comments (16)
src/components/Global/CopyToClipboard/index.tsx (1)

24-29: Make the clickable icon keyboard- and screen-reader-friendly.

Now that it’s pointer-enabled, add role, tab focus, a label, and Enter/Space handling.

   return (
     <Icon
       name={copied ? 'check' : 'copy'}
-      className={twMerge(`h-${iconSize} w-${iconSize} cursor-pointer hover:opacity-80`, className)}
+      className={twMerge(`h-${iconSize} w-${iconSize} cursor-pointer hover:opacity-80`, className)}
       fill={fill ? fill : 'white'}
-      onClick={handleCopy}
+      role="button"
+      tabIndex={0}
+      aria-label={copied ? 'Copied' : 'Copy to clipboard'}
+      title={copied ? 'Copied' : 'Copy to clipboard'}
+      onClick={handleCopy}
+      onKeyDown={(e) => {
+        if (e.key === 'Enter' || e.key === ' ') {
+          e.preventDefault()
+          handleCopy(e as unknown as React.MouseEvent<SVGElement>)
+        }
+      }}
     />
   )
src/constants/actionlist.consts.ts (1)

30-31: Gate Mercado Pago availability behind a feature flag.

Flipping soon: false exposes it for all environments. Consider env-flagging for safe rollout.

+const MERCADOPAGO_ENABLED = process.env.NEXT_PUBLIC_MERCADOPAGO_ENABLED === 'true'
 ...
   {
     id: 'mercadopago',
     title: 'Mercado Pago',
     description: 'Instant transfers',
     icons: [MERCADO_PAGO],
-    soon: false,
+    soon: !MERCADOPAGO_ENABLED,
   },
src/types/manteca.types.ts (1)

7-11: LGTM — enum reads clean and self-explanatory.

Optionally predefine failure/cancel steps (e.g., ERROR, CANCELED) if your flow needs them later.

src/context/RequestFulfillmentFlowContext.tsx (1)

66-87: Avoid the type assertion on Provider by typing useMemo’s return.

Removes the need for as RequestFulfillmentFlowContextType and lets TS catch omissions.

-  const value = useMemo(
-    () => ({
+  const value = useMemo<RequestFulfillmentFlowContextType>(
+    () => ({
       resetFlow,
       externalWalletFulfilMethod,
       setExternalWalletFulfilMethod,
       showExternalWalletFulfilMethods,
       setShowExternalWalletFulfilMethods,
       flowStep,
       setFlowStep,
       showRequestFulfilmentBankFlowManager,
       setShowRequestFulfilmentBankFlowManager,
       selectedCountry,
       setSelectedCountry,
       onrampData,
       setOnrampData,
       showVerificationModal,
       setShowVerificationModal,
       requesterDetails,
       setRequesterDetails,
       fulfilUsingManteca,
       setFulfilUsingManteca,
     }),
     [
       resetFlow,
       externalWalletFulfilMethod,
       showExternalWalletFulfilMethods,
       flowStep,
       showRequestFulfilmentBankFlowManager,
       selectedCountry,
       onrampData,
       showVerificationModal,
       requesterDetails,
       fulfilUsingManteca,
     ]
   )
 ...
-  <RequestFulfillmentFlowContext.Provider value={value as RequestFulfillmentFlowContextType}>
+  <RequestFulfillmentFlowContext.Provider value={value}>
src/components/Payment/PaymentInfoRow.tsx (2)

7-15: Prefer importing ReactNode type over React.ReactNode.

Avoids relying on ambient React namespace and keeps types lean.

-import { useId, useState } from 'react'
+import { useId, useState } from 'react'
+import type { ReactNode } from 'react'
 ...
 export interface PaymentInfoRowProps {
-    label: string | React.ReactNode
-    value: number | string | React.ReactNode
+    label: string | ReactNode
+    value: number | string | ReactNode
     moreInfoText?: string
     loading?: boolean
     hideBottomBorder?: boolean
     allowCopy?: boolean
     copyValue?: string
 }

39-52: Make the info button fully keyboard-accessible.

Handle Enter/Space and add an aria-label.

-          <div
+          <div
             className="relative z-20 flex items-center justify-center px-2"
             role="button"
             tabIndex={0}
             aria-describedby={tooltipId}
+            aria-label="More information"
             onFocus={() => setShowMoreInfo(true)}
             onBlur={() => setShowMoreInfo(false)}
+            onKeyDown={(e) => {
+              if (e.key === 'Enter' || e.key === ' ') {
+                e.preventDefault()
+                setShowMoreInfo((v) => !v)
+              }
+            }}
           >
src/components/Global/PeanutActionDetailsCard/index.tsx (1)

137-149: Include REGIONAL_METHOD_CLAIM in avatar color rules for visual consistency.

Treat it like bank/withdraw paths.

   const getAvatarBackgroundColor = (): string => {
     if (viewType === 'SUCCESS') return '#29CC6A'
     if (
       transactionType === 'ADD_MONEY' ||
       (transactionType === 'WITHDRAW' && recipientType === 'USERNAME') ||
       recipientType === 'ADDRESS' ||
       recipientType === 'ENS' ||
       transactionType === 'WITHDRAW_BANK_ACCOUNT' ||
-      transactionType === 'CLAIM_LINK_BANK_ACCOUNT'
+      transactionType === 'CLAIM_LINK_BANK_ACCOUNT' ||
+      transactionType === 'REGIONAL_METHOD_CLAIM'
     )
       return '#FFC900'
     return getColorForUsername(recipientName).lightShade
   }

   const getAvatarTextColor = (): string => {
     if (
       viewType === 'SUCCESS' ||
       transactionType === 'ADD_MONEY' ||
       (transactionType === 'WITHDRAW' && recipientType === 'USERNAME') ||
       recipientType === 'ADDRESS' ||
       recipientType === 'ENS' ||
       transactionType === 'WITHDRAW_BANK_ACCOUNT' ||
-      transactionType === 'CLAIM_LINK_BANK_ACCOUNT'
+      transactionType === 'CLAIM_LINK_BANK_ACCOUNT' ||
+      transactionType === 'REGIONAL_METHOD_CLAIM'
     ) {
       return AVATAR_TEXT_DARK
     }
     return getColorForUsername(recipientName).darkShade
   }

Also applies to: 151-164

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

64-66: ActionList gating may hide UI with no replacement when fulfilUsingManteca is true.

You hide ActionList, but this file doesn’t render a Manteca fulfilment manager/view. Ensure the Manteca request flow mounts when fulfilUsingManteca is set.

Example placement (adjust import/path as needed):

+ // render Manteca fulfilment flow
+ if (fulfilUsingManteca) {
+   return <MantecaFulfuilmentView parsedPaymentData={parsedPaymentData as ParsedURL} />
+ }

Also applies to: 486-493

src/context/ClaimBankFlowContext.tsx (1)

113-115: Nit: setters don’t need to be dependencies of useMemo.

React guarantees state setters are stable. Dropping them reduces needless recomputations.

-            claimToMercadoPago,
-            setClaimToMercadoPago,
+            claimToMercadoPago,

And remove setClaimToMercadoPago from the dependency array.

Also applies to: 131-133

src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (1)

16-20: Add accessible label/help text to the input and capture value.

Placeholder-only inputs are not accessible. Also consider disabling “Review” until valid input is provided.

-            <BaseInput placeholder="CVU or Alias" />
+            <BaseInput
+                placeholder="CVU or Alias"
+                aria-label="CVU or Alias"
+                // value={cvuOrAlias}
+                // onChange={(e) => setCvuOrAlias(e.target.value)}
+            />

And optionally:

-            <Button onClick={() => setCurrentStep(MercadoPagoStep.REVIEW)} shadowSize="4">
+            <Button
+                onClick={() => setCurrentStep(MercadoPagoStep.REVIEW)}
+                shadowSize="4"
+                // disabled={!cvuOrAlias?.trim()}
+            >
src/components/Claim/Link/views/MantecaReviewStep.tsx (1)

11-43: Replace placeholder strings with real data and format currency/exchange rate.

These look hard-coded. Pull from context/state and format with Intl for locale correctness.

Example:

-            value: 'Manuel Rodríguez Roldán',
+            value: fullName,
...
-            value: '1 USD = 1200 ARS',
+            value: `1 USD = ${new Intl.NumberFormat('es-AR').format(exchangeRateARS)} ARS`,
...
-            value: '1000',
+            value: new Intl.NumberFormat('es-AR', { style: 'currency', currency: 'ARS' }).format(feeARS),
src/components/Payment/PaymentForm/index.tsx (2)

644-647: Early Manteca branch: fix identifier and confirm precedence/props.

  • Use the corrected component name from the import fix.
  • Confirm the Manteca view doesn’t need props from PaymentForm; otherwise pass them through.

Apply:

-    if (fulfilUsingManteca) {
-        return <MantecaFulfuilment />
-    }
+    if (fulfilUsingManteca) {
+        return <MantecaFulfilment />
+    }

Optionally, if props are needed:

return <MantecaFulfilment /* pass needed props here */ />

39-39: Optional refactor: standardize “MantecaFulfuilment” spelling
Rename src/components/Payment/Views/MantecaFulfuilment.view.tsx (and all its imports/exports/JSX usage in src/components/Payment/PaymentForm/index.tsx) to the correct spelling—e.g. MantecaFulfilment (or MantecaFulfillment).

src/components/Claim/Link/MantecaFlowManager.tsx (1)

56-59: Back icon choice nit: use a left chevron for back navigation.

Minor UX consistency. If your design system prefers left chevrons for “back”, switch to chevron-left.

-            <NavHeader icon={isSuccess ? 'cancel' : 'chevron-up'} title="Receive" onPrev={onPrev} />
+            <NavHeader icon={isSuccess ? 'cancel' : 'chevron-left'} title="Receive" onPrev={onPrev} />
src/components/Payment/Views/MantecaFulfuilment.view.tsx (2)

14-17: Replace placeholders with real Manteca account data before shipping.

'[CVU/ALIAS]' and 'manurr.mp' look like placeholders. Wire these from the store/context and ensure the copied/share text uses actual values. Also confirm the correct field naming (CBU vs CVU) for Mercado Pago.

Would you like me to scan the repo for available Manteca fields and propose exact bindings?


10-13: Rename MantecaFulfuilment component and file to MantecaFulfillment

  • In src/components/Payment/Views/MantecaFulfuilment.view.tsx, rename the component and default export to MantecaFulfillment and update the filename accordingly.
  • In src/components/Payment/PaymentForm/index.tsx (lines 39 and 645), update the import and JSX usage from MantecaFulfuilment to MantecaFulfillment.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3a43f4 and a333a54.

📒 Files selected for processing (18)
  • src/app/[...recipient]/client.tsx (2 hunks)
  • src/components/AddMoney/components/MantecaDepositCard.tsx (2 hunks)
  • src/components/Claim/Link/Initial.view.tsx (3 hunks)
  • src/components/Claim/Link/MantecaFlowManager.tsx (1 hunks)
  • src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (1 hunks)
  • src/components/Claim/Link/views/MantecaReviewStep.tsx (1 hunks)
  • src/components/Common/ActionList.tsx (4 hunks)
  • src/components/Global/CopyToClipboard/index.tsx (1 hunks)
  • src/components/Global/MantecaDetailsCard/index.tsx (1 hunks)
  • src/components/Global/PeanutActionDetailsCard/index.tsx (4 hunks)
  • src/components/Payment/PaymentForm/index.tsx (3 hunks)
  • src/components/Payment/PaymentInfoRow.tsx (2 hunks)
  • src/components/Payment/Views/MantecaFulfuilment.view.tsx (1 hunks)
  • src/components/Profile/AvatarWithBadge.tsx (5 hunks)
  • src/constants/actionlist.consts.ts (1 hunks)
  • src/context/ClaimBankFlowContext.tsx (5 hunks)
  • src/context/RequestFulfillmentFlowContext.tsx (5 hunks)
  • src/types/manteca.types.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-26T17:38:37.055Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/components/Common/ActionList.tsx:153-156
Timestamp: 2025-08-26T17:38:37.055Z
Learning: In ActionList.tsx, when there are circular dependency concerns with ACTION_METHODS being imported by other components, the preferred solution is to move ACTION_METHODS to a separate constants file (like src/constants/actionlist.consts.ts) rather than using prop drilling. This centralizes constants management and creates a cleaner dependency graph.

Applied to files:

  • src/components/Common/ActionList.tsx
📚 Learning: 2025-06-18T19:56:55.443Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#919
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:87-87
Timestamp: 2025-06-18T19:56:55.443Z
Learning: In withdraw flows for Peanut Wallet, the PeanutActionDetailsCard should always display "USDC" as the token symbol because it shows the amount being withdrawn from the Peanut Wallet (which holds USDC), regardless of the destination token/chain selected by the user. The TokenSelector is used for choosing the withdrawal destination, not the source display.

Applied to files:

  • src/components/Global/PeanutActionDetailsCard/index.tsx
🧬 Code graph analysis (9)
src/components/Claim/Link/views/MantecaReviewStep.tsx (2)
src/components/Global/MantecaDetailsCard/index.tsx (1)
  • MantecaCardRow (5-7)
src/components/0_Bruddle/Button.tsx (1)
  • Button (76-267)
src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (2)
src/components/Global/Icons/Icon.tsx (1)
  • Icon (195-204)
src/components/0_Bruddle/Button.tsx (1)
  • Button (76-267)
src/components/Payment/Views/MantecaFulfuilment.view.tsx (4)
src/context/RequestFulfillmentFlowContext.tsx (1)
  • useRequestFulfillmentFlow (109-115)
src/redux/hooks.ts (1)
  • usePaymentStore (12-12)
src/components/Global/MantecaDetailsCard/index.tsx (1)
  • MantecaCardRow (5-7)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
  • PeanutActionDetailsCard (55-256)
src/components/Common/ActionList.tsx (1)
src/context/ClaimBankFlowContext.tsx (1)
  • useClaimBankFlow (143-149)
src/components/Claim/Link/MantecaFlowManager.tsx (4)
src/services/sendLinks.ts (1)
  • ClaimLinkData (62-62)
src/context/ClaimBankFlowContext.tsx (1)
  • useClaimBankFlow (143-149)
src/components/0_Bruddle/Button.tsx (1)
  • Button (76-267)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
  • PeanutActionDetailsCard (55-256)
src/components/Payment/PaymentForm/index.tsx (1)
src/context/RequestFulfillmentFlowContext.tsx (1)
  • useRequestFulfillmentFlow (109-115)
src/components/Global/MantecaDetailsCard/index.tsx (1)
src/components/Payment/PaymentInfoRow.tsx (2)
  • PaymentInfoRowProps (7-15)
  • PaymentInfoRow (17-83)
src/components/Claim/Link/Initial.view.tsx (1)
src/utils/general.utils.ts (1)
  • formatTokenAmount (453-474)
src/app/[...recipient]/client.tsx (1)
src/context/RequestFulfillmentFlowContext.tsx (1)
  • useRequestFulfillmentFlow (109-115)
🪛 Biome (2.1.2)
src/components/Global/MantecaDetailsCard/index.tsx

[error] 17-17: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🔇 Additional comments (10)
src/context/RequestFulfillmentFlowContext.tsx (1)

35-37: Nice addition — state and setter are part of the context.

Ensure downstream consumers treat this as the single source of truth for the Manteca guard.

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

216-238: Verify USDC display behavior for Peanut Wallet withdraw flows.

Per our learning, the details card should explicitly display “USDC” for Peanut Wallet withdrawals. Currently, when tokenSymbol equals PEANUT_WALLET_TOKEN_SYMBOL, the UI prefixes with $ and omits the token label. Confirm this matches product guidance for withdraw screens, or adjust to show “USDC”.

src/components/Common/ActionList.tsx (1)

45-51: Wire-ups for Mercado Pago flags look good.

Setting setClaimToMercadoPago(true) and setFulfilUsingManteca(true) cleanly branches both flows without prop-drilling.

Also applies to: 88-90, 110-112

src/context/ClaimBankFlowContext.tsx (1)

45-47: Solid addition of Mercado Pago flow flags with proper reset.

State, setter, and reset are correctly exposed and memoized.

Also applies to: 65-66, 81-82, 113-115, 131-133

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

84-85: No action needed — PaymentForm is within the RequestFulfilmentFlowContextProvider

The root ContextProvider (used in src/app/layout.tsx) already wraps all routes—including PaymentForm—with RequestFulfilmentFlowContextProvider, so useRequestFulfillmentFlow() will never throw.

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

54-54: LGTM: Manteca manager import added.


95-96: LGTM: claimToMercadoPago wired from context.


632-646: Prevent NaN in MantecaFlowManager and enforce branch exclusivity

  • In the amount prop, guard the multiplication by tokenPrice (e.g. tokenPrice ? rawAmount * tokenPrice : undefined) so formatTokenAmount falls back to '' instead of producing "NaN".
  • Ensure claimToMercadoPago and claimBankFlowStep can’t both be truthy—or reorder to prioritize Manteca first:
    if (claimToMercadoPago) return <MantecaFlowManager  />;
    if (claimBankFlowStep)  return <BankFlowManager    />;
src/components/Payment/Views/MantecaFulfuilment.view.tsx (2)

37-49: PeanutActionDetailsCard wiring looks good.

Props are guarded with optional chaining and reasonable defaults; logo integration for Mercado Pago is correct.


54-61: Share generation hook is fine; keep async if API expects it.

If ShareButton.generateText accepts a Promise, your async wrapper is appropriate. After fixing generateShareText, no further change needed.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/app/actions/onramp.ts (1)

127-133: Handle missing auth token before calling Manteca deposit.

If jwt-token is absent, you still send Authorization: Bearer undefined. Bail out early with a clear error like other actions do. Also, cookies() is synchronous in server actions—drop the unnecessary await.

Apply:

-    const cookieStore = cookies()
-    const jwtToken = (await cookieStore).get('jwt-token')?.value
+    const cookieStore = cookies()
+    const jwtToken = cookieStore.get('jwt-token')?.value
+    if (!jwtToken) {
+        return { error: 'Authentication token not found.' }
+    }
src/app/actions/claimLinks.ts (1)

85-97: Don’t send a bogus “recipient” when destinationAddress is present (prevents backend confusion).

In the Manteca flow, you currently call claim(recipient=destinationAddress, ..., destinationAddress). Make the server payload omit recipient when destinationAddress is provided.

Apply:

 export async function claimSendLink(pubKey: string, recipient: string, password: string, destinationAddress?: string) {
@@
-        body: JSON.stringify({
-            recipient,
-            password,
-            destinationAddress,
-        }),
+        body: JSON.stringify(
+            destinationAddress
+                ? { password, destinationAddress }
+                : { recipient, password }
+        ),

This keeps existing callers intact and ensures Manteca claims don’t pass an invalid “recipient”.

♻️ Duplicate comments (1)
src/components/Payment/Views/MantecaFulfuilment.view.tsx (1)

29-35: Build share text from the same rows you render (no “undefined” lines, stays in sync).

Unify the source of truth for account details.

-    const generateShareText = () => {
-        const textParts = []
-        textParts.push(`CBU: ${depositData?.data?.depositAddress}`)
-        textParts.push(`Alias: ${depositData?.data?.depositAlias}`)
-
-        return textParts.join('\n')
-    }
+    const rows =
+        depositData?.data
+            ? [
+                  ...(depositData.data.depositAddress
+                      ? [{ key: 'cbu', label: 'CBU', value: depositData.data.depositAddress, allowCopy: true }] as const
+                      : []),
+                  ...(depositData.data.depositAlias
+                      ? [{ key: 'alias', label: 'Alias', value: depositData.data.depositAlias, hideBottomBorder: true }] as const
+                      : []),
+              ]
+            : []
+
+    const generateShareText = () =>
+        rows.map(({ label, value }) => `${label}: ${String(value ?? '')}`).join('\n')
@@
-                        <MantecaDetailsCard
-                            rows={[
-                                ...(depositData?.data?.depositAddress
-                                    ? [
-                                          {
-                                              key: 'cbu',
-                                              label: 'CBU',
-                                              value: depositData.data.depositAddress,
-                                              allowCopy: true,
-                                          },
-                                      ]
-                                    : []),
-                                ...(depositData?.data?.depositAlias
-                                    ? [
-                                          {
-                                              key: 'alias',
-                                              label: 'Alias',
-                                              value: depositData.data.depositAlias,
-                                              hideBottomBorder: true,
-                                          },
-                                      ]
-                                    : []),
-                            ]}
-                        />
+                        <MantecaDetailsCard rows={rows} />

Also applies to: 69-93

🧹 Nitpick comments (12)
src/app/actions/onramp.ts (3)

136-148: Remove debug logs and rely on Sentry-instrumented fetch.

console.log('called hahahahha') and logging the raw Response add noise and potential PII leakage. fetchWithSentry already captures failures.

Apply:

-        console.log('called hahahahha')
         const response = await fetchWithSentry(`${apiUrl}/manteca/deposit`, {
@@
-        if (!response.ok) {
-            console.log('error', response)
+        if (!response.ok) {
             return { error: data.error || 'Failed to create on-ramp transfer for guest.' }
         }

160-166: Avoid duplicative error logging.

console.error below is sufficient; drop the extra console.log.

-        console.log('error', error)
         console.error('Error calling create manteca on-ramp API:', error)

100-105: Improve error surfacing for guest onramp.

Logging the whole Response object isn’t actionable and can’t be serialized; prefer server-captured details and return a clearer message.

-            console.log('error', response)
             return { error: data.error || 'Failed to create on-ramp transfer for guest.' }
src/app/actions/claimLinks.ts (1)

98-101: Bubble up backend error details for better UX.

Consider parsing and including backend error JSON/text in the thrown error.

-    if (!response.ok) {
-        throw new Error(`HTTP error! status: ${response.status}`)
-    }
+    if (!response.ok) {
+        const text = await response.text()
+        try {
+            const err = jsonParse(text)
+            throw new Error(`HTTP ${response.status}: ${err.message || err.error || text}`)
+        } catch {
+            throw new Error(`HTTP ${response.status}: ${text}`)
+        }
+    }
src/services/sendLinks.ts (1)

195-203: Clarify API doc: recipient is ignored when destinationAddress is provided.

Aligns with the server payload logic updated in claimSendLink.

  /**
   * Claim a send link
   *
-  * @param recipient - The recipient's address or username
+  * @param recipient - The recipient's address or username (ignored if destinationAddress is provided)
   * @param link - The link to claim
-  * @param destinationAddress - The destination address to claim the link to (for manteca claims)
+  * @param destinationAddress - The destination address to claim the link to (Manteca/MP claims)
   * @returns The claim link data
   */
src/app/actions/types/manteca.types.ts (1)

6-50: Consider optional fields and string literal unions for stronger typing.

Backend may omit some fields (e.g., depositAlias, networks). Mark rarely-guaranteed properties as optional and narrow status, type, and stageType with unions to catch UI mismatches at compile time.

Example (illustrative):

-export type MantecaWithdrawResponseData = {
+export type MantecaWithdrawResponseData = {
@@
-    status: string
-    type: string
+    status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED'
+    type: 'WITHDRAW'
@@
-        depositAddress: string
-        depositAvailableNetworks: string[]
-        withdrawCostInAgainst: string
-        withdrawCostInAsset: string
-        price: string
-        priceExpireAt: string
+        depositAddress?: string
+        depositAvailableNetworks?: string[]
+        withdrawCostInAgainst?: string
+        withdrawCostInAsset?: string
+        price?: string
+        priceExpireAt?: string
src/components/Claim/Link/views/MantecaReviewStep.tsx (2)

39-46: Recipient misuse: you’re passing destinationAddress as both recipient and destination.

Per our payload fix in claimSendLink, recipient is ignored when destinationAddress is present. This call will work, but the first arg is misleading and risks future regressions.

-                const destinationAddress = withdrawDetails.stages[2].destination.address
-                await sendLinksApi.claim(destinationAddress, claimLink, destinationAddress)
+                const destinationAddress = withdrawDetails.stages[2].destination.address
+                // Pass a placeholder recipient for clarity; will be ignored server-side when destinationAddress is present
+                await sendLinksApi.claim('manteca', claimLink, destinationAddress)

If you prefer strictness, overload sendLinksApi.claim to accept an options object instead of positional args.


19-37: Guard against missing fields and format the rate.

Defensive access for nested fields and basic formatting avoids “undefined” in UI.

-            value: withdrawDetails?.stages[2].destination.address,
+            value: withdrawDetails?.stages?.[2]?.destination?.address ?? '-',
@@
-            value: `1 USD = ${withdrawDetails?.details.price} ARS`,
+            value: withdrawDetails?.details?.price
+                ? `1 USD = ${Number(withdrawDetails.details.price).toLocaleString()} ARS`
+                : '-',
src/components/Payment/Views/MantecaFulfuilment.view.tsx (1)

14-14: Rename component/file to “Fulfillment” (spelling).

Minor polish; reduces future grep mistakes.

-const MantecaFulfuilment = () => {
+const MantecaFulfillment = () => {
@@
-export default MantecaFulfuilment
+export default MantecaFulfillment

Also applies to: 109-109

src/app/actions/manteca.ts (1)

33-35: Trim noisy logs; rely on fetchWithSentry for error capture.

-            console.log('error', response)
             return { error: data.error || 'Failed to create manteca withdraw.' }
@@
-        console.log('error', error)
         console.error('Error calling create manteca withdraw API:', error)

Also applies to: 39-40

src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (2)

21-41: Add basic input validation and debounce submit.

Prevent empty/whitespace-only aliases and accidental double submits.

-    const createMantecaWithdraw = async () => {
+    const createMantecaWithdraw = async () => {
         setError(null)
-        setIsSubmitting(true)
+        const trimmed = destinationAddress.trim()
+        if (!trimmed) {
+            setError('Please enter a valid CVU or Alias.')
+            return
+        }
+        setIsSubmitting(true)
         const response = await mantecaWithdraw({
             amount,
-            destinationAddress,
+            destinationAddress: trimmed,
         })

47-55: Minor UX: disable Review button until input is non-empty after trim.

-                value={destinationAddress}
-                onChange={(e) => setDestinationAddress(e.target.value)}
+                value={destinationAddress}
+                onChange={(e) => setDestinationAddress(e.target.value)}
@@
-                disabled={!destinationAddress || isSubmitting}
+                disabled={!destinationAddress.trim() || isSubmitting}

Also applies to: 59-66

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a333a54 and 899e5f0.

📒 Files selected for processing (9)
  • src/app/actions/claimLinks.ts (2 hunks)
  • src/app/actions/manteca.ts (1 hunks)
  • src/app/actions/onramp.ts (4 hunks)
  • src/app/actions/types/manteca.types.ts (1 hunks)
  • src/components/Claim/Link/MantecaFlowManager.tsx (1 hunks)
  • src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (1 hunks)
  • src/components/Claim/Link/views/MantecaReviewStep.tsx (1 hunks)
  • src/components/Payment/Views/MantecaFulfuilment.view.tsx (1 hunks)
  • src/services/sendLinks.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/Claim/Link/MantecaFlowManager.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-12-11T10:13:22.806Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#564
File: src/components/Request/Pay/Views/Initial.view.tsx:430-430
Timestamp: 2024-12-11T10:13:22.806Z
Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.

Applied to files:

  • src/components/Claim/Link/views/MantecaDetailsStep.view.tsx
📚 Learning: 2025-04-30T21:31:27.790Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#827
File: src/components/Claim/Link/Initial.view.tsx:120-126
Timestamp: 2025-04-30T21:31:27.790Z
Learning: The `sendLinksApi.claim` function in the Peanut Protocol UI accepts both username and wallet address as the first parameter.

Applied to files:

  • src/services/sendLinks.ts
  • src/app/actions/claimLinks.ts
🧬 Code graph analysis (5)
src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (4)
src/app/actions/types/manteca.types.ts (1)
  • MantecaWithdrawResponseData (6-50)
src/app/actions/manteca.ts (1)
  • mantecaWithdraw (9-46)
src/components/Global/Icons/Icon.tsx (1)
  • Icon (195-204)
src/components/0_Bruddle/Button.tsx (1)
  • Button (76-267)
src/services/sendLinks.ts (1)
src/app/actions/claimLinks.ts (1)
  • claimSendLink (85-102)
src/app/actions/manteca.ts (2)
src/app/actions/types/manteca.types.ts (2)
  • MantecaWithdrawData (1-4)
  • MantecaWithdrawResponse (52-55)
src/utils/sentry.utils.ts (1)
  • fetchWithSentry (26-104)
src/components/Claim/Link/views/MantecaReviewStep.tsx (4)
src/app/actions/types/manteca.types.ts (1)
  • MantecaWithdrawResponseData (6-50)
src/components/Global/MantecaDetailsCard/index.tsx (1)
  • MantecaCardRow (5-7)
src/services/sendLinks.ts (1)
  • sendLinksApi (88-229)
src/components/0_Bruddle/Button.tsx (1)
  • Button (76-267)
src/components/Payment/Views/MantecaFulfuilment.view.tsx (5)
src/context/RequestFulfillmentFlowContext.tsx (1)
  • useRequestFulfillmentFlow (109-115)
src/redux/hooks.ts (1)
  • usePaymentStore (12-12)
src/app/actions/onramp.ts (1)
  • createMantecaOnramp (123-167)
src/components/Global/PeanutLoading/index.tsx (1)
  • PeanutLoading (4-19)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
  • PeanutActionDetailsCard (55-256)
🔇 Additional comments (1)
src/services/sendLinks.ts (1)

203-207: Verify call sites still pass a valid recipient for non-Manteca claims

Attempted repo scan failed in the verification environment (ripgrep: "No files were searched"). Run these locally and confirm every call site supplies a non-empty/appropriate recipient for non-Manteca flows.

Run locally:

rg -nC3 --hidden --no-ignore --glob '!node_modules/**' --glob '!dist/**' '\b(sendLinksApi\.claim|claimSendLink)\s*\('
# fallbacks
git grep -n "sendLinksApi.claim" || true
git grep -n "claimSendLink" || true

File to inspect: src/services/sendLinks.ts (claim at ~lines 203-207).

…lity and improve rendering of account details
@Zishan-7 Zishan-7 marked this pull request as ready for review September 12, 2025 14:53
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

♻️ Duplicate comments (2)
src/components/Payment/Views/MantecaFulfuilment.view.tsx (2)

17-28: Gating looks good; tighten queryKey to avoid undefined in cache keys.

You added enabled, great. Also avoid undefined in keys for cleaner caches.

-        queryKey: ['manteca-deposit', chargeDetails?.uuid],
+        queryKey: chargeDetails?.uuid ? ['manteca-deposit', chargeDetails.uuid] : ['manteca-deposit'],

12-12: Unify rows and share text; avoid “undefined” lines and drop unnecessary async.

Build rows once (memoized), feed both the card and share text, and pass the sync function to ShareButton.

-import React from 'react'
+import React, { useMemo } from 'react'

-    const generateShareText = () => {
-        const textParts = []
-        textParts.push(`CBU: ${depositData?.data?.depositAddress}`)
-        textParts.push(`Alias: ${depositData?.data?.depositAlias}`)
-
-        return textParts.join('\n')
-    }
+    const rows = useMemo(
+        () => [
+            ...(depositData?.data?.depositAddress
+                ? [
+                      {
+                          key: 'cbu',
+                          label: 'CBU',
+                          value: depositData.data.depositAddress,
+                          allowCopy: true,
+                      },
+                  ]
+                : []),
+            ...(depositData?.data?.depositAlias
+                ? [
+                      {
+                          key: 'alias',
+                          label: 'Alias',
+                          value: depositData.data.depositAlias,
+                          hideBottomBorder: true,
+                      },
+                  ]
+                : []),
+        ],
+        [depositData?.data?.depositAddress, depositData?.data?.depositAlias]
+    )
+
+    const generateShareText = () =>
+        rows.map(({ label, value }) => `${label}: ${String(value ?? '')}`).join('\n')

-                        <MantecaDetailsCard
-                            rows={[
-                                ...(depositData?.data?.depositAddress
-                                    ? [
-                                          {
-                                              key: 'cbu',
-                                              label: 'CBU',
-                                              value: depositData.data.depositAddress,
-                                              allowCopy: true,
-                                          },
-                                      ]
-                                    : []),
-                                ...(depositData?.data?.depositAlias
-                                    ? [
-                                          {
-                                              key: 'alias',
-                                              label: 'Alias',
-                                              value: depositData.data.depositAlias,
-                                              hideBottomBorder: true,
-                                          },
-                                      ]
-                                    : []),
-                            ]}
-                        />
+                        <MantecaDetailsCard rows={rows} />

-                        <ShareButton
-                            generateText={async () => generateShareText()}
+                        <ShareButton
+                            generateText={generateShareText}

Also applies to: 30-36, 70-93, 95-101

🧹 Nitpick comments (3)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)

115-115: Use renderRecipient() for address recipients.

If REGIONAL_METHOD_CLAIM ever carries an ADDRESS recipient, renderRecipient() will trim/format it consistently.

-        if (transactionType === 'REGIONAL_METHOD_CLAIM') title = recipientName // Render the string as is for regional method
+        if (transactionType === 'REGIONAL_METHOD_CLAIM') title = renderRecipient()
src/components/Payment/Views/MantecaFulfuilment.view.tsx (2)

26-26: Double-check Infinity staleTime vs. deposit address TTL.

If Manteca deposit details can expire/change, staleTime: Infinity risks showing stale data. Consider a finite staleTime or explicit invalidation when chargeId/amount changes.


14-14: Rename: “Fulfuilment” → “Fulfilment” (or “Fulfillment”).

Typo in component and file name hurts discoverability. Prefer MantecaFulfilment.view.tsx and MantecaFulfilment to match setFulfilUsingManteca.

-const MantecaFulfuilment = () => {
+const MantecaFulfilment = () => {
...
-export default MantecaFulfuilment
+export default MantecaFulfilment

Follow-up: rename the file and update imports.

Also applies to: 110-110

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 899e5f0 and c7e8c4c.

📒 Files selected for processing (6)
  • src/components/AddMoney/components/MantecaDepositCard.tsx (2 hunks)
  • src/components/Claim/Link/MantecaFlowManager.tsx (1 hunks)
  • src/components/Global/MantecaDetailsCard/index.tsx (1 hunks)
  • src/components/Global/PeanutActionDetailsCard/index.tsx (6 hunks)
  • src/components/Payment/Views/MantecaFulfuilment.view.tsx (1 hunks)
  • src/components/Profile/AvatarWithBadge.tsx (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/components/AddMoney/components/MantecaDepositCard.tsx
  • src/components/Claim/Link/MantecaFlowManager.tsx
  • src/components/Profile/AvatarWithBadge.tsx
  • src/components/Global/MantecaDetailsCard/index.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-18T19:56:55.443Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#919
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:87-87
Timestamp: 2025-06-18T19:56:55.443Z
Learning: In withdraw flows for Peanut Wallet, the PeanutActionDetailsCard should always display "USDC" as the token symbol because it shows the amount being withdrawn from the Peanut Wallet (which holds USDC), regardless of the destination token/chain selected by the user. The TokenSelector is used for choosing the withdrawal destination, not the source display.

Applied to files:

  • src/components/Global/PeanutActionDetailsCard/index.tsx
🧬 Code graph analysis (1)
src/components/Payment/Views/MantecaFulfuilment.view.tsx (5)
src/context/RequestFulfillmentFlowContext.tsx (1)
  • useRequestFulfillmentFlow (109-115)
src/redux/hooks.ts (1)
  • usePaymentStore (12-12)
src/app/actions/onramp.ts (1)
  • createMantecaOnramp (123-167)
src/components/Global/PeanutLoading/index.tsx (1)
  • PeanutLoading (4-19)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
  • PeanutActionDetailsCard (54-255)
🔇 Additional comments (4)
src/components/Global/PeanutActionDetailsCard/index.tsx (4)

12-12: Type-only import for StaticImageData is correct.

This avoids a runtime import from next/image. LGTM.


88-94: Icon mapping for REGIONAL_METHOD_CLAIM looks consistent with outflow.

Mapping to arrow-up matches WITHDRAW/WITHDRAW_BANK_ACCOUNT. LGTM.


206-206: AvatarWithBadge — logo prop is StaticImageData-only and renders as an image (no initials/icon clash).

AvatarWithBadge.tsx types logo as StaticImageData and, when provided, returns an Image-only avatar; PeanutActionDetailsCard.logo is also StaticImageData — safe to pass through. Optional cleanup: remove the unreachable {logo && <Image .../>} inside the non-logo return in src/components/Profile/AvatarWithBadge.tsx.


25-25: Handle REGIONAL_METHOD_CLAIM in amount formatting and avatar helpers

getIcon/getTitle already include REGIONAL_METHOD_CLAIM, but the amount prefix/suffix and avatar color/text logic do not — update as follows:

  • src/components/Global/PeanutActionDetailsCard/index.tsx (h2 amount block ~lines 199–237): include transactionType === 'REGIONAL_METHOD_CLAIM' in the prefix condition that uses currencySymbol, and suppress the token suffix for REGIONAL_METHOD_CLAIM (add/exclude it from the token-label conditional).
  • src/components/Global/PeanutActionDetailsCard/index.tsx (getAvatarBackgroundColor / getAvatarTextColor ~lines 136–150): add transactionType === 'REGIONAL_METHOD_CLAIM' to the OR-list that returns '#FFC900' and AVATAR_TEXT_DARK so regional/fiat claims use the bank/add styling.

Rationale: regional/fiat claims should show currencySymbol (not a token suffix); withdraw-like flows should continue to reflect Peanut Wallet denomination (USDC) where appropriate.

⛔ Skipped due to learnings
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#919
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:87-87
Timestamp: 2025-06-18T19:56:55.443Z
Learning: In withdraw flows for Peanut Wallet, the PeanutActionDetailsCard should always display "USDC" as the token symbol because it shows the amount being withdrawn from the Peanut Wallet (which holds USDC), regardless of the destination token/chain selected by the user. The TokenSelector is used for choosing the withdrawal destination, not the source display.

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.

Check comments for requested changes.

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 (1)
src/components/Claim/Link/MantecaFlowManager.tsx (1)

49-51: Success CTA wired — looks good.

🧹 Nitpick comments (6)
src/app/[...recipient]/client.tsx (2)

396-399: ActionList gating ignores Manteca flag for non-direct_pay.

As written, ActionList will still render for any non-direct_pay flow even when fulfillUsingManteca is true. If the intent is “always hide ActionList while in Manteca flow,” invert the condition and also use the logged‑in flag consistently.

Apply:

-const showActionList =
-    flow !== 'direct_pay' || // Always show for non-direct-pay flows
-    (flow === 'direct_pay' && !user) || // Show for direct-pay when user is not logged in
-    !fulfillUsingManteca // Show when not fulfilling using Manteca
+const isLoggedIn = !!user?.user?.userId
+const showActionList =
+  !fulfillUsingManteca && (flow !== 'direct_pay' || (flow === 'direct_pay' && !isLoggedIn))

71-72: Name drift: fulfil(l)UsingManteca vs fulfillUsingManteca — align with context API.

Double-check the property name exported by RequestFulfillmentFlowContext; I see mixed spellings across the PR. A mismatch will break destructuring.

Run to verify and normalize the spelling:

#!/bin/bash
rg -nP --type=ts -C2 '\bfulfil[l]?UsingManteca\b|\bfulfillUsingManteca\b|setFulfil[l]?UsingManteca|setFulfillUsingManteca'
src/components/Payment/Views/MantecaFulfuillment.view.tsx (3)

18-19: Key the query by amount to avoid reusing stale deposit details.

If amount changes while UUID stays the same, the query won’t refetch.

Apply:

-        queryKey: ['manteca-deposit', chargeDetails?.uuid],
+        queryKey: ['manteca-deposit', chargeDetails?.uuid, usdAmount],

30-36: Guard missing alias in share text.

Avoid “Alias: undefined” when alias is absent.

Apply:

-    const generateShareText = () => {
-        const textParts = []
-        textParts.push(`CBU: ${depositData?.data?.depositAddress}`)
-        textParts.push(`Alias: ${depositData?.data?.depositAlias}`)
-        return textParts.join('\n')
-    }
+    const generateShareText = () => {
+        const parts: string[] = []
+        if (depositData?.data?.depositAddress) parts.push(`CBU: ${depositData.data.depositAddress}`)
+        if (depositData?.data?.depositAlias) parts.push(`Alias: ${depositData.data.depositAlias}`)
+        return parts.join('\n')
+    }

14-15: Typo: “Fulfuillment” → “Fulfillment”.

Rename the component and file to the correct spelling to prevent future import mistakes.

Apply in this file:

-const MantecaFulfuillment = () => {
+const MantecaFulfillment = () => {
...
-export default MantecaFulfuillment
+export default MantecaFulfillment

Update imports across the repo:

#!/bin/bash
rg -n "MantecaFulfuillment" -g '!**/dist/**' -g '!**/build/**'

Also applies to: 110-110

src/types/manteca.types.ts (1)

18-62: Model stages more readably.

Numeric keys work but are awkward to access. Consider a discriminated union or a typed Record for clarity.

Example:

-export type MantecaWithdrawResponseData = {
+export type MantecaWithdrawResponseData = {
   // ...
-  stages: {
-      1: { /* stage 1 */ }
-      2: { /* stage 2 */ }
-  }
+  stages: Record<
+    1 | 2,
+    | {
+        stageType: string
+        side: string
+        type: string
+        asset: string
+        against: string
+        assetAmount: string
+        price: string
+        priceCode: string
+      }
+    | {
+        stageType: string
+        asset: string
+        amount: string
+        to: string
+        destination: { address: string; bankCode: string }
+      }
+  >
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c7e8c4c and 7eb03c6.

📒 Files selected for processing (13)
  • src/app/[...recipient]/client.tsx (2 hunks)
  • src/app/actions/manteca.ts (1 hunks)
  • src/app/actions/onramp.ts (3 hunks)
  • src/components/Claim/Link/Initial.view.tsx (3 hunks)
  • src/components/Claim/Link/MantecaFlowManager.tsx (1 hunks)
  • src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (1 hunks)
  • src/components/Claim/Link/views/MantecaReviewStep.tsx (1 hunks)
  • src/components/Common/ActionList.tsx (4 hunks)
  • src/components/Payment/PaymentForm/index.tsx (3 hunks)
  • src/components/Payment/Views/MantecaFulfuillment.view.tsx (1 hunks)
  • src/context/RequestFulfillmentFlowContext.tsx (5 hunks)
  • src/services/sendLinks.ts (1 hunks)
  • src/types/manteca.types.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/services/sendLinks.ts
  • src/components/Claim/Link/views/MantecaDetailsStep.view.tsx
  • src/components/Claim/Link/Initial.view.tsx
  • src/components/Common/ActionList.tsx
  • src/components/Claim/Link/views/MantecaReviewStep.tsx
  • src/app/actions/manteca.ts
  • src/components/Payment/PaymentForm/index.tsx
  • src/app/actions/onramp.ts
  • src/context/RequestFulfillmentFlowContext.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-05T07:31:11.396Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1185
File: src/components/Claim/useClaimLink.tsx:14-0
Timestamp: 2025-09-05T07:31:11.396Z
Learning: In the peanut-ui codebase, `window.history.replaceState` is preferred over `router.replace` when immediate/synchronous URL parameter updates are required, as `router.replace` is asynchronous and doesn't guarantee instant URL changes that subsequent code can rely on. This pattern is used consistently across usePaymentInitiator.ts, Confirm.payment.view.tsx, and useClaimLink.tsx.

Applied to files:

  • src/components/Claim/Link/MantecaFlowManager.tsx
🧬 Code graph analysis (2)
src/components/Payment/Views/MantecaFulfuillment.view.tsx (5)
src/context/RequestFulfillmentFlowContext.tsx (1)
  • useRequestFulfillmentFlow (109-115)
src/redux/hooks.ts (1)
  • usePaymentStore (12-12)
src/app/actions/onramp.ts (1)
  • createMantecaOnramp (123-166)
src/components/Global/PeanutLoading/index.tsx (1)
  • PeanutLoading (4-19)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
  • PeanutActionDetailsCard (54-255)
src/components/Claim/Link/MantecaFlowManager.tsx (4)
src/services/sendLinks.ts (1)
  • ClaimLinkData (62-62)
src/context/ClaimBankFlowContext.tsx (1)
  • useClaimBankFlow (143-149)
src/types/manteca.types.ts (1)
  • MantecaWithdrawResponseData (18-62)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
  • PeanutActionDetailsCard (54-255)

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/services/manteca.ts (1)

136-142: Critical: API key exposed in client bundle — move getPrices to a server-only module.

This file is consumed by client components, and getPrices sends the secret PEANUT_API_KEY in a header. This risks leaking the key to the browser. Split getPrices into a server-only module and remove the PEANUT_API_KEY import from this client service.

Apply:

- import { PEANUT_API_URL, PEANUT_API_KEY } from '@/constants'
+ import { PEANUT_API_URL } from '@/constants'
-    getPrices: async ({ asset, against }: { asset: string; against: string }): Promise<MantecaPrice> => {
-        const response = await fetchWithSentry(`${PEANUT_API_URL}/manteca/prices?asset=${asset}&against=${against}`, {
-            headers: {
-                'Content-Type': 'application/json',
-                'api-key': PEANUT_API_KEY,
-            },
-        })
-
-        if (!response.ok) {
-            const errorData = await response.json().catch(() => ({}))
-            throw new Error(errorData.message || `Get prices failed: ${response.statusText}`)
-        }
-
-        return response.json()
-    },

Server-only addition (new file, example):

// src/app/actions/manteca.ts
'use server'

import { PEANUT_API_URL, PEANUT_API_KEY } from '@/constants'
import { fetchWithSentry } from '@/utils'
import { MantecaPrice } from '@/types/manteca.types'

export async function getMantecaPrices({ asset, against }: { asset: string; against: string }): Promise<MantecaPrice> {
  const res = await fetchWithSentry(`${PEANUT_API_URL}/manteca/prices?asset=${asset}&against=${against}`, {
    headers: { 'Content-Type': 'application/json', 'api-key': PEANUT_API_KEY },
    cache: 'no-store',
  })
  if (!res.ok) throw new Error(`Get prices failed: ${res.statusText}`)
  return res.json()
}

Also move type MantecaPrice to src/types/manteca.types.ts and import it in the server file to avoid coupling back to this client module.

Also applies to: 1-1

♻️ Duplicate comments (2)
src/components/Claim/Link/MantecaFlowManager.tsx (1)

1-1: Good fixes: marked as client component and wired Success CTA.

"use client" added and "Back to home" now navigates. LGTM.

Also applies to: 50-55

src/components/Payment/Views/MantecaFulfuillment.view.tsx (1)

20-28: Wrong unit: pass USD amount to deposit, not token amount.

createMantecaOnramp expects usdAmount; sending tokenAmount yields incorrect ARS instructions.

Apply:

-    const { requestDetails, chargeDetails } = usePaymentStore()
+    const { requestDetails, chargeDetails, usdAmount } = usePaymentStore()
...
-            mantecaApi.deposit({
-                usdAmount: requestDetails?.tokenAmount || chargeDetails?.tokenAmount || '0',
+            mantecaApi.deposit({
+                usdAmount: (usdAmount ?? '0').toString(),
                 currency: 'ARS',
                 chargeId: chargeDetails?.uuid,
             }),
-        refetchOnWindowFocus: false,
-        staleTime: Infinity, // don't refetch the data
-        enabled: Boolean(chargeDetails?.uuid),
+        refetchOnWindowFocus: false,
+        staleTime: 60_000, // ephemeral
+        enabled: Boolean(chargeDetails?.uuid && usdAmount),
🧹 Nitpick comments (7)
src/constants/manteca.consts.ts (1)

1-1: Avoid hard‑coding a single deposit address; type it and scope by env.

If this varies across environments (staging/prod) or chains, hard‑coding risks misroutes. Also, type as Address for compile‑time checks.

Apply:

+import type { Address } from 'viem'
-export const MANTECA_DEPOSIT_ADDRESS = '0x959e088a09f61aB01cb83b0eBCc74b2CF6d62053'
+export const MANTECA_DEPOSIT_ADDRESS: Address = '0x959e088a09f61aB01cb83b0eBCc74b2CF6d62053'
+
+// Optional: env‑scoped map
+export const MANTECA_DEPOSIT_ADDRESS_BY_ENV = {
+  production: '0x959e088a09f61aB01cb83b0eBCc74b2CF6d62053',
+  staging: '0x0000000000000000000000000000000000000000',
+  development: '0x0000000000000000000000000000000000000000',
+} as const

Would you like me to wire a getMantecaDepositAddress() helper that picks by process.env.NEXT_PUBLIC_RUNTIME_ENV?

src/components/Claim/Link/views/MantecaReviewStep.tsx (1)

32-35: Guard exchange rate rendering to avoid “undefined” in UI.

If price is null after a fetch error, the row shows undefined. Provide a fallback.

-      value: `1 USD = ${price?.buy} ARS`,
+      value: price ? `1 USD = ${price.buy.toLocaleString('en-US', { maximumFractionDigits: 2 })} ARS` : '—',
src/components/AddMoney/components/RegionalMethods/MercadoPago/index.tsx (1)

29-41: Validate USD amount and handle optional chargeId.

Send a normalized, positive numeric usdAmount and fail fast; also ensure chargeId is optional server‑side.

   const handleAmountSubmit = async () => {
     if (!selectedCountry?.currency) return
     if (isCreatingDeposit) return

     try {
       setError(null)
       setIsCreatingDeposit(true)
-      const depositData = await mantecaApi.deposit({
-          usdAmount: tokenUSDAmount.replace(/,/g, ''),
+      const usdAmount = tokenUSDAmount.replace(/,/g, '').trim()
+      if (!usdAmount || isNaN(Number(usdAmount)) || Number(usdAmount) <= 0) {
+        setError('Enter a valid amount in USD.')
+        return
+      }
+      const depositData = await mantecaApi.deposit({
+          usdAmount,
           currency: selectedCountry.currency,
-      })
+          // chargeId: ..., // if required by backend
+      })
       if (depositData.error) {
         setError(depositData.error)
         return
       }
-      setDepositDetails(depositData.data)
+      if (!depositData.data) {
+        setError('Missing deposit details.')
+        return
+      }
+      setDepositDetails(depositData.data)
       setStep('depositDetails')

If backend requires chargeId, point me to the source and I’ll thread it through.

src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (1)

20-22: Remove unnecessary async and trim before advancing.

Slight cleanup and robustness on empty/whitespace input.

-    const handleOnClick = async () => {
-        setCurrentStep(MercadoPagoStep.REVIEW)
-    }
+    const handleOnClick = () => {
+        const normalized = destinationAddress.trim()
+        if (!normalized) return
+        setDestinationAddress(normalized)
+        setCurrentStep(MercadoPagoStep.REVIEW)
+    }
@@
-            <Button disabled={!destinationAddress} onClick={() => handleOnClick()} shadowSize="4">
+            <Button disabled={!destinationAddress.trim()} onClick={handleOnClick} shadowSize="4">

Also applies to: 38-40

src/services/manteca.ts (1)

152-182: Harden error handling; avoid console noise; guard missing JWT.

  • Parse error payload robustly (json or text).
  • Remove console.log (Sentry already captures).
  • If jwt-token is missing, return a typed error early.
-    deposit: async (params: CreateMantecaOnrampParams): Promise<{ data?: MantecaDepositDetails; error?: string }> => {
+    deposit: async (params: CreateMantecaOnrampParams): Promise<{ data?: MantecaDepositDetails; error?: string }> => {
         try {
-            const response = await fetchWithSentry(`${PEANUT_API_URL}/manteca/deposit`, {
+            const token = Cookies.get('jwt-token')
+            if (!token) return { error: 'Not authenticated.' }
+            const response = await fetchWithSentry(`${PEANUT_API_URL}/manteca/deposit`, {
                 method: 'POST',
                 headers: {
                     'Content-Type': 'application/json',
-                    Authorization: `Bearer ${Cookies.get('jwt-token')}`,
+                    Authorization: `Bearer ${token}`,
                 },
                 body: JSON.stringify({
                     usdAmount: params.usdAmount,
                     currency: params.currency,
                     chargeId: params.chargeId,
                 }),
             })
-
-            const data = await response.json()
-
-            if (!response.ok) {
-                console.log('error', response)
-                return { error: data.error || 'Failed to create on-ramp transfer for guest.' }
-            }
-
-            return { data }
+            let parsed: any
+            try { parsed = await response.clone().json() } catch { parsed = await response.text() }
+            if (!response.ok) {
+                const msg = typeof parsed === 'string' ? parsed : (parsed?.error || parsed?.message) || 'Failed to create on-ramp transfer for guest.'
+                return { error: msg }
+            }
+            return { data: parsed }
         } catch (error) {
-            console.log('error', error)
             console.error('Error calling create manteca on-ramp API:', error)
             if (error instanceof Error) {
                 return { error: error.message }
             }
             return { error: 'An unexpected error occurred.' }
         }
     },
src/components/Payment/Views/MantecaFulfuillment.view.tsx (1)

30-36: Include amount in share text (useful to the payer).

     const generateShareText = () => {
         const textParts = []
         textParts.push(`CBU: ${depositData?.data?.depositAddress}`)
         textParts.push(`Alias: ${depositData?.data?.depositAlias}`)
+        if (depositData?.data?.depositAmount) textParts.push(`Amount: ${depositData.data.depositAmount}`)
         return textParts.join('\n')
     }
src/types/manteca.types.ts (1)

13-18: Types look consistent with responses, but consider relocating MantecaPrice here.

Move MantecaPrice from services to this types file so both server/client code can share it without importing client modules.

// Add here:
export type MantecaPrice = {
  ticker: string
  buy: string
  sell: string
  timestamp: string
  variation: { buy: { realtime: string; daily: string }; sell: { realtime: string; daily: string } }
  effectiveBuy: string
  effectiveSell: string
}

Also applies to: 20-69

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7eb03c6 and b71d7db.

📒 Files selected for processing (11)
  • src/app/actions/onramp.ts (0 hunks)
  • src/components/AddMoney/components/RegionalMethods/MercadoPago/index.tsx (2 hunks)
  • src/components/Claim/Link/MantecaFlowManager.tsx (1 hunks)
  • src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (1 hunks)
  • src/components/Claim/Link/views/MantecaReviewStep.tsx (1 hunks)
  • src/components/Payment/Views/MantecaFulfuillment.view.tsx (1 hunks)
  • src/constants/index.ts (1 hunks)
  • src/constants/manteca.consts.ts (1 hunks)
  • src/services/manteca.ts (2 hunks)
  • src/services/sendLinks.ts (1 hunks)
  • src/types/manteca.types.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • src/app/actions/onramp.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/services/sendLinks.ts
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-09-15T16:22:58.354Z
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#1190
File: src/services/manteca.ts:1-1
Timestamp: 2025-09-15T16:22:58.354Z
Learning: In the manteca service, PEANUT_API_KEY should not be imported in a module that's used by client-side components. The getPrices function that requires the API key should be moved to a server-only module to prevent exposing secrets in the client bundle.

Applied to files:

  • src/services/manteca.ts
📚 Learning: 2025-09-05T07:31:11.396Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1185
File: src/components/Claim/useClaimLink.tsx:14-0
Timestamp: 2025-09-05T07:31:11.396Z
Learning: In the peanut-ui codebase, `window.history.replaceState` is preferred over `router.replace` when immediate/synchronous URL parameter updates are required, as `router.replace` is asynchronous and doesn't guarantee instant URL changes that subsequent code can rely on. This pattern is used consistently across usePaymentInitiator.ts, Confirm.payment.view.tsx, and useClaimLink.tsx.

Applied to files:

  • src/components/Claim/Link/MantecaFlowManager.tsx
📚 Learning: 2024-10-07T13:42:00.443Z
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-07T13:42:00.443Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.

Applied to files:

  • src/components/Payment/Views/MantecaFulfuillment.view.tsx
📚 Learning: 2024-10-07T15:28:25.280Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:28:25.280Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.

Applied to files:

  • src/components/Payment/Views/MantecaFulfuillment.view.tsx
📚 Learning: 2024-10-07T15:25:45.170Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:25:45.170Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(...)` return strings, ensuring that `calculatedFee` consistently returns a string without the need for additional type conversion.

Applied to files:

  • src/components/Payment/Views/MantecaFulfuillment.view.tsx
📚 Learning: 2024-12-11T10:13:22.806Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#564
File: src/components/Request/Pay/Views/Initial.view.tsx:430-430
Timestamp: 2024-12-11T10:13:22.806Z
Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.

Applied to files:

  • src/components/Payment/Views/MantecaFulfuillment.view.tsx
📚 Learning: 2024-10-04T13:10:49.199Z
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#413
File: src/components/Request/Pay/Views/Initial.view.tsx:71-72
Timestamp: 2024-10-04T13:10:49.199Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, it's acceptable to use the `!` operator in TypeScript to assert that `selectedTokenData` is not `null` or `undefined`, and potential runtime errors from accessing its properties without checks can be disregarded.

Applied to files:

  • src/components/Payment/Views/MantecaFulfuillment.view.tsx
🧬 Code graph analysis (6)
src/components/AddMoney/components/RegionalMethods/MercadoPago/index.tsx (1)
src/services/manteca.ts (1)
  • mantecaApi (95-211)
src/services/manteca.ts (3)
src/types/manteca.types.ts (4)
  • CreateMantecaOnrampParams (71-75)
  • MantecaDepositDetails (1-5)
  • MantecaWithdrawData (13-18)
  • MantecaWithdrawResponse (66-69)
src/utils/sentry.utils.ts (1)
  • fetchWithSentry (26-104)
src/constants/general.consts.ts (1)
  • PEANUT_API_URL (43-47)
src/components/Claim/Link/MantecaFlowManager.tsx (4)
src/services/sendLinks.ts (1)
  • ClaimLinkData (62-62)
src/context/ClaimBankFlowContext.tsx (1)
  • useClaimBankFlow (143-149)
src/components/0_Bruddle/Button.tsx (1)
  • Button (76-267)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
  • PeanutActionDetailsCard (54-255)
src/components/Claim/Link/views/MantecaReviewStep.tsx (6)
src/hooks/useCurrency.ts (1)
  • useCurrency (21-65)
src/components/Global/MantecaDetailsCard/index.tsx (1)
  • MantecaCardRow (5-7)
src/services/sendLinks.ts (1)
  • sendLinksApi (88-264)
src/constants/manteca.consts.ts (1)
  • MANTECA_DEPOSIT_ADDRESS (1-1)
src/services/manteca.ts (1)
  • mantecaApi (95-211)
src/components/Global/PeanutLoading/index.tsx (1)
  • PeanutLoading (4-19)
src/components/Claim/Link/views/MantecaDetailsStep.view.tsx (2)
src/components/Global/Icons/Icon.tsx (1)
  • Icon (196-205)
src/components/0_Bruddle/Button.tsx (1)
  • Button (76-267)
src/components/Payment/Views/MantecaFulfuillment.view.tsx (5)
src/context/RequestFulfillmentFlowContext.tsx (1)
  • useRequestFulfillmentFlow (109-115)
src/redux/hooks.ts (1)
  • usePaymentStore (12-12)
src/services/manteca.ts (1)
  • mantecaApi (95-211)
src/components/Global/PeanutLoading/index.tsx (1)
  • PeanutLoading (4-19)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
  • PeanutActionDetailsCard (54-255)
🔇 Additional comments (4)
src/constants/index.ts (1)

7-7: LGTM: barrel re‑export keeps constants discoverable.

src/components/Claim/Link/views/MantecaReviewStep.tsx (1)

47-53: Confirm claim(recipient, link) semantics and env‑correct recipient.

Double‑check that passing MANTECA_DEPOSIT_ADDRESS as the “recipient” is intended for this flow and correct for the current environment.

Would you like me to add a small guard that logs and blocks if MANTECA_DEPOSIT_ADDRESS is the zero address or mismatched for env?

src/types/manteca.types.ts (1)

7-11: Enum looks good.

src/services/manteca.ts (1)

185-210: Align withdraw response shape; add JWT guard and consistent error parsing.

Return the parsed payload under data (unwrap parsed.data if present); add a JWT guard (reuse a single token variable) and robust error parsing (try JSON, fall back to text) so withdraw mirrors deposit behavior.

  • Implement:
    • Guard JWT: const token = Cookies.get('jwt-token'); if (!token) return { error: 'Not authenticated.' } and use Authorization: \Bearer ${token}``.
    • Parse & normalize: try parsed = await response.clone().json() else parsed = await response.text(); on !response.ok return { error: typeof parsed === 'string' ? parsed : parsed?.error ?? parsed?.message ?? 'Failed to create manteca withdraw.' }.
    • Return normalized payload: return { data: parsed?.data ?? parsed }.

Verification: sandbox search failed (ripgrep skipped files). Run these locally to ensure no callers expect data.data:

rg -n --hidden -S -C2 'mantecaApi.withdraw(' --glob '!/node_modules/' || true
rg -n --hidden -S -C2 '\bmantecaApi\b' --glob '!/node_modules/' || true
rg -n --hidden -S -C2 '\bdata?.data\b|\bdata.data\b' --glob '!/node_modules/' || true

Fallback (git grep):
git grep -n "mantecaApi.withdraw(" || true
git grep -n "data.data" || true

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/Claim/Link/views/MantecaReviewStep.tsx (1)

48-64: Good fix: validate txHash and only show success on confirmed withdraw.

You now gate on a non-empty txHash and check { data, withdrawError } before advancing. This addresses the earlier failure-path issue.

🧹 Nitpick comments (3)
src/components/Claim/Link/views/MantecaReviewStep.tsx (3)

24-42: Hide exchange rate until available; avoid “undefined” and format nicely.

If price is null after load, UI shows “1 USD = undefined ARS”. Only render the row when available and format with locale.

-    const detailsCardRows: MantecaCardRow[] = [
-        {
-            key: 'alias',
-            label: 'Alias',
-            value: destinationAddress,
-            allowCopy: true,
-        },
-        {
-            key: 'exchangeRate',
-            label: 'Exchange Rate',
-            value: `1 USD = ${price?.buy} ARS`,
-        },
-        {
-            key: 'fee',
-            label: 'Fee',
-            value: 'Sponsored by Peanut',
-            hideBottomBorder: true,
-        },
-    ]
+    const detailsCardRows: MantecaCardRow[] = [
+        {
+            key: 'alias',
+            label: 'Alias',
+            value: destinationAddress.trim(),
+            allowCopy: true,
+        },
+        ...(price?.buy
+            ? [
+                  {
+                      key: 'exchangeRate' as const,
+                      label: 'Exchange Rate',
+                      value: `1 USD = ${price.buy.toLocaleString('es-AR', { maximumFractionDigits: 2 })} ARS`,
+                  },
+              ]
+            : []),
+        {
+            key: 'fee',
+            label: 'Fee',
+            value: 'Sponsored by Peanut',
+            hideBottomBorder: true,
+        },
+    ]

83-85: Disable Withdraw when alias is blank.

Prevents submissions with empty/whitespace alias.

-            <Button disabled={isSubmitting} loading={isSubmitting} shadowSize="4" onClick={handleWithdraw}>
+            <Button
+                disabled={isSubmitting || !destinationAddress.trim()}
+                loading={isSubmitting}
+                shadowSize="4"
+                onClick={handleWithdraw}
+            >

74-76: Optional: avoid full-screen loader for a non-critical exchange rate.

Consider keeping the review UI visible and rendering a skeleton/placeholder for the rate instead of blocking the screen.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b71d7db and d6dd05f.

📒 Files selected for processing (1)
  • src/components/Claim/Link/views/MantecaReviewStep.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2024-11-18T21:36:11.486Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.

Applied to files:

  • src/components/Claim/Link/views/MantecaReviewStep.tsx
📚 Learning: 2024-10-08T20:13:42.967Z
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:113-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `PayRequestLink` component (`src/components/Request/Pay/Pay.tsx`), when resolving ENS names, handle errors by displaying an appropriate error message to the user if the ENS cannot be resolved.

Applied to files:

  • src/components/Claim/Link/views/MantecaReviewStep.tsx
📚 Learning: 2024-10-23T09:38:27.670Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#469
File: src/app/request/pay/page.tsx:32-64
Timestamp: 2024-10-23T09:38:27.670Z
Learning: In `src/app/request/pay/page.tsx`, if `linkRes` is not OK in the `generateMetadata` function, the desired behavior is to use the standard title and preview image without throwing an error.

Applied to files:

  • src/components/Claim/Link/views/MantecaReviewStep.tsx
📚 Learning: 2025-08-26T15:25:53.328Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.328Z
Learning: In `src/components/Common/ActionListDaimoPayButton.tsx`, the `handleCompleteDaimoPayment` function should not display error messages to users when DB update fails because the Daimo payment itself has succeeded - showing errors would be confusing since the payment was successful.

Applied to files:

  • src/components/Claim/Link/views/MantecaReviewStep.tsx
📚 Learning: 2024-12-11T10:13:22.806Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#564
File: src/components/Request/Pay/Views/Initial.view.tsx:430-430
Timestamp: 2024-12-11T10:13:22.806Z
Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.

Applied to files:

  • src/components/Claim/Link/views/MantecaReviewStep.tsx
📚 Learning: 2024-10-25T11:33:46.776Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#484
File: src/components/Cashout/Components/Initial.view.tsx:273-274
Timestamp: 2024-10-25T11:33:46.776Z
Learning: In the `InitialCashoutView` component (`src/components/Cashout/Components/Initial.view.tsx`), linked bank accounts should not generate error states, and the `ValidatedInput` component will clear any error messages if needed. Therefore, it's unnecessary to manually clear the error state when selecting or clearing linked bank accounts.

Applied to files:

  • src/components/Claim/Link/views/MantecaReviewStep.tsx
🧬 Code graph analysis (1)
src/components/Claim/Link/views/MantecaReviewStep.tsx (5)
src/hooks/useCurrency.ts (1)
  • useCurrency (21-65)
src/components/Global/MantecaDetailsCard/index.tsx (1)
  • MantecaCardRow (5-7)
src/constants/manteca.consts.ts (1)
  • MANTECA_DEPOSIT_ADDRESS (1-1)
src/components/Global/PeanutLoading/index.tsx (1)
  • PeanutLoading (4-19)
src/components/0_Bruddle/Button.tsx (1)
  • Button (76-267)

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.

Fix typo before merging

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

🧹 Nitpick comments (6)
src/components/Payment/Views/MantecaFulfillment.view.tsx (6)

30-36: Avoid “undefined” in shared text; include only existing fields.

Currently always pushes both lines; missing values render as “undefined”.

-    const generateShareText = () => {
-        const textParts = []
-        textParts.push(`CBU: ${depositData?.data?.depositAddress}`)
-        textParts.push(`Alias: ${depositData?.data?.depositAlias}`)
-
-        return textParts.join('\n')
-    }
+    const generateShareText = () => {
+        const parts: string[] = []
+        const cbu = depositData?.data?.depositAddress
+        const alias = depositData?.data?.depositAlias
+        if (cbu) parts.push(`CBU: ${cbu}`)
+        if (alias) parts.push(`Alias: ${alias}`)
+        return parts.join('\n')
+    }

11-11: Import useQueryClient for cache hygiene on back navigation.

Needed for the suggestion below to clear cached deposit data/errors.

-import { useQuery } from '@tanstack/react-query'
+import { useQuery, useQueryClient } from '@tanstack/react-query'

15-15: Instantiate queryClient to clear deposit query on exit.

Prevents users from seeing stale error/data when returning to this flow.

 const MantecaFulfillment = () => {
-    const { setFulfillUsingManteca } = useRequestFulfillmentFlow()
+    const { setFulfillUsingManteca } = useRequestFulfillmentFlow()
+    const queryClient = useQueryClient()

46-49: Clear the deposit query cache when leaving the view.

Avoids reusing stale results if the user re-enters with the same charge but different amount/state.

                 onPrev={() => {
-                    setFulfillUsingManteca(false)
+                    setFulfillUsingManteca(false)
+                    queryClient.removeQueries({ queryKey: ['manteca-deposit', chargeDetails?.uuid] })
                 }}

17-24: Include usdAmount in the query key (and compute once) to avoid stale fetches when amount changes.

If the API output depends on amount, the current key won’t refetch. Compute usdAmount once to keep key and fn in sync.

-    const { data: depositData, isLoading: isLoadingDeposit } = useQuery({
-        queryKey: ['manteca-deposit', chargeDetails?.uuid],
-        queryFn: () =>
-            mantecaApi.deposit({
-                usdAmount: requestDetails?.tokenAmount || chargeDetails?.tokenAmount || '0',
-                currency: 'ARS',
-                chargeId: chargeDetails?.uuid,
-            }),
+    const usdAmount = requestDetails?.tokenAmount || chargeDetails?.tokenAmount || '0'
+    const { data: depositData, isLoading: isLoadingDeposit } = useQuery({
+        queryKey: ['manteca-deposit', chargeDetails?.uuid, usdAmount],
+        queryFn: () =>
+            mantecaApi.deposit({
+                usdAmount,
+                currency: 'ARS',
+                chargeId: chargeDetails?.uuid,
+            }),
         refetchOnWindowFocus: false,
         staleTime: Infinity, // don't refetch the data
         enabled: Boolean(chargeDetails?.uuid),
     })

If the endpoint truly ignores usdAmount, feel free to keep the original key. Please confirm the API behavior.


95-102: Drop unnecessary async wrapper for generateText.

generateShareText is synchronous.

-                        <ShareButton
-                            generateText={async () => generateShareText()}
+                        <ShareButton
+                            generateText={generateShareText}
                             title="Account Details"
                             variant="purple"
                             className="w-full"
                         >
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6dd05f and 4a74991.

📒 Files selected for processing (2)
  • src/components/Payment/PaymentForm/index.tsx (3 hunks)
  • src/components/Payment/Views/MantecaFulfillment.view.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/Payment/PaymentForm/index.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/components/Payment/Views/MantecaFulfillment.view.tsx (5)
src/context/RequestFulfillmentFlowContext.tsx (1)
  • useRequestFulfillmentFlow (109-115)
src/redux/hooks.ts (1)
  • usePaymentStore (12-12)
src/services/manteca.ts (1)
  • mantecaApi (95-211)
src/components/Global/PeanutLoading/index.tsx (1)
  • PeanutLoading (4-19)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
  • PeanutActionDetailsCard (54-255)
🔇 Additional comments (1)
src/components/Payment/Views/MantecaFulfillment.view.tsx (1)

21-23: Confirm units for usdAmount.

You’re passing tokenAmount while currency is 'ARS'. Ensure the backend expects a USD‑denominated amount (or that USDC amount equals USD here). If not, convert before sending.

@Zishan-7 Zishan-7 merged commit 1529829 into feat/manteca-integration Sep 16, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants