Skip to content

Prod Release 135#1803

Closed
jjramirezn wants to merge 58 commits into
mainfrom
dev
Closed

Prod Release 135#1803
jjramirezn wants to merge 58 commits into
mainfrom
dev

Conversation

@jjramirezn

Copy link
Copy Markdown
Contributor

No description provided.

jjramirezn and others added 30 commits March 18, 2026 12:18
…ages

- Timeout errors now throw 'Service temporarily unavailable' instead of raw URL + ms
- Network errors throw 'Something went wrong' instead of technical details
- Original errors preserved in .cause for debugging
- Sentry reporting unchanged
…errors

[TASK-18804] fix: replace technical timeout/network errors with user-friendly mess…
- Detect onboarding-incomplete errors (fund origin, profile incomplete)
- Auto-generate onboarding URL and redirect user to complete their profile
- Return URL set to current page so user lands back in withdraw flow
- Fallback message if onboarding URL generation fails
- Tighten error matching (remove broad 'onboarding', use 'onboarding required')
- Add handleOnboardingError to useCallback deps
- Wire isRedirectingToOnboarding into button (disabled + loading + 'Redirecting...')
- Check result.message in withdraw path for onboarding errors
…errors

[TASK-18803] fix: redirect to onboarding when manteca reports missing fund origin
When users tap weird/uninhabited countries (Antarctica, etc.) in the
country selector, show a fun modal with a custom image and humorous
caption instead of the normal flow.

- New EasterEggModal component (reuses base Modal)
- Easter egg countries bypass disabled state and "Soon" badge
- Added to design system page for preview
- Only Antarctica active for now (other images ready to enable)
…am on withdraw

- Pass enforceSupportedCountries to CountryList when coming from send flow
  (unsupported countries show 'Soon' badge and are disabled)
- Validate country param on withdraw/[country]/bank — redirect to /withdraw
  if country is not bridge-supported
- Validate country param on withdraw/manteca — redirect to /withdraw
  if country is not in MANTECA_COUNTRIES_CONFIG
…lidation

[TASK-18810] fix: restrict send flow to supported countries + validate country par…
Previously only DIRECT_SEND and completed REQUEST triggered a balance
refetch. Added explicit list of balance-affecting transaction types:
DEPOSIT, WITHDRAW, BRIDGE_OFFRAMP/ONRAMP, MANTECA_OFFRAMP/ONRAMP,
SEND_LINK, BANK_SEND_LINK_CLAIM, and PERK_REWARD.

Non-balance-affecting types (e.g. CASHOUT, QR payments with separate
flows) are excluded. REQUEST still requires COMPLETED status.
…ok cooldown

- ZeroDev: Remove Polygon check (not used in prod), use eth_supportedEntryPoints
  instead of eth_chainId for bundler (mandatory ERC-4337 method)
- RPC: Critical vs non-critical chain distinction (Polygon down = degraded, not unhealthy).
  Added public fallback RPCs for Polygon. Parallel provider testing.
- Main orchestrator: 30-min Discord webhook cooldown to prevent notification spam.
  Use plain fetch instead of fetchWithSentry to stop health check errors polluting Sentry.
- Backend: Use /healthz endpoint instead of /users/username/hugo
fix: improve health checks — false positives, critical chain logic, webhook cooldown
- Hoist BALANCE_AFFECTING_TYPES to module scope (avoid re-allocation per WS event)
- Type as EHistoryEntryType[] instead of string[] for compile-time safety
- Add BRIDGE_GUEST_OFFRAMP to balance-affecting types
- Only refresh balance on COMPLETED status (not PENDING/FAILED)
- Remove !entry.status fallback that treated missing status as completed
- REQUEST still correctly requires explicit COMPLETED status
…r-transaction

[TASK-18801] fix: refresh balance on all balance-affecting websocket history entries
- Replace peanut-holding-mobile.svg with peanut-club.png on install screens
- Use .src accessor for PNG StaticImageData import
- Remove unused mascot assets (0 references on dev):
  peanutman-cheering.png, peanutman-cheering.svg,
  peanutman-happy.svg, peanutman-presenting.svg,
  peanutman-sad.svg, peanut-holding-mobile.svg
…cot-v2

chore: replace install mascot with peanut-club, remove unused assets
…olor-v2

