-
Notifications
You must be signed in to change notification settings - Fork 13
Fix Daimo bugs #1132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Daimo bugs #1132
Conversation
WalkthroughAdds Daimo payment flow updates: new store fields and actions, revised API for tracking deposit tx with extra fields, integration of a new ActionList DaimoPay button using function-as-children in DaimoPayButton, PaymentForm cleanup to remove Daimo UI, support for DEPOSIT in success view, minor UI/layout tweaks, config option, and dependency bump. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested reviewers
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/components/Common/CountryList.tsx (1)
89-101: Remove non-null assertion on flow to avoid runtime crashflow is optional in props; calling onCryptoClick(flow!) risks an exception if a caller forgets to pass it in add-withdraw mode.
- onClick={() => onCryptoClick(flow!)} + onClick={() => flow && onCryptoClick(flow)}For stronger safety, see the discriminated-union props suggestion below.
src/components/Global/DaimoPayButton/index.tsx (1)
71-101: Guard against empty/NaN/negative amounts before showing Daimo.If children is a render-prop and the consumer ignores the disabled flag, handleButtonClick can still invoke show() with an empty or invalid amount. Add strict validation in handleClick to prevent that and return a clear error.
Apply:
- const handleClick = useCallback(async () => { - // Parse and validate amount - const formattedAmount = parseFloat(amount.replace(/,/g, '')) + const handleClick = useCallback(async () => { + // Sanitize and validate amount + const sanitized = amount.replace(/,/g, '').trim() + const formattedAmount = Number(sanitized) + + if (!sanitized) { + onValidationError?.('Please enter an amount.') + return false + } + if (!Number.isFinite(formattedAmount) || formattedAmount <= 0) { + onValidationError?.('Amount must be a positive number.') + return false + } ... - await resetPayment({ - toUnits: amount.replace(/,/g, ''), - }) + await resetPayment({ + toUnits: sanitized, + }) return true - }, [amount, minAmount, maxAmount, onValidationError, onBeforeShow, resetPayment]) + }, [amount, minAmount, maxAmount, onValidationError, onBeforeShow, resetPayment])src/app/[...recipient]/client.tsx (1)
528-533: Fix grammar in user-facing error copy.“The payment” instead of “They payment”.
Apply:
- message: 'They payment you are trying to access is invalid. Please check the URL and try again.', + message: 'The payment you are trying to access is invalid. Please check the URL and try again.',
🧹 Nitpick comments (13)
src/config/wagmi.config.tsx (1)
82-85: Optional: avoid recreating the options object on each renderMinor render optimization: memoize the options object to prevent unnecessary subtree updates.
Add above the return inside ContextProvider:
const daimoOptions = useMemo(() => ({ embedGoogleFonts: true, disableMobileInjector: true }), [])Then change these lines:
- <DaimoPayProvider - options={{ embedGoogleFonts: true, disableMobileInjector: true }} - customTheme={DAIMO_THEME} - > + <DaimoPayProvider options={daimoOptions} customTheme={DAIMO_THEME}>src/components/TransactionDetails/TransactionCard.tsx (2)
111-116: Guard currency symbol resolution for undefined/varied casing codesgetDisplayCurrencySymbol(actualCurrencyCode) may receive undefined or mixed-case values. Normalize to uppercase and add a safe fallback.
- : transaction.currencySymbol || getDisplayCurrencySymbol(actualCurrencyCode) // Use provided sign+symbol or derive symbol + : transaction.currencySymbol || + (actualCurrencyCode ? getDisplayCurrencySymbol(actualCurrencyCode.toUpperCase()) : '')
123-128: Token decimals selection is tied to SEND_LINK onlyDecimals fall back to tokenDecimalsForDisplay only when originalType === SEND_LINK. This risks inconsistent display for DIRECT_SEND or other token flows.
Prefer reading a generic decimals hint (e.g., transaction.extraDataForDrawer?.tokenDecimalsForDisplay) regardless of originalType, with sensible defaults:
- const decimalsForDisplay = actualCurrencyCode - ? defaultDisplayDecimals - : transaction.extraDataForDrawer?.originalType === EHistoryEntryType.SEND_LINK - ? ((transaction.extraDataForDrawer as any)?.tokenDecimalsForDisplay ?? 6) - : 6 + const decimalsForDisplay = actualCurrencyCode + ? defaultDisplayDecimals + : Number((transaction.extraDataForDrawer as any)?.tokenDecimalsForDisplay) || 6src/components/Common/CountryList.tsx (3)
89-89: Copy nit: consider “Add with Crypto” for consistency with “Add/Withdraw”“Crypto Deposit” reads fine, but “Add with Crypto” may align better with the rest of the flow naming (Add/Withdraw). Your call.
46-54: Normalize country codes to uppercase when checking geo matchcountryCodeMap uses uppercase 3-letter keys; normalize a.id before lookup to avoid misses. This matches how you already do it later at lines 105–107.
- const aIsUserCountry = - countryCodeMap[a.id] === userGeoLocationCountryCode || a.id === userGeoLocationCountryCode - const bIsUserCountry = - countryCodeMap[b.id] === userGeoLocationCountryCode || b.id === userGeoLocationCountryCode + const aIsUserCountry = + countryCodeMap[a.id.toUpperCase()] === userGeoLocationCountryCode || + a.id.toUpperCase() === userGeoLocationCountryCode + const bIsUserCountry = + countryCodeMap[b.id.toUpperCase()] === userGeoLocationCountryCode || + b.id.toUpperCase() === userGeoLocationCountryCode
14-20: Make props types safer with a discriminated unionIn add-withdraw mode, flow and onCryptoClick should be required; the current optional typing forces runtime checks. A discriminated union encodes this at compile time.
Example:
type AddWithdrawProps = { inputTitle: string viewMode: 'add-withdraw' onCountryClick: (country: CountryData) => void onCryptoClick: (flow: 'add' | 'withdraw') => void flow: 'add' | 'withdraw' } type ClaimRequestProps = { inputTitle: string viewMode: 'claim-request' onCountryClick: (country: CountryData) => void } type CountryListViewProps = AddWithdrawProps | ClaimRequestPropsI can open a follow-up PR to apply this change across call sites if you’d like.
src/redux/types/payment.types.ts (1)
20-22: Hide backend‐sync failures from the user and clarify Daimo error semantics
Initial state is correctly set in
src/redux/slices/payment-slice.ts(lines 25–26):daimoError: null, isDaimoPaymentProcessing: false,(no action needed here)
In
src/components/Payment/PaymentForm/index.tsx(around lines 775–777), the UI still does:{daimoError && <ErrorAlert description={daimoError} />} {!daimoError && error && (…)}This surfaces backend‐sync failures as a Daimo payment error—per our prior learning, users shouldn’t see sync‐only errors when the payment itself succeeded. Instead:
• Remove or suppress the<ErrorAlert>fordaimoErrorin the form UI
• Log or reportdaimoErrorin the background without interrupting the user flowAdd a brief TSDoc comment on
IPaymentStateinsrc/redux/types/payment.types.tsto explain:
•error: payment‐processing failures (e.g. card decline)
•daimoError: backend update (sync) failures only(Optional) Consider renaming
daimoErrortodaimoSyncError(or similar) to make this distinction obvious in code and avoid confusion with the genericerrorfield.src/components/Payment/Views/Status.payment.view.tsx (2)
176-176: Hide recipient label/link for deposit flowsDEPOSIT is a self-funding event; showing a recipient can confuse users. Gate the recipient snippet out when type === 'DEPOSIT'.
- {!isExternalWalletFlow && - !isWithdrawFlow && - (recipientType !== 'USERNAME' ? ( + {!isExternalWalletFlow && + !isWithdrawFlow && + type !== 'DEPOSIT' && + (recipientType !== 'USERNAME' ? ( <AddressLink className="text-sm font-normal text-grey-1 no-underline" address={recipientName} /> ) : ( recipientName ))}
91-139: Receipt construction currently hardcodes a SEND contexttransactionForDrawer is populated with direction: 'send' and originalType: DIRECT_SEND. It’s fine since the “See receipt” button is SEND-only, but consider guarding this block with if (type === 'SEND') to avoid future confusion.
Example:
const transactionForDrawer = useMemo(() => { if (!chargeDetails || type !== 'SEND') return null // ... existing construction }, [chargeDetails, type, /* ... */])src/components/UserHeader/index.tsx (1)
65-73: Simplify: rely on printableAddress and drop duplicate isAddress/useMemo.printableAddress already no-ops for non-address strings, so the explicit isAddress + useMemo is redundant. This reduces imports and render logic without changing behavior.
Apply:
- const isCryptoAddress = useMemo(() => { - return isAddress(name) - }, [name]) ... - <div className={twMerge('text-sm font-semibold md:text-base', className)}> - {isCryptoAddress ? printableAddress(name, 4, 4) : name} - </div> + <div className={twMerge('text-sm font-semibold md:text-base', className)}> + {printableAddress(name, 4, 4)} + </div>And remove unused imports:
-import { useMemo } from 'react' -import { isAddress } from 'viem' import { printableAddress } from '@/utils'src/components/Global/DaimoPayButton/index.tsx (1)
104-107: Avoid hard-throwing on missing NEXT_PUBLIC_DAIMO_APP_ID in client.Throwing here will crash the page at runtime if the env is absent/misconfigured. Consider rendering nothing and logging an error (or showing a user-facing message) to keep the rest of the UI functional.
Example:
- if (!daimoAppId) { - throw new Error('Daimo APP ID is required') - } + if (!daimoAppId) { + console.error('Daimo APP ID is required') + onValidationError?.('We’re setting up deposits. Please try again in a bit.') + return null + }src/app/actions/users.ts (1)
135-137: Consider validating new fields for consistencyWhile
txHashandpayerAddressare validated, the new fieldssourceChainIdandsourceTokenAddressare not checked. Consider adding validation for these fields as well to ensure data integrity.- if (!txHash || !payerAddress) { - throw new Error('Missing required fields: txHash and payerAddress') + if (!txHash || !payerAddress || !sourceChainId || !sourceTokenAddress) { + throw new Error('Missing required fields: txHash, payerAddress, sourceChainId, and sourceTokenAddress') }src/components/Common/ActionListDaimoPayButton.tsx (1)
63-63: Remove or conditionally include console.log statementsProduction code should not contain console.log statements. Consider using a debug flag or removing these entirely.
- console.log('Initiating Daimo payment', payload) + if (process.env.NODE_ENV === 'development') { + console.log('Initiating Daimo payment', payload) + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (15)
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx(2 hunks)src/app/[...recipient]/client.tsx(2 hunks)src/app/actions/users.ts(2 hunks)src/components/AddMoney/components/CryptoMethodDrawer.tsx(1 hunks)src/components/Common/ActionList.tsx(4 hunks)src/components/Common/ActionListDaimoPayButton.tsx(1 hunks)src/components/Common/CountryList.tsx(1 hunks)src/components/Global/DaimoPayButton/index.tsx(3 hunks)src/components/Payment/PaymentForm/index.tsx(8 hunks)src/components/Payment/Views/Status.payment.view.tsx(2 hunks)src/components/TransactionDetails/TransactionCard.tsx(1 hunks)src/components/UserHeader/index.tsx(2 hunks)src/config/wagmi.config.tsx(1 hunks)src/redux/slices/payment-slice.ts(2 hunks)src/redux/types/payment.types.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
📚 Learning: 2025-08-22T07:28:32.260Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
Applied to files:
src/components/Common/ActionListDaimoPayButton.tsxsrc/components/Global/DaimoPayButton/index.tsxsrc/redux/types/payment.types.tssrc/components/Common/ActionList.tsxsrc/app/[...recipient]/client.tsxsrc/components/Payment/PaymentForm/index.tsxsrc/redux/slices/payment-slice.tssrc/app/(mobile-ui)/add-money/crypto/direct/page.tsx
📚 Learning: 2025-05-22T15:38:48.586Z
Learnt from: kushagrasarathe
PR: peanutprotocol/peanut-ui#869
File: src/app/(mobile-ui)/withdraw/page.tsx:82-88
Timestamp: 2025-05-22T15:38:48.586Z
Learning: The country-specific withdrawal route exists at src/app/(mobile-ui)/withdraw/[...country]/page.tsx and renders the AddWithdrawCountriesList component with flow="withdraw".
Applied to files:
src/components/Common/CountryList.tsxsrc/app/(mobile-ui)/add-money/crypto/direct/page.tsx
📚 Learning: 2025-08-14T14:42:54.411Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1094
File: src/utils/withdraw.utils.ts:181-191
Timestamp: 2025-08-14T14:42:54.411Z
Learning: The countryCodeMap in src/components/AddMoney/consts/index.ts uses uppercase 3-letter country codes as keys (like 'AUT', 'BEL', 'CZE') that map to 2-letter country codes, requiring input normalization to uppercase for proper lookups.
Applied to files:
src/components/Common/CountryList.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/Common/ActionList.tsxsrc/components/Payment/PaymentForm/index.tsx
📚 Learning: 2024-12-02T17:19:18.532Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2024-10-08T20:13:42.967Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#413
File: src/context/tokenSelector.context.tsx:118-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Applied to files:
src/components/Payment/PaymentForm/index.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/Payment/PaymentForm/index.tsx
📚 Learning: 2024-10-29T12:19:41.968Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Global/TokenAmountInput/index.tsx:23-30
Timestamp: 2024-10-29T12:19:41.968Z
Learning: In the `TokenAmountInput` component (`src/components/Global/TokenAmountInput/index.tsx`), when the 'Max' button is clicked, we intentionally set the input denomination to 'TOKEN' because we are setting the value as token.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2024-10-29T12:20:47.207Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Create/Link/Input.view.tsx:244-248
Timestamp: 2024-10-29T12:20:47.207Z
Learning: In the `TokenAmountInput` component within `src/components/Global/TokenAmountInput/index.tsx`, when `balance` is undefined, the `maxValue` prop should be set to an empty string `''`.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2025-08-22T07:25:59.258Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:596-600
Timestamp: 2025-08-22T07:25:59.258Z
Learning: The `TokenAmountInput` component in `src/components/Global/TokenAmountInput/` always returns decimal strings (e.g., "1,234.56"), not base units. When passing these values to external APIs like Daimo's `toUnits` prop, simply stripping commas with `.replace(/,/g, '')` is sufficient.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
🧬 Code graph analysis (8)
src/config/wagmi.config.tsx (1)
src/constants/daimo.consts.ts (1)
DAIMO_THEME(1-101)
src/components/Common/ActionListDaimoPayButton.tsx (7)
src/redux/hooks.ts (2)
useAppDispatch(5-5)usePaymentStore(12-12)src/components/Common/ActionList.tsx (1)
ACTION_METHODS(38-64)src/hooks/useCurrency.ts (1)
useCurrency(9-42)src/hooks/usePaymentInitiator.ts (2)
usePaymentInitiator(80-831)InitiatePaymentPayload(52-68)src/redux/slices/payment-slice.ts (1)
paymentActions(81-81)src/components/Global/DaimoPayButton/index.tsx (1)
DaimoPayButton(51-163)src/components/SearchUsers/SearchResultCard.tsx (1)
SearchResultCard(19-70)
src/components/Global/DaimoPayButton/index.tsx (2)
src/components/Global/Icons/Icon.tsx (1)
IconName(62-120)src/components/0_Bruddle/Button.tsx (1)
Button(76-267)
src/app/[...recipient]/client.tsx (1)
src/redux/hooks.ts (1)
usePaymentStore(12-12)
src/components/Payment/PaymentForm/index.tsx (2)
src/hooks/usePaymentInitiator.ts (1)
usePaymentInitiator(80-831)src/redux/slices/payment-slice.ts (1)
paymentActions(81-81)
src/components/UserHeader/index.tsx (1)
src/utils/general.utils.ts (1)
printableAddress(70-73)
src/components/Payment/Views/Status.payment.view.tsx (1)
src/components/Global/SoundPlayer.tsx (1)
SoundPlayer(18-30)
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx (1)
src/app/actions/users.ts (1)
trackDaimoDepositTransactionHash(123-165)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (25)
src/config/wagmi.config.tsx (2)
82-85: LGTM: DaimoPayProvider options update fits the new Daimo flowAdding disableMobileInjector: true alongside embedGoogleFonts: true looks consistent with the custom DAIMO_THEME (Roboto/Inter). No API surface changes and provider ordering remains sane.
82-85: Double-check global application ofdisableMobileInjector&embedGoogleFontsinDaimoPayProviderI didn’t find any environment- or device-based gating around these options—they’re applied unconditionally in
src/config/wagmi.config.tsx(lines 82–85).Please verify the following manually to ensure no degradation in UX or redundant font loading:
- Wallet connection & checkout flows on
• iOS Safari
• iOS Chrome- Wallet connection & checkout flows on
• Android Chrome
• In-app browsers (e.g. Telegram, Twitter)- That Roboto (or other Google fonts) isn’t being double-loaded if Next.js is preloading them; disable
embedGoogleFontsif necessarysrc/components/Common/CountryList.tsx (1)
85-101: All “add-withdraw” CountryList instances include theflowpropI’ve checked every
CountryListusage withviewMode="add-withdraw"and confirmed they all passflow(e.g. inAddWithdrawRouterView.tsxat lines 231–238). No further changes needed here.src/components/Payment/Views/Status.payment.view.tsx (2)
30-31: LGTM: DirectSuccessView now supports a DEPOSIT typeExtending the type union is clean and isolates DEPOSIT behavior without altering SEND/REQUEST semantics.
182-192: Confirm mobile header behavior for DEPOSIT and REQUESTYou added NavHeader for SEND and DEPOSIT. If REQUEST success screens should also expose a back action on mobile, consider including REQUEST here for parity; otherwise, confirm this difference is intentional.
src/components/UserHeader/index.tsx (1)
8-11: printableAddress correctly re-exported from utils barrelThe barrel file
src/utils/index.tsincludes the lineexport * from './general.utils'which ensures that
printableAddressis available from@/utils. No import path changes are required.src/components/Global/DaimoPayButton/index.tsx (1)
111-117: Verify DaimoPayButton prop semanticsPlease double-check against the official
@daimo/paydocumentation or type definitions to ensure:
- The
intentprop value is exactly"Deposit"(capital “D”) and matches one of the accepted values inDaimoPayButton.Custom(e.g."Deposit" | "Withdraw" | …).- The
toUnitsprop expects a human-readable decimal string (e.g."1234.56") rather than atomic units (e.g."1234560000000000000"). If it requires atomic units, apply the proper conversion (e.g. multiply by 10^decimals).No definitive source was found in the current codebase—please verify in the upstream package or its published type definitions.
src/components/AddMoney/components/CryptoMethodDrawer.tsx (1)
27-27: LGTM: additional bottom padding improves scroll/safe-area spacing.This is a sensible UI tweak for drawer content that may have sticky/overlapping CTAs.
src/app/[...recipient]/client.tsx (1)
45-47: Payment Slice: isDaimoPaymentProcessing Properly IntegratedAll set—
isDaimoPaymentProcessingis correctly defined, defaults tofalse, and is wired through the slice:
- Type definition added at
src/redux/types/payment.types.ts:21- Default state set to
falseatsrc/redux/slices/payment-slice.ts:26- Action creator
setIsDaimoPaymentProcessingimplemented atsrc/redux/slices/payment-slice.ts:72–73No further changes needed.
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx (3)
27-33: Server-tracking call shape updated — matches new API.Good use of an object payload including sourceChainId and sourceTokenAddress. The catch-and-continue behavior aligns with the past learning that users shouldn’t see errors if the backend sync fails after a successful Daimo payment.
50-51: LGTM: success view correctly uses DEPOSIT type.This aligns with the new DirectSuccessView support for deposits.
22-39: trackDaimoDepositTransactionHash is already a server-only actionI checked
src/app/actions/users.tsand confirmed:
- The very first line is
'use server', so everything in this file—includingtrackDaimoDepositTransactionHashand its use ofprocess.env.PEANUT_API_KEY!—runs only on the server and is never bundled to the client.- Your client component (
page.tsx) can safely import and call this server action without exposing the API key.No changes are needed here.
src/components/Common/ActionList.tsx (4)
28-28: Good separation of concerns for Daimo payment flowThe extraction of Daimo payment logic into a dedicated component
ActionListDaimoPayButtonimproves modularity and makes the code more maintainable.
38-38: Export made public for reusabilityMaking
ACTION_METHODSpublic is appropriate since it's now consumed byActionListDaimoPayButton. This follows the principle of exposing what's needed while maintaining encapsulation.
126-126: Refactored amount calculation to avoid potential NaNGood defensive programming - using ternary operator
usdAmount ? parseFloat(usdAmount) : 0prevents NaN whenusdAmountis null/undefined.
183-196: Clean integration of DaimoPayButton componentThe conditional rendering logic is well-structured. The special case for 'exchange-or-wallet' method is cleanly separated, while preserving the existing MethodCard behavior for other payment methods.
src/redux/slices/payment-slice.ts (2)
25-26: State initialization for Daimo error handlingProperly initialized new state fields for Daimo error and processing status tracking.
69-74: Well-implemented Redux actions for Daimo state managementThe new reducers follow Redux best practices with appropriate typing and immutable state updates. This provides a clean interface for managing Daimo payment state across components.
src/app/actions/users.ts (1)
123-133: Improved function signature with destructured parametersThe refactored signature using destructured object parameters is cleaner and more maintainable. This approach makes the function call more explicit and reduces the chance of parameter ordering errors.
src/components/Common/ActionListDaimoPayButton.tsx (2)
136-145: Verify disabled state logicThe SearchResultCard is disabled when either
loadingorisProcessingis true, but both values might represent the same state. Consider if this duplication is necessary.Can you verify if
loading(from the render prop) andisProcessingrepresent different states? If they're always synchronized, you might only need one.
27-30: Add explicit null check for parseFloatThe current check
parseFloat(usdAmount) <= 0could throw an error ifusdAmountis null. Consider adding explicit null checking before parsing.- if (!usdAmount || parseFloat(usdAmount) <= 0) { + if (!usdAmount || isNaN(parseFloat(usdAmount)) || parseFloat(usdAmount) <= 0) { console.error('Invalid amount entered') return false }⛔ Skipped due to learnings
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#868 File: src/components/Payment/PaymentForm/index.tsx:284-293 Timestamp: 2025-05-19T19:40:43.138Z Learning: When converting between USD and token amounts, always check if the token price (divisor) is valid and non-zero before performing the division to prevent Infinity, NaN, or errors. Implementing validation like `if (!tokenPrice || isNaN(tokenPrice) || tokenPrice === 0)` before division operations is crucial for handling cases where price data might be unavailable.Learnt from: Zishan-7 PR: peanutprotocol/peanut-ui#1098 File: src/components/LandingPage/noFees.tsx:26-26 Timestamp: 2025-08-15T08:04:31.171Z Learning: In the peanut-ui codebase, URL parameter parsing with parseFloat() for numeric values is considered safe due to: 1) parseFloat() only returns numbers/NaN (no executable code), 2) comprehensive validation exists elsewhere in the codebase, 3) values flow through type-safe React components, and 4) no direct DOM manipulation occurs that could expose XSS vectors.src/components/Payment/PaymentForm/index.tsx (4)
83-83: Good addition of Daimo error state trackingExtracting
daimoErrorfrom the payment store enables separate handling of Daimo-specific errors.
182-183: Consistent error clearing on recipient changeGood practice to clear both general and Daimo-specific errors when the recipient changes or component mounts.
Also applies to: 187-187
698-701: Good practice: Redux state synchronizationSetting both local state and Redux state for USD amount ensures consistency across the application.
775-785: Clean error display hierarchyThe conditional rendering of Daimo errors separately from general errors provides clear user feedback. The fallback message for insufficient balance is user-friendly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
src/components/TransactionDetails/TransactionCard.tsx (2)
80-83: Bug: completed non-USD bank_deposit shows USD with wrong decimalsWhen a non-USD bank_deposit is completed, you display USD but still use
defaultDisplayDecimalsderived from the original currency. For JPY-origin deposits, this renders USD with 0 decimals (e.g.,$123instead of$123.00). Use USD’s decimals in this branch.Apply:
if (isCompleted) { - // For completed transactions: show USD amount (amount is already in USD) - finalDisplayAmount = `$${formatNumberForDisplay(Math.abs(amount).toString(), { maxDecimals: defaultDisplayDecimals })}` + // For completed transactions: show USD amount (display in USD conventions) + const usdDecimals = 2 + finalDisplayAmount = `$${formatNumberForDisplay(Math.abs(amount).toString(), { maxDecimals: usdDecimals })}` } else {
140-141: Ensure clickable Card is keyboard-accessible and correctly announcedThe
Cardcomponent currently renders as a plain<div>with anonClickhandler but no ARIA or keyboard support. To meet accessibility requirements, update it so that wheneveronClickis provided, the Card:
- Is focusable (
tabIndex={0})- Announces itself as a button (
role="button")- Responds to Enter and Space keys by invoking
onClick- Optionally reflects disabled state with
aria-disabledif you add adisabledpropLocations to update:
- File:
src/components/Global/Card/index.tsx- Line: the
<div>returned in the component’sreturnblockSuggested diff snippet:
--- a/src/components/Global/Card/index.tsx +++ b/src/components/Global/Card/index.tsx @@ -38,7 +38,17 @@ const Card: React.FC<CardProps> = ({ children, position = 'single', className return ( - <div + <div className={twMerge('w-full bg-white px-4 py-2', getBorderRadius(), getBorder(), className)} - onClick={onClick} + onClick={onClick} + /* Make clickable div accessible */ + role={onClick ? 'button' : undefined} + tabIndex={onClick ? 0 : undefined} + onKeyDown={onClick ? (e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + onClick() + } + } : undefined} > {children} </div>With these changes, a keyboard user can focus the Card, activate it via Enter/Space, and assistive technologies will treat it as a button.
src/components/Payment/PaymentForm/index.tsx (3)
285-291: Bug: Prefill writes USD into token inputWhen price data is fetched, the code sets
inputTokenAmountto the computed USD value.TokenAmountInput.tokenValueexpects a token-denominated amount, not USD. This will mislabel the amount, break validations, and later conversions.Fix by setting the USD state(s) and keeping the original token amount in
inputTokenAmount:- // calculate USD value - const tokenAmount = parseFloat(requestDetails.tokenAmount) - const usdValue = formatAmount(tokenAmount * priceData.price) - setInputTokenAmount(usdValue) - setUsdValue(usdValue) + // calculate USD value + const tokenAmount = parseFloat(requestDetails.tokenAmount) + const usdValue = formatAmount(tokenAmount * priceData.price) + // keep token input in token units + setInputTokenAmount(requestDetails.tokenAmount) + // update USD states so downstream logic and UI are in sync + setInputUsdValue(usdValue) + setUsdValue(usdValue)
415-422: Harden cross-token conversion: normalize chainId types and handle empty USDTwo issues here:
requestedChain !== selectedChainIDis type-sensitive (string vs number) and may incorrectly trigger conversion.- Conversion relies solely on
inputUsdValue. When it's empty (e.g., prefilled flows),parseFloat('')becomesNaN, yieldingtokenAmount = 'NaN'.Normalize types and fall back to
usdValue:- if ( - requestedToken && - requestedTokenPrice && - (requestedChain !== selectedChainID || !areEvmAddressesEqual(requestedToken, selectedTokenAddress)) - ) { - tokenAmount = (parseFloat(inputUsdValue) / requestedTokenPrice).toString() - } + if ( + requestedToken && + requestedTokenPrice && + (String(requestedChain) !== String(selectedChainID) || + !areEvmAddressesEqual(requestedToken, selectedTokenAddress)) + ) { + const effectiveUsd = inputUsdValue && parseFloat(inputUsdValue) > 0 ? inputUsdValue : usdValue + tokenAmount = (parseFloat(effectiveUsd) / requestedTokenPrice).toString() + }Also add
usdValueto the callback deps to keep it consistent:}, [ canInitiatePayment, - isDepositRequest, isConnected, openReownModal, recipient, inputTokenAmount, isPintaReq, requestId, initiatePayment, beerQuantity, chargeDetails, isExternalWalletFlow, requestDetails, selectedTokenAddress, selectedChainID, inputUsdValue, requestedTokenPrice, + usdValue, ])
552-555: Align insufficient-balance detection with actual error messagesLocal checks set
'Insufficient balance'/'Insufficient balance in connected wallet', while this predicate looks for “You don't have enough balance.” The mismatch can suppress intended behaviors (e.g., Add Money CTA).Short-term, match both strings (case-insensitive). Longer-term, move to an error code on the store to avoid brittle string checks.
- const isInsufficientBalanceError = useMemo(() => { - return error?.includes("You don't have enough balance.") - }, [error]) + const isInsufficientBalanceError = useMemo(() => { + const msg = (error || '').toLowerCase() + return ( + msg.includes("you don't have enough balance") || + msg.includes('insufficient balance') + ) + }, [error])
♻️ Duplicate comments (3)
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx (1)
48-48: Fix confirmed; optional simplification for key prop.The extra brace bug is resolved. You can simplify by using a plain string instead of a template literal.
Apply:
- key={`success-add-money`} + key="success-add-money"src/components/TransactionDetails/TransactionCard.tsx (1)
175-175: Great fix: truncation now works inside flex containersSwitching to "min-w-0 flex-1 truncate" prevents the left column from pushing the amount and enables proper ellipsis. Matches the earlier recommendation.
src/components/Payment/PaymentForm/index.tsx (1)
771-781: Gate Daimo error display to only user-actionable validationPer prior guidance, post-success DB update failures must not surface to users. Show Daimo errors only for actionable preflight validations (e.g., min/max deposit). If you don’t yet have a code on
daimoError, defensively filter by known validation patterns and prefer moving to typed error codes.Change the render to a guarded flag:
- {daimoError && <ErrorAlert description={daimoError} />} + {shouldShowDaimoError && <ErrorAlert description={daimoError} />}Add this memo near other memos:
const shouldShowDaimoError = useMemo(() => { if (!daimoError) return false // Temporary heuristic until error codes are plumbed through: return ( daimoError.includes('Maximum deposit') || daimoError.includes('Minimum deposit') ) }, [daimoError])Longer-term: carry a structured
{ code: 'DAIMO_MIN_DEPOSIT' | 'DAIMO_MAX_DEPOSIT' | 'DAIMO_BACKEND_SYNC_FAILED', message: string }in Redux and branch oncode.
🧹 Nitpick comments (11)
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx (5)
27-32: Harden payload extraction and coerce chainId to string.
- Robustify against unexpected event shapes to avoid TypeErrors.
- trackDaimoDepositTransactionHash expects string fields; chainId may arrive as a number from providers—coerce to string to satisfy typing and avoid backend ambiguity.
Apply:
- await trackDaimoDepositTransactionHash({ - txHash: e.txHash, - payerAddress: e.payment.source.payerAddress, - sourceChainId: e.payment.source.chainId, - sourceTokenAddress: e.payment.source.tokenAddress, - }) + const txHash = e?.txHash + const payerAddress = e?.payment?.source?.payerAddress + const sourceChainId = + e?.payment?.source?.chainId != null ? String(e.payment.source.chainId) : '' + const sourceTokenAddress = e?.payment?.source?.tokenAddress + await trackDaimoDepositTransactionHash({ + txHash, + payerAddress, + sourceChainId, + sourceTokenAddress, + })
22-22: Replaceanywith a minimal event type for compile-time safety.Annotate the Daimo completion event to document the contract and catch regressions.
Example:
-export default function AddMoneyCryptoDirectPage() { +type DaimoPaymentCompletedEvent = { + txHash: string + payment: { source: { payerAddress: string; chainId: string | number; tokenAddress: string } } +} +export default function AddMoneyCryptoDirectPage() { ... - const onPaymentCompleted = async (e: any) => { + const onPaymentCompleted = async (e: DaimoPaymentCompletedEvent) => {
51-51: Standardize currency formatting.Render a properly formatted currency string to keep UX consistent and avoid cases like “$0.1”.
Apply:
- currencyAmount={`$${inputTokenAmount}`} + currencyAmount={new Intl.NumberFormat(undefined, { + style: 'currency', + currency: 'USD', + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }).format(Number(inputTokenAmount || 0))}
41-43: Consider not gating the success UI on the backend update.Per prior Daimo learnings, the DB sync should not affect user-facing success. You could show the success view immediately and fire-and-forget the tracking call (with logging), improving perceived latency.
Option: remove the loading branch and set
isPaymentSuccess(true)before awaiting the tracking call, or trigger the tracking in a non-blockingvoidpromise with error capture.
18-18: Setter name casing nit.Rename
setisPaymentSuccesstosetIsPaymentSuccessto match common React naming conventions.Apply:
- const [isPaymentSuccess, setisPaymentSuccess] = useState(false) + const [isPaymentSuccess, setIsPaymentSuccess] = useState(false) ... - setisPaymentSuccess(true) + setIsPaymentSuccess(true)Also applies to: 37-37
src/components/TransactionDetails/TransactionCard.tsx (3)
123-128: Use tokenDecimalsForDisplay whenever available (not only for SEND_LINK)Decimal precision for tokens should respect
tokenDecimalsForDisplayregardless oforiginalType. This avoids unexpected 6-decimal truncation for other token flows.- const decimalsForDisplay = actualCurrencyCode // If it's a known currency (USD, ARS) - ? defaultDisplayDecimals - : transaction.extraDataForDrawer?.originalType === EHistoryEntryType.SEND_LINK // Example: check token specific decimals if available - ? ((transaction.extraDataForDrawer as any)?.tokenDecimalsForDisplay ?? 6) // Fallback to 6 for tokens - : 6 // General fallback for other tokens + const decimalsForDisplay = actualCurrencyCode + ? defaultDisplayDecimals + : ((transaction.extraDataForDrawer as any)?.tokenDecimalsForDisplay ?? 6)
129-134: Avoid re-prefixing symbol when appending token symbol
finalDisplayAmountalready contains the symbol (or none for tokens). Re-appendingdisplaySymbolis redundant.- finalDisplayAmount = `${displaySymbol}${formatNumberForDisplay(amountString, { maxDecimals: decimalsForDisplay })}` + finalDisplayAmount = `${displaySymbol}${formatNumberForDisplay(amountString, { maxDecimals: decimalsForDisplay })}` if (!isStableCoin && !actualCurrencyCode) { // Append token symbol if it's a token transaction - - finalDisplayAmount = `${displaySymbol}${finalDisplayAmount} ${transaction.tokenSymbol}` + finalDisplayAmount = `${finalDisplayAmount} ${transaction.tokenSymbol}` }
151-153: Improve avatar image alt text for accessibilityIf the avatar is decorative (name is adjacent), prefer empty alt to avoid redundant announcements. If you want it announced, use a descriptive alt.
- alt="Icon" + alt=""src/components/Payment/PaymentForm/index.tsx (3)
139-140: Remove unusedisDepositRequestand its dependency to reduce churnThe value isn’t used in
handleInitiatePaymentand being in the deps causes unnecessary callback re-creation.Apply this cleanup:
- const isDepositRequest = searchParams.get('action') === 'deposit'And remove it from the deps:
- isDepositRequest,Also applies to: 454-472
524-528: De-duplicate beer-quantity effectsTwo effects update
beerQuantityfrominputTokenAmountunder the same condition. Keep one to avoid double-dispatch and make behavior easier to reason about.Also applies to: 544-550
145-148: Trim unused dep inisConnectedmemo
statusis included in the dependency list but not used in the calculation. Removing it will prevent unnecessary recomputation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx(2 hunks)src/components/Common/ActionListDaimoPayButton.tsx(1 hunks)src/components/Global/DaimoPayButton/index.tsx(3 hunks)src/components/Payment/PaymentForm/index.tsx(5 hunks)src/components/TransactionDetails/TransactionCard.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/components/Common/ActionListDaimoPayButton.tsx
- src/components/Global/DaimoPayButton/index.tsx
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
📚 Learning: 2025-08-22T07:28:32.260Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
Applied to files:
src/app/(mobile-ui)/add-money/crypto/direct/page.tsxsrc/components/Payment/PaymentForm/index.tsx
📚 Learning: 2025-08-26T15:25:53.301Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.301Z
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/app/(mobile-ui)/add-money/crypto/direct/page.tsxsrc/components/Payment/PaymentForm/index.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/app/(mobile-ui)/add-money/crypto/direct/page.tsx
📚 Learning: 2025-07-07T20:22:11.092Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#958
File: src/app/actions/tokens.ts:266-266
Timestamp: 2025-07-07T20:22:11.092Z
Learning: In `src/app/actions/tokens.ts`, within the `fetchWalletBalances` function, using the non-null assertion operator `!` on `process.env.MOBULA_API_KEY!` is intentional and correct, and should not be flagged for replacement with explicit validation.
Applied to files:
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx
📚 Learning: 2024-12-02T17:19:18.532Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Applied to files:
src/components/Payment/PaymentForm/index.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/PaymentForm/index.tsx
📚 Learning: 2024-10-08T20:13:42.967Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#413
File: src/context/tokenSelector.context.tsx:118-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2024-10-29T12:19:41.968Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Global/TokenAmountInput/index.tsx:23-30
Timestamp: 2024-10-29T12:19:41.968Z
Learning: In the `TokenAmountInput` component (`src/components/Global/TokenAmountInput/index.tsx`), when the 'Max' button is clicked, we intentionally set the input denomination to 'TOKEN' because we are setting the value as token.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2024-10-29T12:20:47.207Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Create/Link/Input.view.tsx:244-248
Timestamp: 2024-10-29T12:20:47.207Z
Learning: In the `TokenAmountInput` component within `src/components/Global/TokenAmountInput/index.tsx`, when `balance` is undefined, the `maxValue` prop should be set to an empty string `''`.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2025-08-22T07:25:59.258Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:596-600
Timestamp: 2025-08-22T07:25:59.258Z
Learning: The `TokenAmountInput` component in `src/components/Global/TokenAmountInput/` always returns decimal strings (e.g., "1,234.56"), not base units. When passing these values to external APIs like Daimo's `toUnits` prop, simply stripping commas with `.replace(/,/g, '')` is sufficient.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
🧬 Code graph analysis (2)
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx (1)
src/app/actions/users.ts (1)
trackDaimoDepositTransactionHash(123-165)
src/components/Payment/PaymentForm/index.tsx (2)
src/hooks/usePaymentInitiator.ts (1)
usePaymentInitiator(80-831)src/redux/slices/payment-slice.ts (1)
paymentActions(81-81)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (4)
src/app/(mobile-ui)/add-money/crypto/direct/page.tsx (2)
50-50: DEPOSIT type usage looks correct.Assuming DirectSuccessViewProps includes "DEPOSIT" (as per related changes), this aligns the success view with the deposit flow.
47-55: CheckDirectSuccessViewheader logic to avoid unintended overridesI’ve verified that the
DirectSuccessViewprops include both atype?: 'SEND' | 'REQUEST' | 'DEPOSIT'and an optionalheaderTitle?: string, and that the component uses:
- Its own type-based defaults (e.g. “You deposited”) when
headerTitleis not provided- Always the passed-in
headerTitlewhen it is providedSince our mobile page explicitly passes
headerTitle="Add Money"alongsidetype="DEPOSIT", this will replace the DEPOSIT default (“You deposited”) with “Add Money.”
Please confirm that “Add Money” is indeed the desired header for deposit flows on mobile. If we intend to keep the type-specific copy, remove theheaderTitleprop here so that the component’s built-in default is used instead.—
src/components/Payment/PaymentForm/index.tsx (2)
80-86: Good: Scoped Daimo error in store is now plumbed into the formPulling
daimoErrorfrom the store here makes the UI react to Daimo-specific issues independently of the genericerror. This separation is the right direction.
694-697: Good: Keep Redux USD state in sync with user inputUpdating both local state and
paymentActions.setUsdAmounthere ensures downstream consumers have the latest USD value without waiting for the initiator flow. Matches prior learnings about passing decimal strings upstream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
src/components/Payment/PaymentForm/index.tsx (5)
551-553: Insufficient-balance detection is broken due to string mismatch; fix detection and alert copyYou set "Insufficient balance" earlier but check for "You don't have enough balance." here, so the CTA never flips to “Add funds,” and the retry copy logic doesn't trigger. Use a robust, case-insensitive check (or better: a typed error), and update the alert mapping accordingly.
Apply this diff:
@@ - const isInsufficientBalanceError = useMemo(() => { - return error?.includes("You don't have enough balance.") - }, [error]) + const isInsufficientBalanceError = useMemo(() => { + const msg = (error ?? '').toLowerCase() + // Matches both "Insufficient balance" and "Insufficient balance in connected wallet" + return msg.includes('insufficient balance') + }, [error]) @@ - {!daimoError && error && ( + {!daimoError && error && ( <ErrorAlert description={ - error.includes("You don't have enough balance.") + (error ?? '').toLowerCase().includes('insufficient balance') ? 'Not enough balance to fulfill this request with Peanut' : error } /> )}Also applies to: 775-779
739-753: CTA is hidden for external-wallet flows; remove Peanut-only gatingBoth the primary and Retry CTAs render only when the Peanut Wallet is connected. In external-wallet flows (Add Money, non-Peanut sends), this hides the only action and blocks progression. Render the CTA regardless of Peanut wallet status; your button text/disable logic already adapts per state.
Apply this diff:
@@ - {isPeanutWalletConnected && (!error || isInsufficientBalanceError) && ( + {(!error || isInsufficientBalanceError) && ( <Button variant="purple" loading={isProcessing} shadowSize="4" onClick={handleInitiatePayment} disabled={isButtonDisabled} className="w-full" icon={getButtonIcon()} iconSize={16} > {getButtonText()} </Button> )} - {isPeanutWalletConnected && error && !isInsufficientBalanceError && ( + {error && !isInsufficientBalanceError && ( <Button variant="purple" loading={isProcessing} shadowSize="4" onClick={() => { handleInitiatePayment() }} disabled={isProcessing} className="w-full" icon="retry" iconSize={16} > Retry </Button> )}Also applies to: 754-769
271-301: Do not overwrite token input with a USD stringHere you compute USD from tokenAmount and then set inputTokenAmount to the USD value. That flips units from “token” to “USD,” which breaks later validations and conversions.
Apply this diff to only set the USD value:
@@ if (priceData) { setRequestedTokenPrice(priceData.price) if (requestDetails?.tokenAmount) { // calculate USD value const tokenAmount = parseFloat(requestDetails.tokenAmount) - const usdValue = formatAmount(tokenAmount * priceData.price) - setInputTokenAmount(usdValue) - setUsdValue(usdValue) + const usd = formatAmount(tokenAmount * priceData.price) + setUsdValue(usd) } } else {
304-314: Parsing amounts without stripping thousands separators leads to wrong numbersTokenAmountInput returns formatted decimals (e.g., "1,234.56"). Several places use parseFloat directly, which will parse only the leading “1” and treat the rest as invalid, causing false negatives, disabled CTAs, and wrong conversions.
Apply these diffs to consistently strip commas before numeric ops:
@@ - } else if (isActivePeanutWallet) { - amountIsSet = !!inputTokenAmount && parseFloat(inputTokenAmount) > 0 + } else if (isActivePeanutWallet) { + amountIsSet = + !!inputTokenAmount && parseFloat(String(inputTokenAmount).replace(/,/g, '')) > 0 } else { amountIsSet = - (!!inputTokenAmount && parseFloat(inputTokenAmount) > 0) || (!!usdValue && parseFloat(usdValue) > 0) + (!!inputTokenAmount && + parseFloat(String(inputTokenAmount).replace(/,/g, '')) > 0) || + (!!usdValue && parseFloat(String(usdValue).replace(/,/g, '')) > 0) } @@ - const numericAmount = parseFloat(inputTokenAmount) + const numericAmount = parseFloat(String(inputTokenAmount).replace(/,/g, '')) if (isNaN(numericAmount) || numericAmount <= 0) { if (!isExternalWalletFlow) return true } @@ - if (!inputTokenAmount || parseFloat(inputTokenAmount) <= 0) { + if (!inputTokenAmount || parseFloat(String(inputTokenAmount).replace(/,/g, '')) <= 0) { console.error('Invalid amount entered') dispatch(paymentActions.setError('Please enter a valid amount')) return } @@ - let tokenAmount = inputTokenAmount + let tokenAmount = inputTokenAmount if ( requestedToken && requestedTokenPrice && (requestedChain !== selectedChainID || !areEvmAddressesEqual(requestedToken, selectedTokenAddress)) ) { - tokenAmount = (parseFloat(inputUsdValue) / requestedTokenPrice).toString() + tokenAmount = ( + parseFloat(String(inputUsdValue).replace(/,/g, '')) / requestedTokenPrice + ).toString() } @@ - if (isPintaReq && inputTokenAmount) { - dispatch(paymentActions.setBeerQuantity(Number(inputTokenAmount))) + if (isPintaReq && inputTokenAmount) { + dispatch( + paymentActions.setBeerQuantity( + parseFloat(String(inputTokenAmount).replace(/,/g, '')) || 0 + ) + ) } @@ - if (selectedTokenPrice) { - setUsdValue((parseFloat(inputTokenAmount) * selectedTokenPrice).toString()) + if (selectedTokenPrice) { + const tokenAmt = parseFloat(String(inputTokenAmount).replace(/,/g, '')) + if (!isNaN(tokenAmt)) { + setUsdValue((tokenAmt * selectedTokenPrice).toString()) + } else { + setUsdValue('') + } }Also applies to: 561-565, 387-392, 414-421, 523-527, 529-534
271-301: Enforce client/server boundary for fetchTokenPricefetchTokenPrice is defined in a server-only module (
src/app/actions/tokens.tswith"use server") and cannot be invoked directly from a client component. You’ll need to either:
- Expose a client-safe API endpoint (e.g.
/api/token-price) or- Lift this logic into a server component (using Suspense or server-side props) and pass the result down to PaymentForm.
Locations requiring updates:
- src/components/Payment/PaymentForm/index.tsx, lines 271–301 (useEffect calling fetchTokenPrice)
- src/components/Payment/PaymentForm/index.tsx, lines 387–421 (similar fetch usage)
- src/app/actions/tokens.ts, lines 1 (
"use server") & 106 (export of fetchTokenPrice)
♻️ Duplicate comments (1)
src/components/Payment/PaymentForm/index.tsx (1)
185-187: Thanks for keeping Daimo errors intact during balance checksYou stopped clearing Daimo errors in the balance-check effect. This prevents flicker and preserves actionable Daimo validation.
🧹 Nitpick comments (3)
src/components/Payment/PaymentForm/index.tsx (3)
770-781: Hide generic errors while Daimo completion is in-flight; also disable CTA when Daimo shows an errorPer team learnings, backend sync failures post-successful Daimo payments should not surface to users. Consume isDaimoPaymentProcessing from the store to hide generic errors during Daimo completion. Additionally, disable the CTA when daimoError is present.
Apply these diffs:
@@ - const { + const { requestDetails, chargeDetails, beerQuantity, - daimoError, + daimoError, + isDaimoPaymentProcessing, error: paymentStoreError, attachmentOptions, } = usePaymentStore() @@ - if (isProcessing) return true + if (isProcessing) return true + if (isDaimoPaymentProcessing) return true + if (daimoError) return true @@ - {!daimoError && error && ( + {!daimoError && !isDaimoPaymentProcessing && error && ( <ErrorAlert description={ (error ?? '').toLowerCase().includes('insufficient balance') ? 'Not enough balance to fulfill this request with Peanut' : error } /> )}If preferred, we can instead gate the error source at the selector level and expose a canonical “userFacingError” that already respects Daimo state.
Also applies to: 80-86, 555-559
139-139: Remove unused isDepositRequest to avoid dead codeisDepositRequest is declared but never used; it’s also listed in handleInitiatePayment’s deps. Drop both to reduce noise.
Apply this diff:
@@ - const isDepositRequest = searchParams.get('action') === 'deposit' @@ - isDepositRequest,Also applies to: 454-471
551-553: Optional: move away from string-matching for business logicConsider exposing a typed error code (e.g., 'INSUFFICIENT_BALANCE') from the store/initiator and computing isInsufficientBalanceError from that. This avoids brittle copy dependencies.
Happy to wire this through the payment-slice and initiator if you want.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
src/components/Payment/PaymentForm/index.tsx(5 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
📚 Learning: 2025-08-22T07:28:32.260Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2025-08-26T15:25:53.301Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.301Z
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/Payment/PaymentForm/index.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/Payment/PaymentForm/index.tsx
📚 Learning: 2024-12-02T17:19:18.532Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Applied to files:
src/components/Payment/PaymentForm/index.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/PaymentForm/index.tsx
📚 Learning: 2024-10-29T12:19:41.968Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Global/TokenAmountInput/index.tsx:23-30
Timestamp: 2024-10-29T12:19:41.968Z
Learning: In the `TokenAmountInput` component (`src/components/Global/TokenAmountInput/index.tsx`), when the 'Max' button is clicked, we intentionally set the input denomination to 'TOKEN' because we are setting the value as token.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2024-10-29T12:20:47.207Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Create/Link/Input.view.tsx:244-248
Timestamp: 2024-10-29T12:20:47.207Z
Learning: In the `TokenAmountInput` component within `src/components/Global/TokenAmountInput/index.tsx`, when `balance` is undefined, the `maxValue` prop should be set to an empty string `''`.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2025-08-22T07:25:59.258Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:596-600
Timestamp: 2025-08-22T07:25:59.258Z
Learning: The `TokenAmountInput` component in `src/components/Global/TokenAmountInput/` always returns decimal strings (e.g., "1,234.56"), not base units. When passing these values to external APIs like Daimo's `toUnits` prop, simply stripping commas with `.replace(/,/g, '')` is sufficient.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
🧬 Code graph analysis (1)
src/components/Payment/PaymentForm/index.tsx (1)
src/hooks/usePaymentInitiator.ts (1)
usePaymentInitiator(80-831)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (6)
src/components/Payment/PaymentForm/index.tsx (6)
179-183: Good: reset Daimo error on mount/recipient change onlyClearing Daimo errors on scope boundaries (component mount/recipient change) aligns with the learning to avoid showing backend-sync errors yet keep Daimo validations accurate.
693-696: Pushing live USD edits to Redux looks goodForwarding USD edits via setUsdAmount keeps the store in sync with the UI. No concerns.
118-123: Minor: Error normalization is solidCentralizing error normalization via ErrorHandler for both initiator and store errors is clean. LGTM.
473-521: CTA copy/icons are coherentDynamic label/icon selection covers connect/review/send/add-funds states. Once the insufficient balance matcher is fixed, this will behave as intended.
690-703: Amount input wiring is correctToken amount and USD setters are plumbed correctly, and Peanut balance is hidden for external-wallet flows. Looks good.
706-725: Commented TokenSelector blockThe note about Daimo handling token selection makes sense. Keep an eye on UX: if Daimo is not chosen, ensure token selection is available elsewhere.
If token selection is needed outside Daimo, confirm where that UI lives to avoid dead-ends.
1 similar comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approved preliminarily plus pls ping when youve answered Qs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (3)
src/components/Common/ActionList.tsx (3)
38-64: Make ACTION_METHODS immutable and avoid accidental mutation.If you decide to keep exporting ACTION_METHODS from this file, make it read-only to prevent runtime mutation (especially now that it becomes part of the public surface).
-export const ACTION_METHODS: Method[] = [ +export const ACTION_METHODS: ReadonlyArray<Method> = [ { id: 'bank', title: 'Bank', description: 'EUR, USD, ARS (more coming soon)', icons: [ 'https://flagcdn.com/w160/ar.png', 'https://flagcdn.com/w160/de.png', 'https://flagcdn.com/w160/us.png', ], soon: false, }, /* ... */ -] +] as constNote: If you adopt the “pass method as prop” approach (recommended in this review), you can also drop the export entirely to keep this purely an internal detail of ActionList.
98-98: Remove unnecessary async from handleMethodClick.The function body has no await and returns synchronously. Dropping async avoids an implicit Promise return type and keeps intent clear.
- const handleMethodClick = async (method: Method) => { + const handleMethodClick = (method: Method) => {
100-105: Sanitize USD parsing in request flow & clarify gating logic in claim flow
In the request branch (
flow === 'request'at line 126):
Current codeconst amountInUsd = usdAmount ? parseFloat(usdAmount) : 0 if (method.id === 'bank' && amountInUsd < 1) { … }Issues:
- A string containing only whitespace (e.g.
' ') is truthy, soparseFloat(' ')→NaN.NaN < 1is false, so the “minimum $1” guard is silently bypassed.- Malformed inputs (letters, symbols) also yield NaN, leading to the same silent skip.
In the claim branch (
flow === 'claim'at line 100):
Current codeconst amountInUsd = parseFloat(formatUnits(claimLinkData.amount, claimLinkData.tokenDecimals)) if (method.id === 'bank' && amountInUsd < 1) { … }Misnomer/mis-gating:
formatUnits(...)returns the raw token amount (e.g. 1.5 DAI), not its USD value.- If non-USD tokens (ETH, USDC, etc.) are ever used here, this check is gating on “token units” rather than “USD”.
Apply this diff in
src/components/Common/ActionList.tsx(request branch):- const amountInUsd = usdAmount ? parseFloat(usdAmount) : 0 + // trim and parse, then guard against NaN + const parsedUsd = Number((usdAmount ?? '').trim()) + const amountInUsd = Number.isFinite(parsedUsd) ? parsedUsd : 0Follow-ups & next steps
Claim flow gating:
- If you need a true USD threshold here, fetch the current token price (e.g. via an existing selector like
usePrice(tokenAddress)) and computeconst tokenAmount = Number(formatUnits(...)) const amountInUsd = tokenAmount * currentTokenPrice- If this branch only ever sees USD-pegged tokens, rename
and update the threshold comment accordingly (e.g. “minimum 1 token”).// before const amountInUsd = parseFloat(formatUnits(...)) // after const amountInToken = parseFloat(formatUnits(...))Centralize USD parsing:
- Consider extracting a utility (e.g.
parseUsdAmount(value: string|null): number) and using it in all components (ActionList,ActionListDaimoPayButton, transaction transformers, etc.) to ensure consistent behavior.To verify all gating occurrences:
rg -n -C2 "const amountInUsd" src/components/Common/ActionList.tsx
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
src/components/Common/ActionList.tsx(4 hunks)src/components/Common/ActionListDaimoPayButton.tsx(1 hunks)src/components/Payment/Views/Status.payment.view.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/components/Common/ActionListDaimoPayButton.tsx
- src/components/Payment/Views/Status.payment.view.tsx
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
📚 Learning: 2025-08-26T15:25:53.301Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.301Z
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/Common/ActionList.tsx
📚 Learning: 2025-08-22T07:28:32.260Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
Applied to files:
src/components/Common/ActionList.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/Common/ActionList.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/Common/ActionList.tsx (1)
28-34: Remove the local Method interface here; import the type from the constants module to break the cycle.Defining
Methodhere while the constants file imports it reintroduces a circular dependency. Move the type alongside the constants (or a shared types module) and import it here as a type.Apply this diff to delete the local interface:
-export interface Method { - id: string - title: string - description: string - icons: any[] - soon: boolean -}Then add this import alongside other imports (outside the selected range):
import type { Method } from '@/constants/actionlist.consts'Optional tightening (if you control the type): define
MethodId = 'bank' | 'mercadopago' | 'exchange-or-wallet'and use it forid; narrowiconsto a readonly union rather thanany[].
♻️ Duplicate comments (2)
src/components/Common/ActionList.tsx (2)
25-26: Code-split the Daimo button and avoid SSR/window issues; also helps decouple dependencies.Importing
ActionListDaimoPayButtondirectly can cause SSR headaches if it toucheswindow, and worsens coupling. Use a dynamic import withssr: false. This aligns with earlier guidance in this PR thread.-import ActionListDaimoPayButton from './ActionListDaimoPayButton' import { ACTION_METHODS } from '@/constants/actionlist.consts'Add this import near the top (outside the selected range):
import dynamic from 'next/dynamic' const ActionListDaimoPayButton = dynamic(() => import('./ActionListDaimoPayButton'), { ssr: false })Quick check for any
windowusage in the Daimo button:#!/bin/bash rg -n "ActionListDaimoPayButton\.tsx" -C2 rg -n "\bwindow\b" src/components/Common/ActionListDaimoPayButton.tsx -C2 || true
153-156: Pass the method into the Daimo button to avoid cross-module lookups and hidden cycles.Render-prop the resolved method so
ActionListDaimoPayButtondoesn’t importACTION_METHODS(orActionList) internally. This also improves testability.- {ACTION_METHODS.map((method) => { - if (flow === 'request' && method.id === 'exchange-or-wallet') { - return <ActionListDaimoPayButton key={method.id} /> - } + {ACTION_METHODS.map((method) => { + if (flow === 'request' && method.id === 'exchange-or-wallet') { + return <ActionListDaimoPayButton key={method.id} method={method} /> + }And in
src/components/Common/ActionListDaimoPayButton.tsx, accept the prop and remove any imports ofACTION_METHODS:// at top import type { Method } from '@/constants/actionlist.consts' type Props = { method: Method } export default function ActionListDaimoPayButton({ method }: Props) { // ... }Confirm the button no longer imports ACTION_METHODS and does not show user-facing errors on backend sync failures (per retrieved learnings):
#!/bin/bash # No direct ACTION_METHODS import rg -n "import .*ACTION_METHODS" src/components/Common/ActionListDaimoPayButton.tsx || true # Assert no user-facing error surfaces for post-success sync (toast/alert) rg -nP "toast|alert|ActionModal|console\.(error|warn)" src/components/Common/ActionListDaimoPayButton.tsx -C2 || true
🧹 Nitpick comments (2)
src/constants/actionlist.consts.ts (1)
6-32: Make ACTION_METHODS immutable and tighten typing.Exposing it as a mutable
Method[]invites unintended mutation. Prefer a readonly literal with satisfies for compile-time checks.-export const ACTION_METHODS: Method[] = [ +export const ACTION_METHODS = [ { id: 'bank', title: 'Bank', description: 'EUR, USD, ARS (more coming soon)', icons: [ 'https://flagcdn.com/w160/ar.png', 'https://flagcdn.com/w160/de.png', 'https://flagcdn.com/w160/us.png', ], soon: false, }, { id: 'mercadopago', title: 'Mercado Pago', description: 'Instant transfers', icons: [MERCADO_PAGO_ICON], soon: true, }, { id: 'exchange-or-wallet', title: 'Exchange or Wallet', description: 'Binance, Coinbase, Metamask and more', icons: [binanceIcon, TRUST_WALLET_SMALL_LOGO, METAMASK_LOGO], soon: false, }, -] +] as const satisfies ReadonlyArray<Method>Optional: If you keep the
Methodtype here, consider refiningiconsto a safer union (e.g.,ReadonlyArray<string | StaticImport>if usingnext/image).src/components/Common/ActionList.tsx (1)
96-96: Make amount parsing resilient to non-numeric strings.Current check treats any non-empty string as parseable; whitespace like ' ' yields
NaN. Use a numeric guard.- const amountInUsd = usdAmount ? parseFloat(usdAmount) : 0 + const amountInUsd = Number.isFinite(Number(usdAmount)) ? Number(usdAmount) : 0
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
src/components/Common/ActionList.tsx(3 hunks)src/components/Common/ActionListDaimoPayButton.tsx(1 hunks)src/constants/actionlist.consts.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/Common/ActionListDaimoPayButton.tsx
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
📚 Learning: 2025-08-26T17:38:37.017Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/components/Common/ActionList.tsx:153-156
Timestamp: 2025-08-26T17:38:37.017Z
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/constants/actionlist.consts.tssrc/components/Common/ActionList.tsx
📚 Learning: 2025-08-26T15:25:53.301Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.301Z
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/Common/ActionList.tsx
📚 Learning: 2025-08-22T07:28:32.260Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
Applied to files:
src/components/Common/ActionList.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/Common/ActionList.tsx
🧬 Code graph analysis (2)
src/constants/actionlist.consts.ts (1)
src/components/Common/ActionList.tsx (1)
Method(28-34)
src/components/Common/ActionList.tsx (1)
src/constants/actionlist.consts.ts (1)
ACTION_METHODS(6-32)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Deploy-Preview
- GitHub Check: test
🔇 Additional comments (1)
src/constants/actionlist.consts.ts (1)
11-15: No action needed: wildcard remotePatterns already covers flagcdn.comThe
next.config.jsfile definesimages.remotePatternswith a wildcard hostname for both HTTP and HTTPS, which includesflagcdn.com. Therefore, external images fromhttps://flagcdn.com/...will load successfully with Next.js’s<Image>component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/Common/ActionList.tsx (1)
60-67: Ensure correct USD conversion in claim flow before enforcing the $1 minimumThe
amountInUsdcomputed inhandleMethodClickis actually the raw token amount—not USD—because it’s derived solely viaformatUnits(claimLinkData.amount, claimLinkData.tokenDecimals)(which returns token units). IfclaimLinkData.tokenSymbolever represents a non‐USD‐pegged token (e.g. ETH or other ERC-20), the bank-payout guard (if (method.id === 'bank' && amountInUsd < 1)) will erroneously block legitimate payouts or allow sub-$1 cashouts. To fix:• In
src/components/Common/ActionList.tsxaround lines 61–65:
– Rename the raw token amount to something likeamountInToken.
– Fetch or inject the current USD price (e.g. via an existinguseTokenPricehook or context) and compute
ts const amountInToken = parseFloat(formatUnits(claimLinkData.amount, claimLinkData.tokenDecimals)) const amountInUsd = amountInToken * (tokenPrice ?? 0)
– Then enforce the $1 minimum onamountInUsd.• If your UI restricts send links to USD‐pegged tokens only, rename the variable to
amountInTokento avoid confusion and document that restriction; otherwise, integrate a price feed before applying the threshold.Mandatory fix
♻️ Duplicate comments (2)
src/components/Common/ActionList.tsx (2)
25-26: Code-split Daimo button and disable SSR to avoid hydration/TDZ issuesThe Daimo button is likely browser-only (payment SDKs often touch window). Code-splitting and disabling SSR reduce initial bundle and avoid SSR pitfalls. This also aligns with earlier guidance.
-import ActionListDaimoPayButton from './ActionListDaimoPayButton' +import dynamic from 'next/dynamic' +const ActionListDaimoPayButton = dynamic(() => import('./ActionListDaimoPayButton'), { ssr: false }) import { ACTION_METHODS, PaymentMethod } from '@/constants/actionlist.consts'
145-148: Pass the method into the Daimo button for better isolation and testabilityEven though the constants are centralized, passing the current
methodavoids hidden cross-module lookups and keeps the button self-contained.- {ACTION_METHODS.map((method) => { - if (flow === 'request' && method.id === 'exchange-or-wallet') { - return <ActionListDaimoPayButton key={method.id} /> - } + {ACTION_METHODS.map((method) => { + if (flow === 'request' && method.id === 'exchange-or-wallet') { + return <ActionListDaimoPayButton key={method.id} method={method} /> + }And update
ActionListDaimoPayButton.tsxto acceptmethod: PaymentMethod.
🧹 Nitpick comments (6)
src/components/Request/views/ExternalWalletFulfilMethods.tsx (2)
3-3: Avoid importing MethodCard from a heavy module; extract to a lightweight componentImporting
MethodCardfromActionList.tsxcan pull in that entire module’s client-side code and its dependencies. Consider extractingMethodCardinto its own file (e.g.,src/components/Common/MethodCard.tsx) so bothActionListand this view can import a minimal component.I can generate the extraction patch if you want.
36-41: Docstring typo: “fullfilling” → “fulfilling”Minor spelling fix for clarity and searchability.
- * Shows a list of available payment methods to choose from for claiming a send link or fullfilling a request link + * Shows a list of available payment methods to choose from for claiming a send link or fulfilling a request linksrc/components/Common/ActionList.tsx (1)
36-41: Docstring typo: “fullfilling” → “fulfilling”Minor spelling fix.
- * Shows a list of available payment methods to choose from for claiming a send link or fullfilling a request link + * Shows a list of available payment methods to choose from for claiming a send link or fulfilling a request linksrc/constants/actionlist.consts.ts (3)
5-11: Strengthen types: make icons immutable to prevent accidental mutationUse a readonly array for
iconsto better reflect constant data and help TS catch unintended writes.export interface PaymentMethod { - id: string + id: string title: string description: string - icons: any[] + icons: ReadonlyArray<any> soon: boolean }Optionally, define a dedicated
IconSourcetype matchingIconStack’s expectations if available.
13-39: Freeze ACTION_METHODS and keep it strictly typedMark the array as readonly and validate shape with
satisfies. This improves type safety, preserves literal ids, and avoids accidental mutation.-export const ACTION_METHODS: PaymentMethod[] = [ +export const ACTION_METHODS = [ { id: 'bank', title: 'Bank', description: 'EUR, USD, ARS (more coming soon)', icons: [ 'https://flagcdn.com/w160/ar.png', 'https://flagcdn.com/w160/de.png', 'https://flagcdn.com/w160/us.png', ], soon: false, }, { id: 'mercadopago', title: 'Mercado Pago', description: 'Instant transfers', icons: [MERCADO_PAGO_ICON], soon: true, }, { id: 'exchange-or-wallet', title: 'Exchange or Wallet', description: 'Binance, Coinbase, Metamask and more', icons: [binanceIcon, TRUST_WALLET_SMALL_LOGO, METAMASK_LOGO], soon: false, }, -] +] as const satisfies ReadonlyArray<PaymentMethod>
5-6: Optional: Centralize method ids as a union to remove magic strings across the appDefining a
PaymentMethodIdunion helps prevent typos in switches and lookups.export interface PaymentMethod { - id: string + id: PaymentMethodId title: string description: string icons: ReadonlyArray<any> soon: boolean } + +export type PaymentMethodId = 'bank' | 'mercadopago' | 'exchange-or-wallet'Note: adopting this will require small updates where
idis referenced.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
src/components/Common/ActionList.tsx(5 hunks)src/components/Request/views/ExternalWalletFulfilMethods.tsx(1 hunks)src/constants/actionlist.consts.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.301Z
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.
📚 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/Request/views/ExternalWalletFulfilMethods.tsx
📚 Learning: 2025-08-26T17:38:37.017Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/components/Common/ActionList.tsx:153-156
Timestamp: 2025-08-26T17:38:37.017Z
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/Request/views/ExternalWalletFulfilMethods.tsxsrc/constants/actionlist.consts.tssrc/components/Common/ActionList.tsx
📚 Learning: 2025-08-26T15:25:53.301Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.301Z
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/Common/ActionList.tsx
📚 Learning: 2025-08-22T07:28:32.260Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
Applied to files:
src/components/Common/ActionList.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/Common/ActionList.tsx
🧬 Code graph analysis (2)
src/components/Request/views/ExternalWalletFulfilMethods.tsx (1)
src/constants/actionlist.consts.ts (1)
PaymentMethod(5-11)
src/components/Common/ActionList.tsx (1)
src/constants/actionlist.consts.ts (2)
PaymentMethod(5-11)ACTION_METHODS(13-39)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (2)
src/components/Common/ActionList.tsx (1)
186-186: Type alignment looks goodSwitching
MethodCard’s prop toPaymentMethodaligns with the centralized type. No issues.src/constants/actionlist.consts.ts (1)
1-39: Overall: Good centralization of action methods and typesMoving the shared type and constants here eliminates prior cycles and improves reuse. The structure is clear and extensible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/TransactionDetails/TransactionDetailsReceipt.tsx (2)
206-207: Bug: fee can be a string;as numberdoesn’t coerce at runtime.If
transaction.feeis a string (per type),formatAmountreceives a string and may mis-render. Normalize first.-const feeDisplay = transaction.fee !== undefined ? formatAmount(transaction.fee as number) : 'N/A' +const feeNumeric = + transaction.fee !== undefined + ? (typeof transaction.fee === 'string' ? Number(transaction.fee) : transaction.fee) + : undefined +const feeDisplay = feeNumeric !== undefined && Number.isFinite(feeNumeric) ? formatAmount(feeNumeric as number) : 'N/A'
731-755: Gate the “Cancel link” button on the presence of setShowCancelLinkModal.Without this guard (and with the previous noop default removed), the button could still render and do nothing. Add the setter to the condition.
- {(transaction.extraDataForDrawer.originalType === EHistoryEntryType.SEND_LINK || - transaction.extraDataForDrawer.originalType === EHistoryEntryType.REQUEST) && - transaction.extraDataForDrawer.originalUserRole === EHistoryUserRole.SENDER && - setIsLoading && - onClose && ( + {(transaction.extraDataForDrawer.originalType === EHistoryEntryType.SEND_LINK || + transaction.extraDataForDrawer.originalType === EHistoryEntryType.REQUEST) && + transaction.extraDataForDrawer.originalUserRole === EHistoryUserRole.SENDER && + setIsLoading && + onClose && + setShowCancelLinkModal && (Optional: with the guard in place, you can drop
?.fromsetShowCancelLinkModal?.(true).
🧹 Nitpick comments (6)
src/components/TransactionDetails/TransactionDetailsReceipt.tsx (6)
17-17: Prefer type-only imports (and avoid default React import if unused at runtime).Use type-only imports for
Dispatch/SetStateActionto keep them erased at compile time. If you don’t rely onReactas a value (new JSX transform), you can also drop the default import; otherwise keep it. Minimal change:-import React, { Dispatch, SetStateAction, useMemo, useState } from 'react' +import React, { useMemo, useState, type Dispatch, type SetStateAction } from 'react'
40-50: Unify setter types: use Dispatch<SetStateAction> for setIsLoading.
setIsLoadingis a state setter semantically; type it the same assetShowCancelLinkModalfor accuracy and consistency.interface TransactionDetailsReceiptProps { transaction: TransactionDetails | null onClose?: () => void isLoading?: boolean - setIsLoading?: (isLoading: boolean) => void + setIsLoading?: Dispatch<SetStateAction<boolean>> contentRef?: React.RefObject<HTMLDivElement> transactionAmount?: string // dollarized amount of the transaction showCancelLinkModal?: boolean setShowCancelLinkModal?: Dispatch<SetStateAction<boolean>> className?: string }
191-204: Handle bigint safely when formatting amounts.
transaction.amountcan benumber | bigint. Asserting withas numberwon’t convert at runtime; useNumber()to handle bigint consistently.- amountDisplay = `$ ${formatAmount(transaction.amount as number)}` + amountDisplay = `$ ${formatAmount(Number(transaction.amount))}` ... - amountDisplay = `$ ${formatAmount(transaction.amount as number)}` + amountDisplay = `$ ${formatAmount(Number(transaction.amount))}`
296-305: Normalize cancelledDate to Date before formatting (consistency with other date fields).
cancelledDateisstring | Date. Unlike other places, here it’s not wrapped innew Date(...). Align for robustness:- <PaymentInfoRow - label="Cancelled" - value={formatDate(transaction.cancelledDate as Date)} - /> + <PaymentInfoRow + label="Cancelled" + value={formatDate(new Date(transaction.cancelledDate as any))} + />
908-913: Avoid non-null assertion on bridgeTransferId; guard and surface actionable error.
transaction.extraDataForDrawer?.bridgeTransferId!risks runtime errors if undefined. Guard and bail early, or disable the button when not present.-// first cancel the onramp -await cancelOnramp(transaction.extraDataForDrawer?.bridgeTransferId!) +// first cancel the onramp +const transferId = transaction.extraDataForDrawer?.bridgeTransferId +if (!transferId) { + captureException(new Error('Missing bridgeTransferId while canceling bank request')) + setIsLoading(false) + return +} +await cancelOnramp(transferId)
951-982: Optional: NormalizeCancelSendLinkModalprop name to camelCaseWe verified that in
src/components/Global/CancelSendLinkModal/index.tsxthe interface and destructured prop are currently defined as:interface CancelSendLinkModalProps { showCancelLinkModal: boolean setshowCancelLinkModal: (show: boolean) => void … } const CancelSendLinkModal = ({ showCancelLinkModal, setshowCancelLinkModal, … }) => { … }All call sites (e.g. in
TransactionDetailsReceipt.tsxandSuccess.link.send.view.tsx) correctly passsetshowCancelLinkModal. However, this deviates from the standard camelCase convention (which would besetShowCancelLinkModal) and can hinder editor auto-complete and readability.If you’d like to align with React naming conventions, consider renaming the prop across the board:
• Modal definition (
src/components/Global/CancelSendLinkModal/index.tsx)interface CancelSendLinkModalProps { - setshowCancelLinkModal: (show: boolean) => void + setShowCancelLinkModal: (show: boolean) => void } const CancelSendLinkModal = ({ - setshowCancelLinkModal, + setShowCancelLinkModal, … }) => { … }• Call sites
src/components/TransactionDetails/TransactionDetailsReceipt.tsxsrc/components/Send/link/views/Success.link.send.view.tsx- <CancelSendLinkModal - showCancelLinkModal={…} - setshowCancelLinkModal={setShowCancelLinkModal} + <CancelSendLinkModal + showCancelLinkModal={…} + setShowCancelLinkModal={setShowCancelLinkModal} … />If you’d rather preserve the existing API for now, this change isn’t strictly required—feel free to ignore this suggestion.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
src/components/TransactionDetails/TransactionDetailsReceipt.tsx(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.260Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.301Z
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.
🧬 Code graph analysis (1)
src/components/TransactionDetails/TransactionDetailsReceipt.tsx (1)
src/components/TransactionDetails/transactionTransformer.ts (1)
TransactionDetails(40-120)
🔇 Additional comments (1)
src/components/TransactionDetails/TransactionDetailsReceipt.tsx (1)
419-675: Deposit instructions: great UX touches.The expandable bank details, copy-to-clipboard affordances, and contextual MoreInfo tooltip are cohesive and well-structured. Nice work on the conditional EU/US layouts.
src/components/TransactionDetails/TransactionDetailsReceipt.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/components/Payment/PaymentForm/index.tsx (3)
547-549: Fix mismatch in insufficient-balance detection (prevents Add Funds CTA and wrong alert mapping).Balance-check sets errors like 'Insufficient balance' or 'Insufficient balance in connected wallet', but the UI checks for "You don't have enough balance." Use a consistent predicate.
@@ - const isInsufficientBalanceError = useMemo(() => { - return error?.includes("You don't have enough balance.") - }, [error]) + const isInsufficientBalanceError = useMemo(() => { + return !!error && (/\binsufficient balance\b/i.test(error) || error.includes("You don't have enough balance.")) + }, [error]) @@ - {!daimoError && error && ( - <ErrorAlert - description={ - error.includes("You don't have enough balance.") - ? 'Not enough balance to fulfill this request with Peanut' - : error - } - /> - )} + {!daimoError && error && ( + <ErrorAlert + description={ + isInsufficientBalanceError + ? 'Not enough balance to fulfill this request with Peanut' + : error + } + /> + )}Also applies to: 763-771
300-309: Parse user-entered numbers safely (commas cause wrong amounts and NaN propagation).TokenAmountInput returns formatted decimals (e.g., "1,234.56"). Use a helper to strip commas before numeric ops to avoid undercounting (parseFloat('1,000') => 1) and NaN.
Add once (anywhere inside component scope, e.g., after state hooks):
const parseDecimal = (v: string | number | undefined | null) => Number(String(v ?? '').replace(/,/g, ''));Apply diffs:
@@ - } else if (isActivePeanutWallet) { - amountIsSet = !!inputTokenAmount && parseFloat(inputTokenAmount) > 0 + } else if (isActivePeanutWallet) { + amountIsSet = !!inputTokenAmount && parseDecimal(inputTokenAmount) > 0 @@ - amountIsSet = - (!!inputTokenAmount && parseFloat(inputTokenAmount) > 0) || (!!usdValue && parseFloat(usdValue) > 0) + amountIsSet = + (!!inputTokenAmount && parseDecimal(inputTokenAmount) > 0) || (!!usdValue && parseDecimal(usdValue) > 0)@@ - if (!inputTokenAmount || parseFloat(inputTokenAmount) <= 0) { + if (!inputTokenAmount || parseDecimal(inputTokenAmount) <= 0) { console.error('Invalid amount entered') dispatch(paymentActions.setError('Please enter a valid amount')) return }@@ - tokenAmount = (parseFloat(inputUsdValue) / requestedTokenPrice).toString() + tokenAmount = (parseDecimal(inputUsdValue || usdValue) / requestedTokenPrice).toString()@@ - if (isPintaReq && inputTokenAmount) { - dispatch(paymentActions.setBeerQuantity(Number(inputTokenAmount))) + if (isPintaReq && inputTokenAmount) { + dispatch(paymentActions.setBeerQuantity(parseDecimal(inputTokenAmount)))@@ - if (selectedTokenPrice) { - setUsdValue((parseFloat(inputTokenAmount) * selectedTokenPrice).toString()) + if (selectedTokenPrice) { + setUsdValue((parseDecimal(inputTokenAmount) * selectedTokenPrice).toString())@@ - if (isPintaReq) { - dispatch(paymentActions.setBeerQuantity(Number(inputTokenAmount))) + if (isPintaReq) { + dispatch(paymentActions.setBeerQuantity(parseDecimal(inputTokenAmount)))@@ - const numericAmount = parseFloat(inputTokenAmount) - if (isNaN(numericAmount) || numericAmount <= 0) { + const numericAmount = parseDecimal(inputTokenAmount) + if (!Number.isFinite(numericAmount) || numericAmount <= 0) { @@ - return ( - !inputTokenAmount || - isNaN(parseFloat(inputTokenAmount)) || - parseFloat(inputTokenAmount) <= 0 || + return ( + !inputTokenAmount || + !Number.isFinite(parseDecimal(inputTokenAmount)) || + parseDecimal(inputTokenAmount) <= 0 || !selectedTokenAddress || !selectedChainID || isProcessing )Also add usdValue to handleInitiatePayment deps (since we used it for conversion):
@@ - requestedTokenPrice, + requestedTokenPrice, + usdValue,Also applies to: 383-388, 416-417, 520-523, 525-530, 540-545, 556-571
280-286: Don’t overwrite token amount with USD; only set the USD field.This flips the token input to show USD text, likely confusing users and breaking validation that expects token units.
- const usdValue = formatAmount(tokenAmount * priceData.price) - setInputTokenAmount(usdValue) - setUsdValue(usdValue) + const usdValue = formatAmount(tokenAmount * priceData.price) + setUsdValue(usdValue)
♻️ Duplicate comments (1)
src/components/Payment/PaymentForm/index.tsx (1)
175-183: Resolved: Daimo errors are no longer cleared in the balance-check effect.Clearing daimoError only on mount/recipient change matches prior guidance; prevents flicker.
🧹 Nitpick comments (1)
src/components/Payment/PaymentForm/index.tsx (1)
135-136: Remove unused isDepositRequest (and its dependency).It’s defined but not used; transactionType derives from isExternalWalletFlow.
- const isDepositRequest = searchParams.get('action') === 'deposit' @@ - isDepositRequest, isConnected,Also applies to: 449-468
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
package.json(1 hunks)src/app/[...recipient]/client.tsx(2 hunks)src/components/Payment/PaymentForm/index.tsx(5 hunks)
✅ Files skipped from review due to trivial changes (1)
- package.json
🚧 Files skipped from review as they are similar to previous changes (1)
- src/app/[...recipient]/client.tsx
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.281Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
📚 Learning: 2025-08-22T07:28:32.281Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:522-545
Timestamp: 2025-08-22T07:28:32.281Z
Learning: In `src/components/Payment/PaymentForm/index.tsx`, the `handleCompleteDaimoPayment` function is only for updating payment status in the backend after a successful Daimo payment. Payment success/failure is handled by Daimo itself, so try/catch error handling and error display are not needed for backend sync failures - users shouldn't see errors if payment succeeded but database update failed.
Applied to files:
src/components/Payment/PaymentForm/index.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/Payment/PaymentForm/index.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/Payment/PaymentForm/index.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/PaymentForm/index.tsx
📚 Learning: 2024-12-02T17:19:18.532Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Applied to files:
src/components/Payment/PaymentForm/index.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/PaymentForm/index.tsx
📚 Learning: 2024-10-29T12:19:41.968Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Global/TokenAmountInput/index.tsx:23-30
Timestamp: 2024-10-29T12:19:41.968Z
Learning: In the `TokenAmountInput` component (`src/components/Global/TokenAmountInput/index.tsx`), when the 'Max' button is clicked, we intentionally set the input denomination to 'TOKEN' because we are setting the value as token.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2024-10-29T12:20:47.207Z
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Create/Link/Input.view.tsx:244-248
Timestamp: 2024-10-29T12:20:47.207Z
Learning: In the `TokenAmountInput` component within `src/components/Global/TokenAmountInput/index.tsx`, when `balance` is undefined, the `maxValue` prop should be set to an empty string `''`.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
📚 Learning: 2025-08-22T07:25:59.304Z
Learnt from: Zishan-7
PR: peanutprotocol/peanut-ui#1104
File: src/components/Payment/PaymentForm/index.tsx:596-600
Timestamp: 2025-08-22T07:25:59.304Z
Learning: The `TokenAmountInput` component in `src/components/Global/TokenAmountInput/` always returns decimal strings (e.g., "1,234.56"), not base units. When passing these values to external APIs like Daimo's `toUnits` prop, simply stripping commas with `.replace(/,/g, '')` is sufficient.
Applied to files:
src/components/Payment/PaymentForm/index.tsx
🧬 Code graph analysis (1)
src/components/Payment/PaymentForm/index.tsx (1)
src/hooks/usePaymentInitiator.ts (1)
usePaymentInitiator(80-831)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Deploy-Preview
- GitHub Check: test
🔇 Additional comments (1)
src/components/Payment/PaymentForm/index.tsx (1)
684-687: Good: propagate USD value to the store alongside local state.Keeps Redux in sync with the input component without extra effects.
* feat: handle send link claims to bank account for peanut users (#1078) * reafactor: create reusable country list component and use it for all the flows * feat: reusable user accounts components * feat: handle different cases based on kyc status for bank claim * fix: account creation * chore: add docstring to hooks * chore: better comments for bank flow manager * fix: kyc modal closing after tos acceptance issue * fix: remove bank acc caching from withdraw flow * fix: update confirm claim modal copy * fix: remove bank acc caching from claim flow * fix: navheader title * remove duplicate debounce code and use `useDebounce` hook instead (#1079) * Landing page v2.1 (#1089) * lpv2.1 part 1 * Add exchange widget * add and integrate exchange API * add yourMoney component bg * update landing countries svg * integrate frankfurter API * fixes and improvements * decrease hero section height * allow max 2 decimal places * Add `/exchange` route * fix: overlay * make destination amount editable and bugg fixes * some fixes & currency improvements * crucial commit * fix checkmark, font size and weight --------- Co-authored-by: Hugo Montenegro <[email protected]> * [TASK-13186] refactor: use networkName instead of axelarChainName (#1095) * refactor: use networkName instead of axelarChainName * fix: types * fix: onramp currency (#1096) * fix: stretched favicon (#1099) * [TASK-13971] fix: scientific notation in eip681 parsing (#1097) * fix: scientific notation in eip681 parsing * fix: qr handling tests * fix: peanut sdk mock * pull iban hotfix (#1100) * fix: claim flow bugs (#1102) * fix: cross chain claim * fix: full name issue on confirm bank claim view * fix: back navigation on desktop views * Fix back button not working on /profile (#1101) * Fix back button not working * fix public profile page * extract internal navigation logic to utility function * fix: send link claims to us bank accounts (#1108) * fix: usa bank account claims * fix: show bank account details in confirm claim view * Sync Landing page changes (#1111) * reduce clouds size and update font * fix: hero section responsiveness issue * fix: formatting errors * add currency animation * fix: us bank claims after kyc for logged in users (#1112) * fix: trim account form inputs for spaces (#1114) * [TASK-14107] fix: don't allow claiming on xChain if route is not found (#1115) * fix: don't allow claiming on xChain if route is not found * fix(claim): use correct decimals for min receive amount * feat: handle redirect uri when on unsupported browsers (#1117) * feat: handle redirect uri when on unsupported browsers * fix: confirm bank claim ui rows for iban guest claim * remove animation (#1118) * Prod to staging (#1124) * HOTFIX - IBAN country detection and incorrect bank acc details (#1094) * Fix: Iban country detection and incorrect bank acc details * Fix: update IBAN country validation to use correct locale string comparison * add validations for US and mexican bank accounts * fix typo * fix claim flow and create a reusable function for getting 3 letter code * fix country code mismatch * fix: show error below input field * remove unnecessary checks * remove unnecessary CLABE check * Prod LP v2.1 (#1098) * feat: lpv2.1 * fix: gigaclouds, font and exchange widget * fixes and improvements * remove duplicate export * remove unused component * Fix: Landing page hero section responsiveness issue (#1107) * fix: hero section responsiveness issue * fix: stars position * fix height on desktop * remove unused code * fix margins (#1113) * [TASK-14052] Prod release 105 (#1122) * feat: handle send link claims to bank account for peanut users (#1078) * reafactor: create reusable country list component and use it for all the flows * feat: reusable user accounts components * feat: handle different cases based on kyc status for bank claim * fix: account creation * chore: add docstring to hooks * chore: better comments for bank flow manager * fix: kyc modal closing after tos acceptance issue * fix: remove bank acc caching from withdraw flow * fix: update confirm claim modal copy * fix: remove bank acc caching from claim flow * fix: navheader title * remove duplicate debounce code and use `useDebounce` hook instead (#1079) * Landing page v2.1 (#1089) * lpv2.1 part 1 * Add exchange widget * add and integrate exchange API * add yourMoney component bg * update landing countries svg * integrate frankfurter API * fixes and improvements * decrease hero section height * allow max 2 decimal places * Add `/exchange` route * fix: overlay * make destination amount editable and bugg fixes * some fixes & currency improvements * crucial commit * fix checkmark, font size and weight --------- Co-authored-by: Hugo Montenegro <[email protected]> * [TASK-13186] refactor: use networkName instead of axelarChainName (#1095) * refactor: use networkName instead of axelarChainName * fix: types * fix: onramp currency (#1096) * fix: stretched favicon (#1099) * [TASK-13971] fix: scientific notation in eip681 parsing (#1097) * fix: scientific notation in eip681 parsing * fix: qr handling tests * fix: peanut sdk mock * pull iban hotfix (#1100) * fix: claim flow bugs (#1102) * fix: cross chain claim * fix: full name issue on confirm bank claim view * fix: back navigation on desktop views * Fix back button not working on /profile (#1101) * Fix back button not working * fix public profile page * extract internal navigation logic to utility function * fix: send link claims to us bank accounts (#1108) * fix: usa bank account claims * fix: show bank account details in confirm claim view * Sync Landing page changes (#1111) * reduce clouds size and update font * fix: hero section responsiveness issue * fix: formatting errors * add currency animation * fix: us bank claims after kyc for logged in users (#1112) * fix: trim account form inputs for spaces (#1114) * [TASK-14107] fix: don't allow claiming on xChain if route is not found (#1115) * fix: don't allow claiming on xChain if route is not found * fix(claim): use correct decimals for min receive amount * feat: handle redirect uri when on unsupported browsers (#1117) * feat: handle redirect uri when on unsupported browsers * fix: confirm bank claim ui rows for iban guest claim * remove animation (#1118) * fix: formatting --------- Co-authored-by: Kushagra Sarathe <[email protected]> Co-authored-by: Mohd Zishan <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]> --------- Co-authored-by: Mohd Zishan <[email protected]> Co-authored-by: Kushagra Sarathe <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]> * fix: dates in receipts (#1105) * [TASK-13865] fix: add tx info on receipt (#1109) * fix: add tx info on receipt * feat: use address explorer url for depositor address * fix(history): check befroe creating address explorer url * Fix: logged in users have to re-login after installing PWA (#1103) * store `LOCAL_STORAGE_WEB_AUTHN_KEY` in cookies * ensure backward compatibility * refactor: move syncLocalStorageToCookie call into useEffect for better lifecycle management * feat: links v2.1 req fulfilment flows (#1085) * reafactor: create reusable country list component and use it for all the flows * feat: reusable user accounts components * feat: handle different cases based on kyc status for bank claim * fix: account creation * chore: add docstring to hooks * chore: better comments for bank flow manager * fix: kyc modal closing after tos acceptance issue * fix: remove bank acc caching from withdraw flow * fix: update confirm claim modal copy * fix: remove bank acc caching from claim flow * fix: navheader title * feat: req fulfillment exchange flow * fix: header title * feat: req fulfillment using connected external wallet * fix: navigation and ui * fix: file name * feat: abstract reusbale components from onramp flow for bank fulfilment * feat: handle onramp creation for request fulfilment * feat: reusable verification component * feat: handle bank req fulfilment for peanut users * fix: show all supported countries in req/claim bank flow * feat: show google-pay/apple-pay based on users device * fix: resolve pr review comments * fix: exhange rate hook fallback value * fix: resolve pr comments * Feat: Collect tg username (#1110) * feat: collect tg username * update animations * fix api route * add thinking peanut gif * fix typescript errors * fix typo and reset telegramHandle field on logout * fix: spacing and describe regex rules * add missing export * feat: add sound in success views (#1127) * feat: handle history ui changes for links v2.1 (#1106) * reafactor: create reusable country list component and use it for all the flows * feat: reusable user accounts components * feat: handle different cases based on kyc status for bank claim * fix: account creation * chore: add docstring to hooks * chore: better comments for bank flow manager * fix: kyc modal closing after tos acceptance issue * fix: remove bank acc caching from withdraw flow * fix: update confirm claim modal copy * fix: remove bank acc caching from claim flow * fix: navheader title * feat: req fulfillment exchange flow * fix: header title * feat: req fulfillment using connected external wallet * fix: navigation and ui * fix: file name * feat: abstract reusbale components from onramp flow for bank fulfilment * feat: handle onramp creation for request fulfilment * feat: reusable verification component * feat: handle bank req fulfilment for peanut users * fix: show all supported countries in req/claim bank flow * feat: show google-pay/apple-pay based on users device * feat: handle bank send link claim hisotry for peanut users * feat: handle history ui changes for request fulfillment using bank accounts * fix: resolve pr review comments * fix: exhange rate hook fallback value * fix: resolve pr comments * fix: review comments * feat: badges updates (#1119) * feat: badges updates and hook to check for interactions * feat: handle badges for receipts and drawer header * feat: handle badges on request and send flow * feat: tooltip for badges * fix: tooltip positioning * fix: associate a external wallet claim to user if logged in (#1126) * fix: associate a external wallet claim to user if logged in * chore: fix comments * [TASK-14113] fix: handle rpc outage when creating sendlinks (#1120) * HOTFIX - IBAN country detection and incorrect bank acc details (#1094) * Fix: Iban country detection and incorrect bank acc details * Fix: update IBAN country validation to use correct locale string comparison * add validations for US and mexican bank accounts * fix typo * fix claim flow and create a reusable function for getting 3 letter code * fix country code mismatch * fix: show error below input field * remove unnecessary checks * remove unnecessary CLABE check * Prod LP v2.1 (#1098) * feat: lpv2.1 * fix: gigaclouds, font and exchange widget * fixes and improvements * remove duplicate export * remove unused component * Fix: Landing page hero section responsiveness issue (#1107) * fix: hero section responsiveness issue * fix: stars position * fix height on desktop * remove unused code * fix margins (#1113) * fix: handle rpc outage when creating sendlinks * fix: formatting * fix: parallelize geting deposit index --------- Co-authored-by: Mohd Zishan <[email protected]> * Integrate Daimo Pay (#1104) * add daimo pay * minor improvements * cleanup and add success state * resolve dependency issues * fix: formatting * fix: recent methods redirection * add functions for daimo payment in request fulfilment flow * Integrate daimo in request fulfilment flow * remove hardcoded address * add separate arbitrum usdc flow for deposits * Add risk modal * fix overlay blur * Enhance loading state indication in payment process * Add payer's address in deposit history entry * Add validation * add error handling * remove action and move logic to API route * fix errors * fix: request flow * fix: validation * fixes * add daimo flow in country specific method * fix: slider not working on first attempt * filter supported networks * create reusable daimo button * remove space * remove route.ts file and move logic to server actions * fix: infinite loading edge case * update api and remove delay * fix: layout shift * fix: shadow * update function name * fix: success receipt (#1129) * fix: roboto font not working (#1130) * fix: allow cancel link from the claim page * fix: allow canceling links from the shared receipt (#1134) * fix: send flow cta (#1133) * fix: send flow ctas * fix: success sound on send flow * fix: disabled btn on req pay flow * Fix Daimo bugs (#1132) * fix: bugs * fix cross chain deposit details not correct * fix: request screen UI * add loading state * remove old daimo button * fix: missing dependencies and dead code * add try catch finally block * remove clear Daimo errors inside the balance-check effect * fix copy * minor fixes * move ACTION_METHODS to constants file to remove circular dependency * fix: circular dependency * fix ts error * update daimo version * [TASK-14095] feat: add fallback transport to viem clients (#1131) * feat: add fallback transport to viem clients Use viem fallback transport to handle RPC errors and fallback to other providers. * style: Apply prettier formatting * test: add fallback to viem mock * fix: external claim links history ui + badges fix (#1136) * fix: external claim links history ui + badges fix * fix: resolve codderrabbit suggestions * fix: coderrabbit comment on state stale * Fix: disable add money button on default state + disable sound on IOS (#1145) * fix: add money success screen shows usernmae * disable add money button in default state * disable sound on IOS * Fix: daimo bugs part2 (#1149) * fix: black screen on IOS * fix: sucess screen showed without paying - add money flow * fix currency and double $ in txn history * fix: x-chan token size and add API to get missing token icons * fix: req fulfilment * add default value to tokenData * fix: move useeffect above transaction null check * format amount * fix: space between currency and amount (#1135) * Lock token to USDC arb for peanut ens username (#1128) * Lock token to USDC arb for peanut ens username * add comment * revert variable declaration for sanitizedValue in GeneralRecipientInput component * fix add regex to strip only from the end * [TASK-13900] Feat/kyc modal changes (#1137) * fix: pointer events * fix: modal btns not working on mobile * add missing dependency * remove close button * Chore/prod to dev 106 (#1152) * HOTFIX - IBAN country detection and incorrect bank acc details (#1094) * Fix: Iban country detection and incorrect bank acc details * Fix: update IBAN country validation to use correct locale string comparison * add validations for US and mexican bank accounts * fix typo * fix claim flow and create a reusable function for getting 3 letter code * fix country code mismatch * fix: show error below input field * remove unnecessary checks * remove unnecessary CLABE check * Prod LP v2.1 (#1098) * feat: lpv2.1 * fix: gigaclouds, font and exchange widget * fixes and improvements * remove duplicate export * remove unused component * Fix: Landing page hero section responsiveness issue (#1107) * fix: hero section responsiveness issue * fix: stars position * fix height on desktop * remove unused code * fix margins (#1113) * [TASK-14052] Prod release 105 (#1122) * feat: handle send link claims to bank account for peanut users (#1078) * reafactor: create reusable country list component and use it for all the flows * feat: reusable user accounts components * feat: handle different cases based on kyc status for bank claim * fix: account creation * chore: add docstring to hooks * chore: better comments for bank flow manager * fix: kyc modal closing after tos acceptance issue * fix: remove bank acc caching from withdraw flow * fix: update confirm claim modal copy * fix: remove bank acc caching from claim flow * fix: navheader title * remove duplicate debounce code and use `useDebounce` hook instead (#1079) * Landing page v2.1 (#1089) * lpv2.1 part 1 * Add exchange widget * add and integrate exchange API * add yourMoney component bg * update landing countries svg * integrate frankfurter API * fixes and improvements * decrease hero section height * allow max 2 decimal places * Add `/exchange` route * fix: overlay * make destination amount editable and bugg fixes * some fixes & currency improvements * crucial commit * fix checkmark, font size and weight --------- Co-authored-by: Hugo Montenegro <[email protected]> * [TASK-13186] refactor: use networkName instead of axelarChainName (#1095) * refactor: use networkName instead of axelarChainName * fix: types * fix: onramp currency (#1096) * fix: stretched favicon (#1099) * [TASK-13971] fix: scientific notation in eip681 parsing (#1097) * fix: scientific notation in eip681 parsing * fix: qr handling tests * fix: peanut sdk mock * pull iban hotfix (#1100) * fix: claim flow bugs (#1102) * fix: cross chain claim * fix: full name issue on confirm bank claim view * fix: back navigation on desktop views * Fix back button not working on /profile (#1101) * Fix back button not working * fix public profile page * extract internal navigation logic to utility function * fix: send link claims to us bank accounts (#1108) * fix: usa bank account claims * fix: show bank account details in confirm claim view * Sync Landing page changes (#1111) * reduce clouds size and update font * fix: hero section responsiveness issue * fix: formatting errors * add currency animation * fix: us bank claims after kyc for logged in users (#1112) * fix: trim account form inputs for spaces (#1114) * [TASK-14107] fix: don't allow claiming on xChain if route is not found (#1115) * fix: don't allow claiming on xChain if route is not found * fix(claim): use correct decimals for min receive amount * feat: handle redirect uri when on unsupported browsers (#1117) * feat: handle redirect uri when on unsupported browsers * fix: confirm bank claim ui rows for iban guest claim * remove animation (#1118) * fix: formatting --------- Co-authored-by: Kushagra Sarathe <[email protected]> Co-authored-by: Mohd Zishan <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]> * fix: bank claim flow runtime error (#1138) * hotfix: make iban non optional (#1139) * fix: bank claim flow runtime error * fix: dont have iban as optional * fix: merge conflicts * fix: merge external account with bank details (#1140) * fix: add id to external account (#1142) * added tg footer (#1144) * Hotfix : add missing countries - claim as guest flow (#1146) * fix: add missing countries * remove duplicate comment * fix: show error on dynamic bank account form (#1147) * fix: Invalid IBAN for UK (#1151) --------- Co-authored-by: Mohd Zishan <[email protected]> Co-authored-by: Kushagra Sarathe <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]> * [TASK-13950] Fix: incorrect token amount on second withdraw (#1150) * fix: incorrect token amount on second withdraw * move `resetTokenContextProvider()` to unmount callback * fix: transaction explorer url for deposits * fix: history skeleton copy * save token and chain details for cross chain req-fulfilments (#1154) * fix: send links history ui for senders pov when claimed to bank accounts (#1156) * fix: sort action list methods * fix: send links claimed to bank accounts history ui for senders pov * fix: issues for request link paying with bank (#1158) - Specify recipient when creating onramp for request fulfillment - Use correct amount depending on currency * fix: stop cleaning error by bic field (#1159) We now always clear before starting submission and also bic field will always show, so that logic is not needed anymore. * fix: claim country currency and amount, fallback to $ (#1164) * feat: show local bank currency incase of bank claims * fix: activity rows for sender's send link history * fix: verification modal when claiming * fix: state issue when new user tries to claim to bank * fix: request pay copy (#1165) * fix: close kyc modal btn (#1166) * Fix testing github action (#1167) * chore: remove prettier action When commiting it clashes with signature verification rules * chore: update test action setup version * fix: install first * fix: actually make sure that cancelledDate is a Date (#1170) * fix: icon and margin (#1171) * Hide pay with wallet button in Daimo component (#1172) * hide pay with wallet button * improve targeted css approach * Fix: Daimo bug and activity receipt bug (#1175) * sligify chain name * fix: stale state issue * hide row if tokenData is not present * Fix/conflicts (#1177) * HOTFIX - IBAN country detection and incorrect bank acc details (#1094) * Fix: Iban country detection and incorrect bank acc details * Fix: update IBAN country validation to use correct locale string comparison * add validations for US and mexican bank accounts * fix typo * fix claim flow and create a reusable function for getting 3 letter code * fix country code mismatch * fix: show error below input field * remove unnecessary checks * remove unnecessary CLABE check * Prod LP v2.1 (#1098) * feat: lpv2.1 * fix: gigaclouds, font and exchange widget * fixes and improvements * remove duplicate export * remove unused component * Fix: Landing page hero section responsiveness issue (#1107) * fix: hero section responsiveness issue * fix: stars position * fix height on desktop * remove unused code * fix margins (#1113) * [TASK-14052] Prod release 105 (#1122) * feat: handle send link claims to bank account for peanut users (#1078) * reafactor: create reusable country list component and use it for all the flows * feat: reusable user accounts components * feat: handle different cases based on kyc status for bank claim * fix: account creation * chore: add docstring to hooks * chore: better comments for bank flow manager * fix: kyc modal closing after tos acceptance issue * fix: remove bank acc caching from withdraw flow * fix: update confirm claim modal copy * fix: remove bank acc caching from claim flow * fix: navheader title * remove duplicate debounce code and use `useDebounce` hook instead (#1079) * Landing page v2.1 (#1089) * lpv2.1 part 1 * Add exchange widget * add and integrate exchange API * add yourMoney component bg * update landing countries svg * integrate frankfurter API * fixes and improvements * decrease hero section height * allow max 2 decimal places * Add `/exchange` route * fix: overlay * make destination amount editable and bugg fixes * some fixes & currency improvements * crucial commit * fix checkmark, font size and weight --------- Co-authored-by: Hugo Montenegro <[email protected]> * [TASK-13186] refactor: use networkName instead of axelarChainName (#1095) * refactor: use networkName instead of axelarChainName * fix: types * fix: onramp currency (#1096) * fix: stretched favicon (#1099) * [TASK-13971] fix: scientific notation in eip681 parsing (#1097) * fix: scientific notation in eip681 parsing * fix: qr handling tests * fix: peanut sdk mock * pull iban hotfix (#1100) * fix: claim flow bugs (#1102) * fix: cross chain claim * fix: full name issue on confirm bank claim view * fix: back navigation on desktop views * Fix back button not working on /profile (#1101) * Fix back button not working * fix public profile page * extract internal navigation logic to utility function * fix: send link claims to us bank accounts (#1108) * fix: usa bank account claims * fix: show bank account details in confirm claim view * Sync Landing page changes (#1111) * reduce clouds size and update font * fix: hero section responsiveness issue * fix: formatting errors * add currency animation * fix: us bank claims after kyc for logged in users (#1112) * fix: trim account form inputs for spaces (#1114) * [TASK-14107] fix: don't allow claiming on xChain if route is not found (#1115) * fix: don't allow claiming on xChain if route is not found * fix(claim): use correct decimals for min receive amount * feat: handle redirect uri when on unsupported browsers (#1117) * feat: handle redirect uri when on unsupported browsers * fix: confirm bank claim ui rows for iban guest claim * remove animation (#1118) * fix: formatting --------- Co-authored-by: Kushagra Sarathe <[email protected]> Co-authored-by: Mohd Zishan <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]> * fix: bank claim flow runtime error (#1138) * hotfix: make iban non optional (#1139) * fix: bank claim flow runtime error * fix: dont have iban as optional * fix: merge conflicts * fix: merge external account with bank details (#1140) * fix: add id to external account (#1142) * added tg footer (#1144) * Hotfix : add missing countries - claim as guest flow (#1146) * fix: add missing countries * remove duplicate comment * fix: show error on dynamic bank account form (#1147) * fix: Invalid IBAN for UK (#1151) --------- Co-authored-by: Mohd Zishan <[email protected]> Co-authored-by: Juan José Ramírez <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]> --------- Co-authored-by: Mohd Zishan <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]> Co-authored-by: Juan José Ramírez <[email protected]> Co-authored-by: Juan José Ramírez <[email protected]> Co-authored-by: Hugo Montenegro <[email protected]>
Contributes to tasks -
TASK-14251
TASK-14252
TASK-14247
TASK-14248
TASK-14250
TASK-14253
Please note - Cross chain txn bug fix (TASK-14254) will only work after the backend PR is merged