fix: use bg-gray-200 for help page skeleton loading
Added images and captions for Bouvet Island, Christmas Island,
Cocos Islands, South Georgia, Heard Island, Pitcairn Islands,
and Tokelau. Each gets a unique image and humorous caption.
iframe no longer unmounts on close, eliminating 4-5s reload delay.
added touch drag-to-dismiss on handle bar.
dual-layer clippath for black-to-white text transition on hold.
reduced icon size to max 15% container width for narrow devices.
kushagrasarathe and others added 24 commits March 20, 2026 20:29
- move paymentMethodName useMemo above the isProviderDisabled conditional
  to fix Rules of Hooks violation (hooks can't be called conditionally)
- add proper deps (paymentProcessor, qrType) to the useMemo
- fix text-grey-1 → text-gray-1 in TransactionCard for consistency
Updates src/content submodule (50 commits behind).

Changes:
• Notify peanut-ui when content is updated on main
• Add valid-links.md reference for LLM content generation
• Add link validation CI for content PRs
• Test: trigger auto-update to peanut-ui
• Fix validate-links CI: peanut-ui is public, no token needed
• feat: add receive-from-country content (29 pages + template)
• Merge pull request #5 from peanutprotocol/feat/receive-from-content
• Add workflow to auto-trigger peanut-ui submodule update
• Merge pull request #6 from peanutprotocol/ci/notify-ui-on-push
• docs: add site integration lifecycle to ARCHITECTURE.md
• feat: add missing country, send-to, and deposit content
• Merge pull request #8 from peanutprotocol/docs/site-integration-lifecycle
• fix: address CR review — diacritics, broken links, TBD placeholders
• Content quality: legal hedging, DAI removal, SEPA updates
• Merge origin/main: resolve 33 conflicts combining both change sets
• feat: add supported-geographies help article
• Merge pull request #10 from peanutprotocol/feat/help-supported-geographies
• style: format notify-ui workflow
• Merge remote-tracking branch 'origin/main'
• Merge remote-tracking branch 'origin/main' into feat/seo-missing-content
• docs: simplify Site Integration section to brief reference
• fix: use locale-prefixed paths in supported-geographies links
• Merge pull request #9 from peanutprotocol/feat/seo-missing-content
• fix: reframe CPF messaging from negative to positive for pt-br trust
• Merge branch 'main' of https://github.com/peanutprotocol/peanut-content
• feat: apply human audit feedback to es-ar and pt-br content
• fix: fully regenerate remaining pt-br content to eliminate em-dash overuse
• fix: replace self-custodial with non-custodial in security data
• fix(content): fix broken pt-br links to supported-geographies (#11)
• fix: correct supported-geographies link path to /help/supported-geographies
• feat: add pt-br translation for supported-geographies help page
• Merge pull request #12 from peanutprotocol/chip/pt-br-supported-geographies
• feat: P7 MercadoPago cluster + Spain-Argentina locale fill (30 pages)
• fix: localize help URLs and add missing es-419 translation
• Merge pull request #13 from peanutprotocol/chip/fix-help-locale-links
• Merge pull request #7 from peanutprotocol/content/update-help-articles
• fix: correct account recovery content — Peanut is self-custodial, no server-side recovery
• fix: use #chat CTA instead of /profile/backup to pass link validation
• fix: restore /profile/backup CTA (validator updated in peanut-ui#1775)
• chore: retrigger CI (peanut-ui#1777 merged)
• Merge pull request #14 from peanutprotocol/chip/fix-recovery-self-custody
• feat: add featured frontmatter + footer manifest generator
• Merge pull request #15 from peanutprotocol/chip/footer-featured-manifest
• feat: add user stories system
• fix: em-dash cleanup, canonical URLs, broken link, workflow update
• Merge pull request #16 from peanutprotocol/chip/user-stories
• feat: integrate user interviews into country-hub, use-case, and compare templates
• fix: update stale section number references in coming-soon variant and component tables
• fix: add stories URLs to valid-links.md
• Merge pull request #17 from peanutprotocol/chip/templates-user-stories
Content with published: false in frontmatter is now excluded
from link validation. Draft content often links to routes that
do not exist yet (e.g. /en/stories/*), and these should not
block CI.
Adds mobile-ui routes (/profile/backup, etc.) to the valid paths
index so content linking to in-app routes does not fail CI.

Ported from #1777 (merged to main).
chore: bump peanut-content to 35cd834a4494
Conflicts resolved:
- zerodev/route.ts: kept dev's improved health check (ERC-4337 method,
  no Sentry noise, Arbitrum-only) + main's AbortSignal.timeout(5000)
- SupportDrawer: kept dev's custom drawer with drag-to-dismiss +
  main's crispTokenId for session continuity
- src/content: pointed to latest main
Sync dev with main (17 commits). Resolved conflicts:
- scripts/validate-links.ts: deleted on main (replaced by validate-content.ts)
- src/content: accepted main's submodule pointer
@vercel

vercel Bot commented Mar 26, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview, Comment Mar 26, 2026 4:22am

Request Review

@coderabbitai

coderabbitai Bot commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR refactors the mobile crypto deposit flow by replacing RhinoDepositView with a new CryptoDepositView component driven by network-based query state and polling, adds Easter egg modals for select countries, restructures add-money and withdrawal navigation with improved country/bridge validation, updates global UI components with styling refinements, and removes the sitemap verification pass.

Changes

Cohort / File(s) Summary
Verification Removal
scripts/verify-content.ts
Removed the sitemap coverage verification pass and its function invocation.
Crypto Deposit - New Components
src/components/AddMoney/components/*, src/components/AddMoney/hooks/*, src/components/AddMoney/views/CryptoDeposit.view.tsx, src/components/AddMoney/views/AddMoneyMethodSelection.view.tsx
Added new crypto deposit UI components (ChooseNetworkDrawer, HowToDepositModal, SupportedNetworksModal), polling hook (useCryptoDepositPolling), and CryptoDepositView for the deposit flow.
Crypto Deposit - Page Integration
src/app/(mobile-ui)/add-money/crypto/page.tsx
Replaced RhinoDepositView with CryptoDepositView, introduced network-based query state, added transaction details handling, and updated success flow with payment success view integration.
Add Money Navigation
src/app/(mobile-ui)/add-money/page.tsx, src/components/AddMoney/..., src/components/AddWithdraw/AddWithdrawCountriesList.tsx
Refactored add-money page to use custom country selection UI instead of AddWithdrawRouterView, added method query state tracking, and updated back-navigation with method parameter.
Easter Egg Modal System
src/components/Global/EasterEggModal/index.tsx, src/components/Common/CountryList.tsx, src/app/(mobile-ui)/dev/ds/patterns/modal/page.tsx
Added EasterEggModal component with country-specific configurations, integrated into CountryList to show modals for Easter egg countries, and exposed in design system documentation.
Withdrawal Flow Updates
src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx, src/app/(mobile-ui)/withdraw/manteca/page.tsx, src/components/AddWithdraw/AddWithdrawRouterView.tsx
Added bridge country validation with client-side redirects, implemented onboarding error handling in manteca flow, updated UI copy ("You're sending" instead of "You're withdrawing"), and passed enforceSupportedCountries prop.
Network & Token Configuration
src/constants/rhino.consts.ts, src/services/services.types.ts, src/services/rhino.ts
Added NETWORK_LABELS, NETWORK_LOGOS constants and getSupportedTokens function; introduced DepositAddressStatusResponse type; updated getDepositAddressStatus return type.
Global Component Styling
src/components/Global/StatusBadge.tsx, src/components/Global/StatusPill/index.tsx, src/components/Global/Modal/index.tsx, src/components/Global/Icons/Icon.tsx, src/components/Slider/index.tsx, src/components/Global/QRCodeWrapper/index.tsx
Updated styling for refunded status badges/pills to use success palette, adjusted modal close button positioning, removed unused icon import, updated QR wrapper with optional center image prop.
Support & Exchange UI
src/components/Global/SupportDrawer/index.tsx, src/components/Global/ExchangeRateWidget/index.tsx
Replaced drawer implementation with slide-up panel with drag-to-dismiss, added Crisp readiness detection; added currency swap UI with state and UX gating for loading states.
Payment Success & Contribution
src/features/payments/shared/components/PaymentSuccessView.tsx, src/features/payments/shared/components/SendWithPeanutCta.tsx, src/features/payments/flows/contribute-pot/components/RequestPotActionList.tsx, src/features/payments/flows/contribute-pot/views/ContributePotInputView.tsx
Extended PaymentSuccessView to support DEPOSIT type and transaction details prop, updated SendWithPeanutCta to handle invite-based routing with inviterUsername, added external wallet loading state to contribution flow.
Transaction & History Updates
src/components/TransactionDetails/TransactionCard.tsx, src/components/Home/HomeHistory.tsx, src/components/Global/PeanutActionDetailsCard/index.tsx
Added strikethrough styling for refunded transaction amounts, introduced BALANCE_AFFECTING_TYPES constant for WebSocket balance refresh logic, updated withdrawal copy to "You're sending".
Asset & Setup Updates
src/assets/peanut/index.ts, src/components/Setup/Setup.consts.tsx
Changed PEANUTMAN_MOBILE asset reference and removed unused peanut man exports; updated setup steps to use PEANUTMAN_MOBILE.src instead of the object.
Home & Utility Updates
src/app/(mobile-ui)/home/page.tsx, src/app/(mobile-ui)/points/page.tsx, src/app/(mobile-ui)/qr-pay/page.tsx, src/components/LandingPage/CurrencySelect.tsx, src/utils/sentry.utils.ts
Removed useDeviceType hook, updated points suffix styling, refactored qr-pay polling and button visuals, added ARS and BRL to popular currencies, improved error messages in fetchWithSentry.
Deprecated Components
src/components/AddMoney/views/CryptoDepositQR.view.tsx, src/components/AddMoney/views/RhinoDeposit.view.tsx, src/components/AddMoney/views/TokenSelection.view.tsx
Removed deprecated CryptoDepositQR and TokenSelectionView components; replaced RhinoDeposit polling with useCryptoDepositPolling hook integration.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • Hugo0
🚥 Pre-merge checks | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Prod Release 135' is vague and does not convey meaningful information about the specific changes in the changeset. Consider using a more descriptive title that summarizes the primary changes (e.g., 'Add crypto deposit flow with network selection and polling' or similar).
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to assess relatedness to the changeset. Add a description explaining the purpose of this release and the main features or fixes included in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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

@coderabbitai coderabbitai Bot added the enhancement New feature or request label Mar 26, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Nitpick comments (4)
src/features/payments/flows/contribute-pot/views/ContributePotInputView.tsx (1)

66-80: Consider adding isExternalWalletLoading to the guard condition.

The guard on line 68 checks !isLoading but not isExternalWalletLoading. If executeContribution(true, true) doesn't immediately set the hook's isLoading state, rapid clicks could potentially trigger multiple concurrent calls before the first completes.

♻️ Suggested fix
 const handleOpenExternalWalletFlow = async () => {
-    if (canProceed && !isLoading) {
+    if (canProceed && !isLoading && !isExternalWalletLoading) {
         setIsExternalWalletLoading(true)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/payments/flows/contribute-pot/views/ContributePotInputView.tsx`
around lines 66 - 80, The click guard in handleOpenExternalWalletFlow should
also check isExternalWalletLoading to prevent concurrent invocations; update the
condition (which currently checks canProceed && !isLoading) to include &&
!isExternalWalletLoading, and ensure setIsExternalWalletLoading(true) is still
set before calling executeContribution(true, true) and cleared in the finally
block as implemented.
src/app/(mobile-ui)/withdraw/manteca/page.tsx (1)

178-199: Consider adding error capture for observability.

Other error handlers in this file (lines 254, 293) capture exceptions to Sentry. The catch block here silently swallows the error, which could make debugging onboarding failures difficult.

♻️ Suggested improvement
         } catch {
+            captureException(new Error('Failed to initiate onboarding redirect'))
             setErrorMessage('Please complete your account setup. Go to Settings to update your profile.')
             setIsRedirectingToOnboarding(false)
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`(mobile-ui)/withdraw/manteca/page.tsx around lines 178 - 199, The
catch in handleOnboardingError currently swallows exceptions; modify it to
capture the thrown error (e.g., catch (err)) and send it to your observability
tool (Sentry.captureException(err) or equivalent) before calling setErrorMessage
and setIsRedirectingToOnboarding(false); ensure the Sentry (or chosen) client is
imported/available in this module so failures from mantecaApi.initiateOnboarding
are recorded for debugging.
src/components/Common/CountryList.tsx (1)

186-205: Normalize country.id before Easter-egg map lookups.

EASTER_EGG_COUNTRIES is read with raw country.id in multiple branches. Normalize once (e.g., uppercase) and reuse to avoid lookup drift across datasets.

♻️ Proposed patch
-                            const twoLetterCountryCode =
-                                ALL_COUNTRIES_ALPHA3_TO_ALPHA2[country.id.toUpperCase()] ?? country.id.toLowerCase()
+                            const normalizedCountryId = country.id.toUpperCase()
+                            const twoLetterCountryCode =
+                                ALL_COUNTRIES_ALPHA3_TO_ALPHA2[normalizedCountryId] ?? country.id.toLowerCase()
@@
-                                        ) : !isSupported && !EASTER_EGG_COUNTRIES[country.id] ? (
+                                        ) : !isSupported && !EASTER_EGG_COUNTRIES[normalizedCountryId] ? (
@@
-                                        if (EASTER_EGG_COUNTRIES[country.id]) {
-                                            setEasterEggCountry(country.id)
+                                        if (EASTER_EGG_COUNTRIES[normalizedCountryId]) {
+                                            setEasterEggCountry(normalizedCountryId)
                                             return
                                         }
@@
-                                        (!isSupported && !EASTER_EGG_COUNTRIES[country.id]) ||
+                                        (!isSupported && !EASTER_EGG_COUNTRIES[normalizedCountryId]) ||
                                         clickedCountryId === country.id
                                     }
Based on learnings: The countryCodeMap in `src/components/AddMoney/consts/index.ts` uses uppercase 3-letter country codes as keys and requires uppercase normalization for lookups.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Common/CountryList.tsx` around lines 186 - 205, Normalize
country.id to the uppercase 3-letter form once and reuse it for all
EASTER_EGG_COUNTRIES lookups and state updates: create a local variable (e.g.,
const normalizedId = (country.id || '').toUpperCase()) at the top of the
component/render block and replace raw country.id usages in the ternary check,
the onClick handler (EASTER_EGG_COUNTRIES lookup and setEasterEggCountry call),
the setClickedCountryId call, and the isDisabled expression to use normalizedId
instead, and guard against empty/undefined ids before using them.
src/components/AddMoney/views/CryptoDeposit.view.tsx (1)

145-186: Make the supported-networks opener a real button.

The modal currently opens from a wrapping div, while the visible control is an icon-only button with no handler or accessible name. Moving the click to the button and adding an aria-label makes this interaction discoverable for keyboard and screen-reader users.

♿ Suggested refactor
-                            <div
-                                onClick={() => {
-                                    if (isEvm) {
-                                        setShowSupportedNetworks(true)
-                                    }
-                                }}
-                                className={`border-t border-black p-4 ${isEvm ? 'cursor-pointer' : ''}`}
-                            >
+                            <div className="border-t border-black p-4">
...
-                                        <Button
+                                        <Button
+                                            onClick={() => setShowSupportedNetworks(true)}
+                                            aria-label="Show supported EVM networks"
                                             shadowSize="4"
                                             size="small"
                                             className="ml-auto h-6 w-6 flex-shrink-0 rounded-full p-0 shadow-[0.12rem_0.12rem_0_#000000]"
                                         >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/AddMoney/views/CryptoDeposit.view.tsx` around lines 145 - 186,
The wrapper div currently handles the onClick to open networks but the visible
control is the Icon-only Button without a handler or accessible name; move the
onClick handler from the div to the Button component (the one rendering Icon
"chevron-up") so clicking/keyboard activation triggers
setShowSupportedNetworks(true), give that Button a clear aria-label like "Open
supported networks", ensure the Button has type="button" and retains the
conditional styling when isEvm (e.g., cursor-pointer) on either the Button or
wrapper, and remove the div's click handler to avoid duplicate handlers while
keeping non-EVM rendering (ChainChip, SUPPORTED_EVM_CHAINS, networkLabel,
NETWORK_LOGOS) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/`(mobile-ui)/add-money/crypto/page.tsx:
- Around line 28-31: The page reads the deposit network as a read-only query
state (const [network] = useQueryState(...)) so the UI cannot change it and
CryptoDepositView never receives a setter; make the query state writable (const
[network, setNetwork] = useQueryState(...)) using the existing
parseAsStringEnum<RhinoChainType>(...).withDefault('EVM'), pass the setter (e.g.
onNetworkChange={setNetwork}) into CryptoDepositView, and wire that prop into
the selector UI inside CryptoDepositView so user selections update the query
param; apply the same change for the other occurrence referenced (lines
~117-123) where network is currently read-only.
- Around line 57-97: The deposit receipt mixes USD and token quantities:
TransactionDetails.amount is used alongside tokenSymbol but is currently set
from depositResult.amount (USD). Extract the token quantity (e.g., const
tokenAmount = depositResult.tokenAmount ?? depositResult.amountToken ?? '0') and
set amount: parseFloat(tokenAmount) while keeping currency: { amount: usdAmount,
code: 'USD' }; update the depositTransactionDetails construction (use
depositResult, tokenAmount, TransactionDetails.amount, and currency) so the
drawer shows token quantity paired with tokenSymbol and USD remains in currency.

In `@src/app/`(mobile-ui)/dev/ds/patterns/modal/page.tsx:
- Around line 334-336: Update the documentation string that currently says "uses
base Modal" to correctly state that this component uses ActionModal; locate the
descriptive paragraph containing "Fun modal shown when users tap
uninhabited/weird countries" in the Modal component file and replace the phrase
"uses base Modal" with "uses ActionModal" so the doc matches the implementation.

In `@src/app/`(mobile-ui)/qr-pay/page.tsx:
- Around line 1355-1366: The overlaid label fragment (the inner span that uses
style clipPath and className "absolute inset-0 ...") is being read by screen
readers in addition to the base label; update that span (the one referencing
holdProgress and rendering {label}) to be hidden from assistive tech by adding
aria-hidden="true" (or role="presentation") so the visual overlay remains but
screen readers only read the first span/label.
- Around line 1077-1092: The useMemo hook that defines paymentMethodName is
declared after conditional early returns tied to kycGateState, violating React
Hooks rules; move the paymentMethodName declaration (the useMemo block computing
paymentMethodName) above the early-return checks so all hooks (including
paymentMethodName) are called unconditionally at the top of the component render
before any returns; ensure the dependency array [paymentProcessor, qrType] is
preserved and no other logic is reordered that would change behavior.

In `@src/components/AddMoney/components/ChooseNetworkDrawer.tsx`:
- Around line 45-51: The clickable EVM expanded area uses a plain div which is
not keyboard-accessible; update the element in ChooseNetworkDrawer (the
container that calls onSelect('EVM') and renders SUPPORTED_EVM_CHAINS/ChainChip
with CHAIN_LOGOS) to be a semantic interactive element (e.g., a <button> or an
element with role="button") and ensure keyboard accessibility by supporting
Enter/Space activation and being focusable (tabIndex) and preserving the
existing className and onSelect('EVM') behavior; keep the inner mapping of
SUPPORTED_EVM_CHAINS to ChainChip unchanged.

In `@src/components/AddMoney/hooks/useCryptoDepositPolling.ts`:
- Around line 16-25: The polling delay currently only runs on mount so switching
depositAddress can skip the POLLING_DELAY and reuse hasCalledSuccess; update the
useEffect that sets isDelayComplete to depend on depositAddress, and on change
reset state/refs: setIsDelayComplete(false),
setIsResetting(true)/isResettingRef.current = true, reset
hasCalledSuccess.current = false, then start a new timeout to
setIsDelayComplete(true) and clear/reset the isResetting flags when it fires;
ensure you clear the previous timer in the cleanup to avoid leaks.

In `@src/components/AddWithdraw/AddWithdrawRouterView.tsx`:
- Line 312: The enforceSupportedCountries prop is being driven by isBankFromSend
which causes Manteca-only countries to be hidden because downstream support
checks are bridge-only; update the caller in AddWithdrawRouterView by toggling
enforceSupportedCountries only when the send path is a bridge (e.g., replace
enforceSupportedCountries={isBankFromSend} with
enforceSupportedCountries={isBankFromSend && isBridgeSend} or equivalent) and
ensure any local flag (isBridgeSend / sendMethod === 'bridge') is derived from
the same router state used for downstream checks; also confirm CountryList (the
component handling supported-country filtering) still performs bridge-only
support evaluation so no further changes are required there.

In `@src/components/Global/EasterEggModal/index.tsx`:
- Around line 66-67: Normalize the countryCode before using it to index
EASTER_EGG_COUNTRIES: ensure you call toUpperCase() (guarding for
null/undefined) on the incoming countryCode and use that normalized value for
the lookup (so replace direct lookup of EASTER_EGG_COUNTRIES[countryCode] with
EASTER_EGG_COUNTRIES[normalizedCountryCode] where normalizedCountryCode =
(countryCode || '').toUpperCase()) to avoid returning null when lowercase codes
are provided.

In `@src/components/Global/ExchangeRateWidget/index.tsx`:
- Around line 96-104: The swap button must explicitly set type="button" and the
swap action should be no-op during loading/error or when destinationAmount is
not a valid positive number; update the swap handler (swapCurrencies) to first
check loading/error flags and that typeof destinationAmount === 'number' &&
destinationAmount > 0 before setting setIsSwapping or flip
skipNextDebounceSyncRef.current, and only call updateUrlParams with a rounded
amount when valid (otherwise avoid updating the amount query param at all);
adjust the component rendering for the swap button to include type="button" so
it never acts as a form submitter.

In `@src/components/Global/SupportDrawer/index.tsx`:
- Around line 59-67: When the support drawer opens the page scroll should be
locked: inside the existing useEffect that watches isSupportModalOpen (the one
with handleEscape) add logic to set document.body.style.overflow = 'hidden' when
isSupportModalOpen is true and restore it to '' (or the previous value) when it
becomes false or on cleanup; ensure the restoration also runs on component
unmount so scrolling is always returned (reference the useEffect,
isSupportModalOpen and setIsSupportModalOpen symbols). If you prefer a
class-based approach, toggle a "no-scroll" class on document.body instead and
remove it in the cleanup to achieve the same effect across devices.
- Around line 95-99: The touch handlers on the drawer are missing a touchcancel
handler so interrupted gestures leave stale drag state; add an onTouchCancel
that resets the drag state (either by calling the existing handleTouchEnd or by
implementing a new handleTouchCancel that mirrors its cleanup) alongside the
existing onTouchStart/onTouchMove/onTouchEnd handlers to ensure dragging flags
and any touch-tracking variables are cleared on cancel. Ensure the symbol
referenced is handleTouchEnd (or create handleTouchCancel) and that it clears
the same state that handleTouchEnd clears.
- Around line 80-88: The panel currently stays mounted so screen readers still
encounter it when isSupportModalOpen is false; update the dialog container and
its interactive children (the element using panelRef and the embedded iframe) to
be hidden from assistive tech when closed by adding aria-hidden={
!isSupportModalOpen } and switching tabIndex to tabIndex={ isSupportModalOpen ?
0 : -1 } (or remove tabindex when open), and only expose aria-modal/role
semantics when open (you can keep role="dialog" but ensure
aria-modal={isSupportModalOpen}). Apply the same aria-hidden/tabIndex change to
the other support panel instance referenced in this file (the second
dialog/iframe block).

In `@src/utils/sentry.utils.ts`:
- Around line 181-184: The code always renames unknown failures to
ServiceUnavailableError by setting userError.name = 'ServiceUnavailableError';
change this to map or preserve the original error type instead: inspect the
incoming error (the variable error) and only set userError.name =
'ServiceUnavailableError' when the error clearly indicates a
timeout/network/service-unavailable condition (e.g., instanceof TimeoutError or
known codes like ETIMEDOUT/ECONNREFUSED), otherwise preserve error.name or map
to a more appropriate name; always attach the original error as userError.cause
and throw the wrapped Error (refer to the userError variable and the existing
assignment userError.cause = error and the previous name assignment).

---

Nitpick comments:
In `@src/app/`(mobile-ui)/withdraw/manteca/page.tsx:
- Around line 178-199: The catch in handleOnboardingError currently swallows
exceptions; modify it to capture the thrown error (e.g., catch (err)) and send
it to your observability tool (Sentry.captureException(err) or equivalent)
before calling setErrorMessage and setIsRedirectingToOnboarding(false); ensure
the Sentry (or chosen) client is imported/available in this module so failures
from mantecaApi.initiateOnboarding are recorded for debugging.

In `@src/components/AddMoney/views/CryptoDeposit.view.tsx`:
- Around line 145-186: The wrapper div currently handles the onClick to open
networks but the visible control is the Icon-only Button without a handler or
accessible name; move the onClick handler from the div to the Button component
(the one rendering Icon "chevron-up") so clicking/keyboard activation triggers
setShowSupportedNetworks(true), give that Button a clear aria-label like "Open
supported networks", ensure the Button has type="button" and retains the
conditional styling when isEvm (e.g., cursor-pointer) on either the Button or
wrapper, and remove the div's click handler to avoid duplicate handlers while
keeping non-EVM rendering (ChainChip, SUPPORTED_EVM_CHAINS, networkLabel,
NETWORK_LOGOS) unchanged.

In `@src/components/Common/CountryList.tsx`:
- Around line 186-205: Normalize country.id to the uppercase 3-letter form once
and reuse it for all EASTER_EGG_COUNTRIES lookups and state updates: create a
local variable (e.g., const normalizedId = (country.id || '').toUpperCase()) at
the top of the component/render block and replace raw country.id usages in the
ternary check, the onClick handler (EASTER_EGG_COUNTRIES lookup and
setEasterEggCountry call), the setClickedCountryId call, and the isDisabled
expression to use normalizedId instead, and guard against empty/undefined ids
before using them.

In `@src/features/payments/flows/contribute-pot/views/ContributePotInputView.tsx`:
- Around line 66-80: The click guard in handleOpenExternalWalletFlow should also
check isExternalWalletLoading to prevent concurrent invocations; update the
condition (which currently checks canProceed && !isLoading) to include &&
!isExternalWalletLoading, and ensure setIsExternalWalletLoading(true) is still
set before calling executeContribution(true, true) and cleared in the finally
block as implemented.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f289cc28-954b-45ee-aa9f-7745ced99d50

📥 Commits

Reviewing files that changed from the base of the PR and between 9283eb5 and eaa34ac.

⛔ Files ignored due to path filters (13)
  • public/easter-eggs/antarctica.png is excluded by !**/*.png
  • public/easter-eggs/bouvet.png is excluded by !**/*.png
  • public/easter-eggs/christmas.png is excluded by !**/*.png
  • public/easter-eggs/cocos.png is excluded by !**/*.png
  • public/easter-eggs/heard.png is excluded by !**/*.png
  • public/easter-eggs/pitcairn.png is excluded by !**/*.png
  • public/easter-eggs/southgeorgia.png is excluded by !**/*.png
  • public/easter-eggs/tokelau.png is excluded by !**/*.png
  • src/assets/peanut/peanut-holding-mobile.svg is excluded by !**/*.svg
  • src/assets/peanut/peanutman-cheering.png is excluded by !**/*.png
  • src/assets/peanut/peanutman-cheering.svg is excluded by !**/*.svg
  • src/assets/peanut/peanutman-happy.svg is excluded by !**/*.svg
  • src/assets/peanut/peanutman-presenting.svg is excluded by !**/*.svg
📒 Files selected for processing (44)
  • scripts/verify-content.ts
  • src/app/(mobile-ui)/add-money/crypto/page.tsx
  • src/app/(mobile-ui)/add-money/page.tsx
  • src/app/(mobile-ui)/dev/ds/patterns/modal/page.tsx
  • src/app/(mobile-ui)/home/page.tsx
  • src/app/(mobile-ui)/points/page.tsx
  • src/app/(mobile-ui)/qr-pay/page.tsx
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx
  • src/app/(mobile-ui)/withdraw/manteca/page.tsx
  • src/assets/peanut/index.ts
  • src/components/AddMoney/components/ChooseNetworkDrawer.tsx
  • src/components/AddMoney/components/HowToDepositModal.tsx
  • src/components/AddMoney/components/SupportedNetworksModal.tsx
  • src/components/AddMoney/hooks/useCryptoDepositPolling.ts
  • src/components/AddMoney/views/AddMoneyMethodSelection.view.tsx
  • src/components/AddMoney/views/CryptoDeposit.view.tsx
  • src/components/AddMoney/views/CryptoDepositQR.view.tsx
  • src/components/AddMoney/views/RhinoDeposit.view.tsx
  • src/components/AddMoney/views/TokenSelection.view.tsx
  • src/components/AddWithdraw/AddWithdrawCountriesList.tsx
  • src/components/AddWithdraw/AddWithdrawRouterView.tsx
  • src/components/Common/CountryList.tsx
  • src/components/Global/Badges/StatusBadge.tsx
  • src/components/Global/EasterEggModal/index.tsx
  • src/components/Global/ExchangeRateWidget/index.tsx
  • src/components/Global/Icons/Icon.tsx
  • src/components/Global/Modal/index.tsx
  • src/components/Global/PeanutActionDetailsCard/index.tsx
  • src/components/Global/QRCodeWrapper/index.tsx
  • src/components/Global/StatusPill/index.tsx
  • src/components/Global/SupportDrawer/index.tsx
  • src/components/Home/HomeHistory.tsx
  • src/components/LandingPage/CurrencySelect.tsx
  • src/components/Setup/Setup.consts.tsx
  • src/components/Slider/index.tsx
  • src/components/TransactionDetails/TransactionCard.tsx
  • src/constants/rhino.consts.ts
  • src/features/payments/flows/contribute-pot/components/RequestPotActionList.tsx
  • src/features/payments/flows/contribute-pot/views/ContributePotInputView.tsx
  • src/features/payments/shared/components/PaymentSuccessView.tsx
  • src/features/payments/shared/components/SendWithPeanutCta.tsx
  • src/services/rhino.ts
  • src/services/services.types.ts
  • src/utils/sentry.utils.ts
💤 Files with no reviewable changes (5)
  • src/app/(mobile-ui)/home/page.tsx
  • src/components/Global/Icons/Icon.tsx
  • scripts/verify-content.ts
  • src/components/AddMoney/views/CryptoDepositQR.view.tsx
  • src/components/AddMoney/views/TokenSelection.view.tsx

Comment thread src/app/(mobile-ui)/add-money/crypto/page.tsx
Comment thread src/app/(mobile-ui)/add-money/crypto/page.tsx
Comment thread src/app/(mobile-ui)/dev/ds/patterns/modal/page.tsx
Comment thread src/app/(mobile-ui)/qr-pay/page.tsx
Comment thread src/app/(mobile-ui)/qr-pay/page.tsx
Comment thread src/components/Global/ExchangeRateWidget/index.tsx
Comment thread src/components/Global/SupportDrawer/index.tsx
Comment thread src/components/Global/SupportDrawer/index.tsx
Comment thread src/components/Global/SupportDrawer/index.tsx
Comment thread src/utils/sentry.utils.ts
@jjramirezn jjramirezn closed this Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants