Skip to content

Prod Release Sprint 154 — app localization · lifecycle emails · error codes (2026-08-06) - #2624

Open
kushagrasarathe wants to merge 223 commits into
mainfrom
dev
Open

Prod Release Sprint 154 — app localization · lifecycle emails · error codes (2026-08-06)#2624
kushagrasarathe wants to merge 223 commits into
mainfrom
dev

Conversation

@kushagrasarathe

Copy link
Copy Markdown
Contributor

Prod Release Sprint 154 — app localization (en/es-419/pt-BR) · lifecycle emails · error codes (2026-08-06)

Release payload: devmain. Back-merge of prod hotfixes (main → dev) already landed via #2611.

What ships (peanut-ui)

Localization (the dominant theme)

Native / migration

Money flows

Platform

Migrations

None for this release (FE).

Deploy order

Deploys after the BE release PR. See the release doc for the full checklist:
https://app.notion.com/p/3b38381175798001af66d8450d48f692

jjramirezn and others added 30 commits July 8, 2026 11:02
…the apply funnel

The /card state machine ignored country eligibility: users from Rain's
prohibited-issuance countries were teased with the press-and-hold
"see if you qualify" gate and could run the whole KYC funnel before Rain
rejected them.

- computeCardState: new 'geo-blocked' state, keyed on BE's new
  geoProhibited field (country KNOWN and prohibited — never blocks on
  unknown, so pre-KYC users still enter). Scoped to users with no
  existing application: in-flight/rejected rails keep their truthful
  state and the re-issue path stays untouched, mirroring the BE gate.
- ApplicationStatusScreen: 'geo-blocked' variant — regulatory dead end,
  no support CTA (support can't override regulation).
- api.openapi.json patched surgically with just the new field (the
  committed copy has pre-existing drift; full re-sync left for its own PR).
…unnel

/code-review findings:

- A Sumsub-only user (country unknown up front, so geoProhibited couldn't
  block them) who completes KYC with a prohibited-country address got a
  generic applyError on add-card — an apply button that can never
  succeed. The BE now answers a typed 'geo-blocked' status; handle it in
  the apply/poll/refresh paths with a local flag that renders the
  terminal screen immediately, plus a cardInfo refetch so the state
  machine owns the block on later visits.
- Component test pinning the geo-blocked no-support-CTA contract
  (support cannot override regulation; guards SUPPORT_VARIANTS drift).
- Straight apostrophe in the geo-blocked body copy (matched the rest of
  the COPY table).
…d screen

A geo-blocked user had no way to see WHICH regions are restricted: Rain's
marketing-compliance rules ban country names on card-marketing surfaces
(help articles included), so the full issuance denylist is published in
exactly one compliant place — the legal Prohibited Activities Policy
(§1 Restricted Countries). Link it from the geo-blocked screen, the one
surface where a user actually needs it. Tests pin the href and that the
link stays off other variants.
…zation header

CapacitorHttp's Android GET proxy (_capacitor_http_interceptor_) stalls under
load, timing out every in-flight request after 10s (PEANUT-UI-R44): ~400
timeouts/user on Android vs ~3 on web/iOS over 14d, GETs only, in correlated
bursts. Requests now go direct from the webview, same path as web.

- auth: token moves from the CapacitorHttp cookie jar to @capacitor/preferences
  (survives webview storage eviction, unlike localStorage — PEANUT-UI-QTQ),
  hydrated into an in-memory cache and sent as Authorization. authReady() gates
  callApi and direct fetchWithSentry call sites against cold-start races.
- login: the ZeroDev SDK consumes /passkeys/*/verify responses internally, so a
  window.fetch wrapper captures the body token on native. /users/me sliding
  refresh keeps it current via the existing setAuthToken path.
- old binaries keep working: server still accepts the jwt-token cookie and
  hasNativeSession falls back to the legacy jar. Existing native sessions are
  not migrated — testers log in once after updating.
- fetchWithSentry: idempotent requests (GET/HEAD) get one silent retry on
  timeout before surfacing.
- canary: one-shot startup probe reports direct-fetch viability to Sentry
  (message:"direct-fetch canary", tags outcome/transport) so the transport
  switch is validated fleet-wide via OTA before the binary rolls out.
@capacitor/device requires the next native binary release; JS falls back
to navigator.language on older binaries.
Hoist the lazy viem require in peanut-claim.utils (viem is already
statically imported there) and scope the rule off for Jest test files,
where require() after jest.mock()/resetModules() is intentional.
Remove dead imports/declarations, use bare catch where the binding was
unused, and _-prefix signature-bound params and kept hook results.
Also ignore ios/ and build/ (generated) in eslint.
Replace raw <a> internal-route anchors with <Link> (client-side
navigation) across LandingPage components and the dev debug page.
- src/i18n/app: locale config + resolveLocale normalizer, catalogs
  (en/es-419/pt-BR), deep-merge loader so missing keys render English,
  runtime locale store (Preferences/Device on native, cookie on web),
  AppIntlProvider with hydration-safe English-first state
- provider wired into ClientProviders; native splash gated on the
  startup locale being painted (2s timeout guard)
- loadingStates union converted to a const array + key mapping
- jest: transform ESM-only intl packages (pnpm-aware ignore pattern)

Marketing i18n (src/i18n/*.json) untouched.
/settings/language screen with the supported locales, reached from a
new Profile row showing the active language. Live re-render on switch,
persisted via Preferences (native) / cookie (web).
The OPEN-status badge fix was picked up by 1eb7c3c ("fix(lint): resolve
no-unused-vars") along with that commit's lint sweep. It is unrelated to
localization and is being reviewed on its own branch against main
(peanut-ui#2430), so remove it here to keep the two changes separable.

Pure removal — no behaviour change beyond reverting to main's badge logic.
Step titles/descriptions keyed by screenId (removed from ISetupStep),
all Setup views, wrapper, and (setup) pages on useTranslations.
es-419 + pt-BR drafts included.
Home screen, activation CTAs, carousel, perk/welcome modals, tab bar,
desktop sidebar and top navbar. TopNavbar maps pathname to typed
navigation.* keys, replacing the pathTitles util.
ExchangeRateWidget (marketing-shared) takes an optional labels prop with
English defaults; product callers pass translated labels.
Limits warning-card items now carry a kind discriminator so render
sites can map them to translated copy; qr-pay uses it.
The warning card rendered raw English item text for the withdraw and
add-money callers while qr-pay mapped the kind discriminator at its own
render site. Resolve copy inside the card instead, so every flow gets it,
and drop the duplicated mapping from qr-pay.

Passkey troubleshooting steps and warnings become ids resolved against
setup.passkey.help.*, so the modal's content is translated, not just its
chrome.
The min/max cashout branches assigned the placeholder slugs
'offramp_lt_minimum'/'offramp_mt_maximum', which ErrorAlert rendered
verbatim — users saw the raw slug. Assign real messages with the limit
formatted as currency.

Also return on the over-maximum branch: it set the error and then kept
going, fetching a route and letting the flow continue past the limit,
unlike the under-minimum branch.
validatePin returns reason codes instead of English copy so the util
stays copy-free; CardPinSetupFlow maps them to messages.
CardCountryConfirmScreen feeds the active locale into Intl.DisplayNames
(was hardcoded to en), so country names follow the UI language.
Drop the vestigial capitalize class on the feed's type label: it existed
to case raw enum values (getActionText returned the type verbatim), but
the catalog now supplies cased copy, and CSS title-casing mangles
multi-word labels in every locale.

cardDeclineReason and the bank-account label util return codes now, with
the copy resolved at the render site.
Drop the capitalize class on the badge-unlocked label for the same
reason as the transaction feed: it title-cased translated copy.

Remove invites.consts.ts — it held only display copy, and its last
consumer now reads the setup-flow waitlist key so the two gates can't
drift.
sumsub-reject-labels.consts.ts becomes a copy-free code registry; the
62 reject labels move to the kyc namespace and resolve at the render
site, with unknown codes collapsing to FALLBACK as before.

recover-funds no longer prints a raw loadingState or raw token amounts,
and the KYC screens format dates through the active locale instead of a
hardcoded en-US.
Marketing-shared components under Global/ keep their English and take
copy as props instead: they render inside the app intl context, but the
marketing site resolves its language from the URL, so a shared component
would show the app locale on a marketing page.

Fix UserCard.getTitle reading fullName/username while only depending on
type, which rendered a stale name after a rename.
Extraction silently rewrote ' to the typographic form in 32 places,
changing English copy that ships today (e.g. the balance-warning modal's
"you're the only one who can access your funds"). Straighten them all so
en matches source and reads consistently; the translated catalogs are
unaffected.

Also wrap the useSumsubKycFlow test in an intl provider — the hook now
calls useTranslations and the suite never had one.
friendly-error.utils.tsx becomes copy-free: ErrorHandler is replaced by
friendlyError(), returning a code or backend-provided text, resolved to
a message by the new useFriendlyError hook. Backend copy (rain collateral,
stale-card re-enable with its dynamic retry hint) passes through untranslated.

Three sites compared the rendered error string against a constant to gate
UI; those now compare the error CODE, so the gate survives translation.
src/features/payments was missed by every earlier pass — a lint probe
caught it. Extends the existing payment namespace (no payments dupe);
contributor and receipt counts use ICU plurals, the 'on <chain>' label
reuses the shared tokenSelector.onChain rich-text key. Also covers the
KYC status drawer, sumsub load-error, and amount-input balance label.
Scopes react/jsx-no-literals to the translated surface so new hardcoded
JSX strings fail lint. Excludes tests, the /dev catalog, and marketing-
shared Global components; allowlists non-copy glyphs (card masks, %,
decorative emoji). Extraction stragglers the guard surfaced are also
handled: the beta/demo banners and the transaction 'Enjoy Peanut!' title.
useSendMoney calls useTranslations, and it runs inside ContextProvider
(via TokenContextProvider → useWallet), which was mounted ABOVE the intl
provider — so every route 500'd with a missing-context error. Unit tests
each wrap their subject in a provider, so only a full-app render caught
it. Move AppIntlProvider to wrap ContextProvider (still inside
PeanutProvider, which needs no translations).
'Video element not available' was shown to users when the video element
lost the mount race. Say what it means to them instead.

Adds a ClientProviders provider-order test: it walks the real element
tree rather than rendering it, so the AppIntlProvider-wraps-ContextProvider
contract is checked without mocking the wallet and kernel stack.
jjramirezn and others added 12 commits August 5, 2026 15:44
fix(i18n): four locale gaps — spinner words, savings message, Crisp locale, date casing
…second broadcast

A recordPayment timeout after the on-chain transfer broadcast lands the
user on Retry, and Retry re-ran the whole flow — issuing a second
on-chain transfer for the same charge (TASK-19581 double-spend: two
distinct Rhino bridges 30s apart, user moved $10 instead of $5).

Stamp the executed spend (charge, tx hash, strategy) in a ref the moment
a tx identifier exists; a retry for the same charge skips the broadcast
and replays only the record. Failures before any tx identifier still
retry with a fresh broadcast. Also give createPayment 30s (default 20s
abort fired while the API had committed in 49ms — the Vercel proxy
cold-start ate the budget).
pre-commit scan false positive: flagged value is a hardcoded test fixture constant from dev's side of the merge, already in dev history.
…unted sections

Two review findings:

- `handleClaimLink` reads `tCommon` in both invite-error branches but the
  callback's dep list only carried `t`, so a locale switch mid-session
  would leave it closed over the old translator. eslint didn't flag it
  because `t` is still a dep and the callback is large.

- The es-AR delta assertion counted top-level sections (`< 8`), which
  breaks the moment someone legitimately overrides one more section. It
  now compares leaf paths: every es-AR path must exist in es-419, and the
  delta must stay strictly smaller. That is the actual contract.
…d-only

fix(withdraw): record-only retry after an executed spend (TASK-19581 double-spend)
…sive service type

The hand-declared spec marked geoProhibited required while src/services/card.ts declares it optional — and the current BE does not emit it yet (FE-first deploy). Optional is the honest contract and reduces sync-openapi churn direction.
Locale was client-only (cookie / native Preferences) and never reached
analytics, so the localization OKR was unmeasurable. Register app_locale
as an event super property at startup resolve and on manual change, set
the person property for identified users, and mirror it on the identify
payload to cover the first session.
Emission moves to AppIntlProvider's apply points so analytics report the
language the user actually saw, never a failed catalog swap. $set fires
only on a real change by an identified user (startup coverage rides the
identify), calls are deduped and fenced so a posthog failure can't break
i18n, and logout re-registers app_locale after posthog.reset() wipes
super properties. Gating logic covered by locale-store.test.ts.
The English startup path never swaps intl state, so if setLocale already
applied another locale the UI keeps it — emitting the startup value
would record a language nobody sees (CodeRabbit).
@vercel

vercel Bot commented Aug 6, 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 Aug 6, 2026 5:35pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 745 files, which is 595 over the limit of 150.

To get a review, reduce the PR to 150 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to Pro+ to raise the limit.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bb81535e-6da4-4acb-b993-6c60c73c389b

📥 Commits

Reviewing files that changed from the base of the PR and between fb4cd2c and 608cf8f.

⛔ Files ignored due to path filters (8)
  • android/app/capacitor.build.gradle is excluded by !android/**
  • android/capacitor.settings.gradle is excluded by !android/**
  • ios/App/App/Info.plist is excluded by !ios/**
  • ios/App/CapApp-SPM/Package.swift is excluded by !ios/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • src/assets/icons/telegram-white.svg is excluded by !**/*.svg, !**/*.svg
  • src/assets/icons/x-logo.svg is excluded by !**/*.svg, !**/*.svg
  • src/types/api.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing (745)
  • capacitor.config.ts
  • csp-google-domains.js
  • eslint.config.js
  • instrumentation-client.ts
  • local/scratch/pr-peanut-ui-feat-share-asset-crisp-hand.md
  • next.config.js
  • package.json
  • redirects.json
  • scripts/native-build.js
  • src/__tests__/proxy-locale.test.ts
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx
  • src/app/(mobile-ui)/add-money/__tests__/add-money-states.test.tsx
  • src/app/(mobile-ui)/add-money/crypto/page.tsx
  • src/app/(mobile-ui)/add-money/page.tsx
  • src/app/(mobile-ui)/card-recovery/page.tsx
  • src/app/(mobile-ui)/card/limit/page.tsx
  • src/app/(mobile-ui)/card/page.tsx
  • src/app/(mobile-ui)/card/physical/page.tsx
  • src/app/(mobile-ui)/card/pin/page.tsx
  • src/app/(mobile-ui)/dev/_components/DevChip.tsx
  • src/app/(mobile-ui)/dev/_components/DevField.tsx
  • src/app/(mobile-ui)/dev/_components/DevNoteCard.tsx
  • src/app/(mobile-ui)/dev/_components/DevPageShell.tsx
  • src/app/(mobile-ui)/dev/_components/DevPanel.tsx
  • src/app/(mobile-ui)/dev/_components/DevPresetButton.tsx
  • src/app/(mobile-ui)/dev/_components/DevSectionLabel.tsx
  • src/app/(mobile-ui)/dev/_components/DevSegmented.tsx
  • src/app/(mobile-ui)/dev/_components/devChipTones.ts
  • src/app/(mobile-ui)/dev/card-session-approve/page.tsx
  • src/app/(mobile-ui)/dev/components/page.tsx
  • src/app/(mobile-ui)/dev/debug/page.tsx
  • src/app/(mobile-ui)/dev/ds/_components/Playground.tsx
  • src/app/(mobile-ui)/dev/ds/patterns/drawer/page.tsx
  • src/app/(mobile-ui)/dev/full-graph/page.tsx
  • src/app/(mobile-ui)/dev/home-ctas/page.tsx
  • src/app/(mobile-ui)/dev/journey/BoardGroup.tsx
  • src/app/(mobile-ui)/dev/journey/EmailCard.tsx
  • src/app/(mobile-ui)/dev/journey/EmailPreviewPanel.tsx
  • src/app/(mobile-ui)/dev/journey/FindingsStrip.tsx
  • src/app/(mobile-ui)/dev/journey/JourneyBoard.tsx
  • src/app/(mobile-ui)/dev/journey/KindLegend.tsx
  • src/app/(mobile-ui)/dev/journey/PushCard.tsx
  • src/app/(mobile-ui)/dev/journey/ReviewProgressStrip.tsx
  • src/app/(mobile-ui)/dev/journey/RulesLegend.tsx
  • src/app/(mobile-ui)/dev/journey/StuckBadge.tsx
  • src/app/(mobile-ui)/dev/journey/SurfaceCard.tsx
  • src/app/(mobile-ui)/dev/journey/UserInspector.tsx
  • src/app/(mobile-ui)/dev/journey/ViewModeToggle.tsx
  • src/app/(mobile-ui)/dev/journey/__tests__/copyReviewStorage.test.ts
  • src/app/(mobile-ui)/dev/journey/__tests__/emailReview.test.ts
  • src/app/(mobile-ui)/dev/journey/__tests__/surfaceKindMeta.test.ts
  • src/app/(mobile-ui)/dev/journey/__tests__/userLookup.test.ts
  • src/app/(mobile-ui)/dev/journey/copyReviewStorage.ts
  • src/app/(mobile-ui)/dev/journey/emailReview.ts
  • src/app/(mobile-ui)/dev/journey/journeyTypes.ts
  • src/app/(mobile-ui)/dev/journey/page.tsx
  • src/app/(mobile-ui)/dev/journey/surfaceKindMeta.ts
  • src/app/(mobile-ui)/dev/journey/useCopyReview.ts
  • src/app/(mobile-ui)/dev/journey/userLookup.ts
  • src/app/(mobile-ui)/dev/leaderboard/page.tsx
  • src/app/(mobile-ui)/dev/page.tsx
  • src/app/(mobile-ui)/dev/perk-success-test/page.tsx
  • src/app/(mobile-ui)/dev/profile-card-row/page.tsx
  • src/app/(mobile-ui)/dev/rejection-builder/page.tsx
  • src/app/(mobile-ui)/dev/shake-test/page.tsx
  • src/app/(mobile-ui)/dev/share-builder/page.tsx
  • src/app/(mobile-ui)/history/page.tsx
  • src/app/(mobile-ui)/home/page.tsx
  • src/app/(mobile-ui)/layout.tsx
  • src/app/(mobile-ui)/notifications/page.tsx
  • src/app/(mobile-ui)/profile/backup/page.tsx
  • src/app/(mobile-ui)/profile/exchange-rate/page.tsx
  • src/app/(mobile-ui)/profile/page.tsx
  • src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx
  • src/app/(mobile-ui)/qr-pay/page.tsx
  • src/app/(mobile-ui)/qr/[code]/page.tsx
  • src/app/(mobile-ui)/qr/[code]/success/page.tsx
  • src/app/(mobile-ui)/receipt/page.tsx
  • src/app/(mobile-ui)/recover-funds/page.tsx
  • src/app/(mobile-ui)/rewards/invites/page.tsx
  • src/app/(mobile-ui)/rewards/page.tsx
  • src/app/(mobile-ui)/settings/language/page.tsx
  • src/app/(mobile-ui)/settings/page.tsx
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx
  • src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx
  • src/app/(mobile-ui)/withdraw/crypto/__tests__/crypto-withdraw-confirm.test.tsx
  • src/app/(mobile-ui)/withdraw/crypto/page.tsx
  • src/app/(mobile-ui)/withdraw/manteca/page.tsx
  • src/app/(mobile-ui)/withdraw/page.tsx
  • src/app/(setup)/layout.tsx
  • src/app/(setup)/setup/finish/page.tsx
  • src/app/(setup)/setup/page.tsx
  • src/app/ClientProviders.tsx
  • src/app/[...recipient]/error.tsx
  • src/app/[...recipient]/page.tsx
  • src/app/[locale]/(marketing)/[country]/page.tsx
  • src/app/[locale]/(marketing)/blog/[slug]/page.tsx
  • src/app/[locale]/(marketing)/blog/page.tsx
  • src/app/[locale]/(marketing)/card-esign/page.tsx
  • src/app/[locale]/(marketing)/card-privacy/page.tsx
  • src/app/[locale]/(marketing)/card-prohibited-activities/page.tsx
  • src/app/[locale]/(marketing)/card-terms-international/page.tsx
  • src/app/[locale]/(marketing)/card-terms-us/page.tsx
  • src/app/[locale]/(marketing)/compare/[slug]/page.tsx
  • src/app/[locale]/(marketing)/content/page.tsx
  • src/app/[locale]/(marketing)/deposit/[exchange]/page.tsx
  • src/app/[locale]/(marketing)/error.tsx
  • src/app/[locale]/(marketing)/help/[slug]/page.tsx
  • src/app/[locale]/(marketing)/help/page.tsx
  • src/app/[locale]/(marketing)/layout.tsx
  • src/app/[locale]/(marketing)/pay-with/[method]/page.tsx
  • src/app/[locale]/(marketing)/pricing/page.tsx
  • src/app/[locale]/(marketing)/privacy/page.tsx
  • src/app/[locale]/(marketing)/receive-money-from/[country]/page.tsx
  • src/app/[locale]/(marketing)/send-money-from/[from]/to/[to]/page.tsx
  • src/app/[locale]/(marketing)/send-money-to/[country]/page.tsx
  • src/app/[locale]/(marketing)/stories/[slug]/page.tsx
  • src/app/[locale]/(marketing)/stories/page.tsx
  • src/app/[locale]/(marketing)/supported-networks/page.tsx
  • src/app/[locale]/(marketing)/team/page.tsx
  • src/app/[locale]/(marketing)/terms/page.tsx
  • src/app/[locale]/(marketing)/use-cases/[slug]/page.tsx
  • src/app/[locale]/(marketing)/withdraw/[slug]/page.tsx
  • src/app/__tests__/ClientProviders.test.tsx
  • src/app/actions/__tests__/api-headers-extended.test.ts
  • src/app/actions/__tests__/api-headers.test.ts
  • src/app/actions/__tests__/currency.test.ts
  • src/app/actions/bridge/get-customer.ts
  • src/app/actions/card.ts
  • src/app/actions/clients.ts
  • src/app/actions/currency.ts
  • src/app/actions/exchange-rate.ts
  • src/app/actions/external-accounts.ts
  • src/app/actions/onramp-quote.ts
  • src/app/actions/sumsub.ts
  • src/app/actions/users.ts
  • src/app/api/health/justaname/route.ts
  • src/app/api/health/route.ts
  • src/app/api/health/rpc/route.ts
  • src/app/api/health/zerodev/route.ts
  • src/app/api/og/route.tsx
  • src/app/api/preview-image/route.tsx
  • src/app/api/recent-transactions/route.ts
  • src/app/api/version/route.ts
  • src/app/app/page.tsx
  • src/app/careers/page.tsx
  • src/app/crisp-proxy/page.tsx
  • src/app/dev/loading-words/page.tsx
  • src/app/es-419/page.tsx
  • src/app/es-ar/page.tsx
  • src/app/exchange/layout.tsx
  • src/app/exchange/page.tsx
  • src/app/invite/page.tsx
  • src/app/kyc/success/page.tsx
  • src/app/lp/card/CardLandingPage.tsx
  • src/app/lp/page.tsx
  • src/app/metadata.ts
  • src/app/page.tsx
  • src/app/pt-br/page.tsx
  • src/app/quests/[questId]/page.tsx
  • src/app/quests/components/QuestCard.tsx
  • src/app/quests/components/QuestLeaderboard.tsx
  • src/app/quests/components/QuestsHero.tsx
  • src/app/quests/explore/page.tsx
  • src/app/quests/layout.tsx
  • src/app/quests/page.tsx
  • src/app/receipt/[entryId]/page.tsx
  • src/app/robots.ts
  • src/app/shhhhh/ShhhhhLandingPage.tsx
  • src/app/sitemap.ts
  • src/components/AddMoney/components/AddMoneyBankDetails.tsx
  • src/components/AddMoney/components/ChooseNetworkDrawer.tsx
  • src/components/AddMoney/components/EvmChainChips.tsx
  • src/components/AddMoney/components/HowToDepositModal.tsx
  • src/components/AddMoney/components/InputAmountStep.tsx
  • src/components/AddMoney/components/MantecaAddMoney.tsx
  • src/components/AddMoney/components/MantecaDepositShareDetails.tsx
  • src/components/AddMoney/components/MantecaPixQrDeposit.tsx
  • src/components/AddMoney/components/OnrampConfirmationModal.tsx
  • src/components/AddMoney/components/SupportedNetworksModal.tsx
  • src/components/AddMoney/components/__tests__/MantecaAddMoney.exits.test.tsx
  • src/components/AddMoney/components/__tests__/MantecaAddMoney.test.tsx
  • src/components/AddMoney/components/__tests__/MantecaPixQrDeposit.test.tsx
  • src/components/AddMoney/hooks/__tests__/useMantecaDepositPolling.test.tsx
  • src/components/AddMoney/views/AddMoneyMethodSelection.view.tsx
  • src/components/AddMoney/views/CryptoDeposit.view.tsx
  • src/components/AddMoney/views/OfframpHandleGate.view.tsx
  • src/components/AddMoney/views/RhinoDeposit.view.tsx
  • src/components/AddWithdraw/AddWithdrawCountriesList.tsx
  • src/components/AddWithdraw/AddWithdrawRouterView.tsx
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx
  • src/components/AddWithdraw/__tests__/AddWithdrawCountriesList.test.tsx
  • src/components/AddWithdraw/__tests__/AddWithdrawRouterView.test.tsx
  • src/components/Auth/auth.e2e.test.ts
  • src/components/Badges/BadgeDetailModal.tsx
  • src/components/Badges/BadgeEarnToast.tsx
  • src/components/Badges/BadgeStatusDrawer.tsx
  • src/components/Badges/BadgeStatusItem.tsx
  • src/components/Badges/BadgesRow.tsx
  • src/components/Badges/__tests__/BadgeDetailModal.test.tsx
  • src/components/Badges/__tests__/BadgeEarnToast.test.tsx
  • src/components/Badges/__tests__/BadgesRow.test.tsx
  • src/components/Badges/__tests__/badge.utils.test.ts
  • src/components/Badges/badge.types.ts
  • src/components/Badges/badge.utils.ts
  • src/components/Badges/index.tsx
  • src/components/Card/AddCardEntryScreen.tsx
  • src/components/Card/AddToWalletCarousel.tsx
  • src/components/Card/ApplicationStatusScreen.tsx
  • src/components/Card/BadgeSkipCelebration.tsx
  • src/components/Card/CancelCardModal.tsx
  • src/components/Card/CardCountryConfirmScreen.tsx
  • src/components/Card/CardEligibilityCheckScreen.tsx
  • src/components/Card/CardFace.tsx
  • src/components/Card/CardLimitEditModal.tsx
  • src/components/Card/CardLimitsScreen.tsx
  • src/components/Card/CardPinScreen.tsx
  • src/components/Card/CardPinSetupFlow.tsx
  • src/components/Card/CardRejectionScreen.tsx
  • src/components/Card/CardTermsScreen.tsx
  • src/components/Card/CardUnlockDrawer.tsx
  • src/components/Card/CardUnlockHistoryItem.tsx
  • src/components/Card/LockCardModal.tsx
  • src/components/Card/PhysicalCardScreen.tsx
  • src/components/Card/PinInput.tsx
  • src/components/Card/SlideToAction.tsx
  • src/components/Card/YourCardScreen.tsx
  • src/components/Card/__tests__/ApplicationStatusScreen.test.tsx
  • src/components/Card/__tests__/CardCountryConfirmScreen.test.tsx
  • src/components/Card/__tests__/CardFace.test.tsx
  • src/components/Card/__tests__/LockCardModal.test.tsx
  • src/components/Card/__tests__/PhysicalCardScreen.test.tsx
  • src/components/Card/__tests__/cardState.utils.test.ts
  • src/components/Card/cardState.utils.ts
  • src/components/Card/pin.utils.ts
  • src/components/Card/share-asset/PixelatedCardFace.tsx
  • src/components/Card/share-asset/RejectionAssetD3.tsx
  • src/components/Card/share-asset/ShareAssetActions.tsx
  • src/components/Card/share-asset/ShareAssetD3.tsx
  • src/components/Card/share-asset/captureShareAsset.ts
  • src/components/Card/share-asset/shareAsset.types.ts
  • src/components/Claim/Claim.tsx
  • src/components/Claim/Generic/ClaimError.view.tsx
  • src/components/Claim/Generic/Claimed.view.tsx
  • src/components/Claim/Link/Initial.view.tsx
  • src/components/Claim/Link/MantecaFlowManager.tsx
  • src/components/Claim/Link/Onchain/Confirm.view.tsx
  • src/components/Claim/Link/Onchain/Success.view.tsx
  • src/components/Claim/Link/SendLinkActionList.tsx
  • src/components/Claim/Link/__tests__/SendLinkActionList.test.tsx
  • src/components/Claim/Link/views/BankFlowManager.view.tsx
  • src/components/Claim/Link/views/Confirm.bank-claim.view.tsx
  • src/components/Claim/Link/views/MantecaDetailsStep.view.tsx
  • src/components/Claim/Link/views/MantecaReviewStep.tsx
  • src/components/Claim/__tests__/claim-states.test.tsx
  • src/components/Claim/useClaimLink.tsx
  • src/components/Common/ContactsListSkeleton.tsx
  • src/components/Common/CountryList.tsx
  • src/components/Common/CountryListRouter.tsx
  • src/components/Common/PointsCard.tsx
  • src/components/Common/SavedAccountsView.tsx
  • src/components/Create/useCreateLink.tsx
  • src/components/ExchangeRate/index.tsx
  • src/components/ForceIOSPWAInstall/index.tsx
  • src/components/Global/AmountInput/index.tsx
  • src/components/Global/AppLock/__tests__/app-lock-gate.test.tsx
  • src/components/Global/AppLock/index.tsx
  • src/components/Global/Attachment/index.tsx
  • src/components/Global/BackendErrorScreen/index.tsx
  • src/components/Global/Badges/StatusBadge.tsx
  • src/components/Global/BalanceWarningModal/index.tsx
  • src/components/Global/Banner/MantecaTransfersMaintenanceView.tsx
  • src/components/Global/Banner/index.tsx
  • src/components/Global/CancelSendLinkModal/index.tsx
  • src/components/Global/ConfirmInviteModal/index.tsx
  • src/components/Global/CopyField/index.tsx
  • src/components/Global/CopyToClipboard/index.tsx
  • src/components/Global/CreateAccountButton/index.tsx
  • src/components/Global/DocsLink.tsx
  • src/components/Global/EarlyUserModal/index.tsx
  • src/components/Global/EasterEggModal/index.tsx
  • src/components/Global/ErrorAlert/index.tsx
  • src/components/Global/ExchangeRateWidget/index.tsx
  • src/components/Global/FileUploadInput/index.tsx
  • src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx
  • src/components/Global/GeneralRecipientInput/index.tsx
  • src/components/Global/GuestLoginModal/index.tsx
  • src/components/Global/GuestVerificationModal/index.tsx
  • src/components/Global/Icons/Icon.tsx
  • src/components/Global/Icons/store-brands.tsx
  • src/components/Global/IframeWrapper/__tests__/IframeWrapper.test.tsx
  • src/components/Global/IframeWrapper/index.tsx
  • src/components/Global/InfoCard/index.tsx
  • src/components/Global/InviteFriendsModal/index.tsx
  • src/components/Global/InvitesGraph/index.tsx
  • src/components/Global/IosPwaInstallModal/index.tsx
  • src/components/Global/Layout/index.tsx
  • src/components/Global/LogoutButton/index.tsx
  • src/components/Global/MarqueeWrapper/index.tsx
  • src/components/Global/Modal/index.tsx
  • src/components/Global/NavHeader/index.tsx
  • src/components/Global/NoMoreJailModal/index.tsx
  • src/components/Global/OfflineScreen/index.tsx
  • src/components/Global/PeanutActionCard/index.tsx
  • src/components/Global/PeanutActionDetailsCard/__tests__/index.test.tsx
  • src/components/Global/PeanutActionDetailsCard/index.tsx
  • src/components/Global/PeanutLoading/CyclingLoading.tsx
  • src/components/Global/PeanutLoading/index.tsx
  • src/components/Global/PeanutLoading/words.ts
  • src/components/Global/PostSignupActionManager/index.tsx
  • src/components/Global/ProgressBar/index.tsx
  • src/components/Global/QRBottomDrawer/index.tsx
  • src/components/Global/QRCodeWrapper/index.tsx
  • src/components/Global/QRScanner/CameraPermissionModal.tsx
  • src/components/Global/QRScanner/__tests__/index.test.tsx
  • src/components/Global/QRScanner/index.tsx
  • src/components/Global/QRScanner/useQRScanner.ts
  • src/components/Global/QRScannerOverlay/index.tsx
  • src/components/Global/RainCooldown/IntroModal.tsx
  • src/components/Global/RouteExpiryTimer/index.tsx
  • src/components/Global/ScreenOrientationLocker.tsx
  • src/components/Global/SecurityVerificationOverlay/index.tsx
  • src/components/Global/ShareButton/__tests__/ShareButton.test.tsx
  • src/components/Global/ShareButton/index.tsx
  • src/components/Global/SoundPlayer.tsx
  • src/components/Global/StaleCardApproval/ReEnableModal.tsx
  • src/components/Global/StaleCardApproval/__tests__/ReEnableModal.test.tsx
  • src/components/Global/StaleDeploymentReload/index.tsx
  • src/components/Global/SuccessViewComponents/SuccessViewDetailsCard.tsx
  • src/components/Global/SupportCTA/index.tsx
  • src/components/Global/SupportDrawer/__tests__/SupportDrawer.test.tsx
  • src/components/Global/SupportDrawer/index.tsx
  • src/components/Global/TokenAndNetworkConfirmationModal/index.tsx
  • src/components/Global/TokenSelector/Components/NetworkButton.tsx
  • src/components/Global/TokenSelector/Components/NetworkListView.tsx
  • src/components/Global/TokenSelector/Components/SearchInput.tsx
  • src/components/Global/TokenSelector/Components/TokenListItem.tsx
  • src/components/Global/TokenSelector/TokenSelector.consts.ts
  • src/components/Global/TokenSelector/TokenSelector.tsx
  • src/components/Global/TopNavbar/index.tsx
  • src/components/Global/UnsupportedBrowserModal/index.tsx
  • src/components/Global/ValidatedInput/index.tsx
  • src/components/Global/WalletNavigation/index.tsx
  • src/components/Global/__tests__/docs-link.test.ts
  • src/components/Home/ActivationCTAs.tsx
  • src/components/Home/CardLaunchCTA/CardLaunchCTABanner.tsx
  • src/components/Home/EnableAutoBalanceBanner.tsx
  • src/components/Home/HomeCarouselCTA/CarouselCTA.tsx
  • src/components/Home/HomeCarouselCTA/index.tsx
  • src/components/Home/HomeHistory.tsx
  • src/components/Home/PerkClaimModal.tsx
  • src/components/Home/WelcomeUnlockModal/index.tsx
  • src/components/Home/__tests__/ActivationCTAs.test.tsx
  • src/components/Home/__tests__/EnableAutoBalanceBanner.test.tsx
  • src/components/IdentityVerification/UnlockRegionModal.tsx
  • src/components/Invites/InvitesPage.tsx
  • src/components/Invites/InvitesPageLayout.tsx
  • src/components/Invites/JoinWaitlistPage.tsx
  • src/components/Invites/campaign-maps.test.ts
  • src/components/Invites/campaign-maps.ts
  • src/components/Jobs/index.tsx
  • src/components/Kyc/AdvisoryPreemptModal.tsx
  • src/components/Kyc/BridgeTosStep.tsx
  • src/components/Kyc/CountryRegionRow.tsx
  • src/components/Kyc/InitiateKycModal.tsx
  • src/components/Kyc/KYCStatusDrawerItem.tsx
  • src/components/Kyc/KycFailedContent.tsx
  • src/components/Kyc/KycReverificationPendingModal.tsx
  • src/components/Kyc/KycStatusDrawer.tsx
  • src/components/Kyc/KycStatusItem.tsx
  • src/components/Kyc/KycVerificationInProgressModal.tsx
  • src/components/Kyc/PeanutDoesntStoreAnyPersonalInformation.tsx
  • src/components/Kyc/ProvideEmailStep.tsx
  • src/components/Kyc/RejectLabelsList.tsx
  • src/components/Kyc/SumsubKycFlow.tsx
  • src/components/Kyc/SumsubKycWrapper.tsx
  • src/components/Kyc/SumsubNativeSdk.tsx
  • src/components/Kyc/SumsubSdkErrorView.tsx
  • src/components/Kyc/__tests__/SumsubKycWrapper.test.tsx
  • src/components/Kyc/__tests__/SumsubNativeSdk.test.tsx
  • src/components/Kyc/modals/KycActionRequiredModal.tsx
  • src/components/Kyc/modals/KycFailedModal.tsx
  • src/components/Kyc/modals/KycProcessingModal.tsx
  • src/components/Kyc/states/KycActionRequired.tsx
  • src/components/Kyc/states/KycCompleted.tsx
  • src/components/Kyc/states/KycFailed.tsx
  • src/components/Kyc/states/KycProcessing.tsx
  • src/components/Kyc/states/__tests__/KycActionRequired.rejectCopy.test.tsx
  • src/components/Kyc/states/__tests__/KycStates.test.tsx
  • src/components/Kyc/states/__tests__/kycCallbackHygiene.test.tsx
  • src/components/Kyc/sumsubSdk.types.ts
  • src/components/LandingPage/CardPioneers.tsx
  • src/components/LandingPage/CloudsCss.tsx
  • src/components/LandingPage/CurrencySelect.tsx
  • src/components/LandingPage/Footer.tsx
  • src/components/LandingPage/LandingPageCapacitorGate.tsx
  • src/components/LandingPage/LandingPageClient.tsx
  • src/components/LandingPage/LandingPageContent.tsx
  • src/components/LandingPage/LandingPageShell.tsx
  • src/components/LandingPage/Manteca.tsx
  • src/components/LandingPage/RegulatedRails.tsx
  • src/components/LandingPage/SEOFooter.tsx
  • src/components/LandingPage/SendInSecondsCTA.tsx
  • src/components/LandingPage/StickyMobileCTA.tsx
  • src/components/LandingPage/TweetCarousel.tsx
  • src/components/LandingPage/dropLink.tsx
  • src/components/LandingPage/faq.tsx
  • src/components/LandingPage/hero.tsx
  • src/components/LandingPage/landing.types.ts
  • src/components/LandingPage/landingStrings.ts
  • src/components/LandingPage/marquee.tsx
  • src/components/LandingPage/noFees.tsx
  • src/components/LandingPage/securityBuiltIn.tsx
  • src/components/LandingPage/sendInSeconds.tsx
  • src/components/LandingPage/yourMoney.tsx
  • src/components/Marketing/ArticleBackNav.tsx
  • src/components/Marketing/ContentPage.tsx
  • src/components/Marketing/DestinationGrid.tsx
  • src/components/Marketing/HtmlLang.tsx
  • src/components/Marketing/LocaleSuggestion.tsx
  • src/components/Marketing/LocaleSwitcher.tsx
  • src/components/Marketing/MarketingErrorBoundary.tsx
  • src/components/Marketing/MarketingHero.tsx
  • src/components/Marketing/__tests__/locale-switcher.test.ts
  • src/components/Marketing/mdx/CountryGrid.tsx
  • src/components/Marketing/mdx/ExchangeWidget.tsx
  • src/components/Marketing/mdx/FAQ.tsx
  • src/components/Marketing/mdx/Hero.tsx
  • src/components/Marketing/mdx/ProseStars.tsx
  • src/components/Marketing/mdx/RelatedPages.tsx
  • src/components/Marketing/mdx/Stars.tsx
  • src/components/Marketing/mdx/Steps.tsx
  • src/components/Marketing/mdx/components.tsx
  • src/components/Migration/DownloadQR.tsx
  • src/components/Migration/MigrationDownloadModal.tsx
  • src/components/Migration/MigrationHero.tsx
  • src/components/Migration/ReviewPromptModal.tsx
  • src/components/Migration/ScanToDownloadModal.tsx
  • src/components/Migration/StoreBadges.tsx
  • src/components/Migration/StoreButtons.tsx
  • src/components/Migration/SunsetScreen.tsx
  • src/components/Migration/__tests__/MigrationDownloadModal.test.tsx
  • src/components/Notifications/SetupNotificationsModal.tsx
  • src/components/Offramp/Offramp.consts.ts
  • src/components/Payment/Views/Error.validation.view.tsx
  • src/components/Points/InviteePointsBadge.tsx
  • src/components/Profile/components/ProfileEditField.tsx
  • src/components/Profile/components/ProfileHeader.tsx
  • src/components/Profile/components/ProfileMenuItem.tsx
  • src/components/Profile/components/PublicProfile.tsx
  • src/components/Profile/index.tsx
  • src/components/Profile/views/ProfileEdit.view.tsx
  • src/components/Profile/views/UnlockedRegions.view.tsx
  • src/components/Request/Pay/Pay.tsx
  • src/components/Request/__tests__/request-states.test.tsx
  • src/components/Request/direct-request/views/Initial.direct.request.view.tsx
  • src/components/Request/link/views/Create.request.link.view.tsx
  • src/components/Send/__tests__/send-states.test.tsx
  • src/components/Send/link/LinkSendFlowManager.tsx
  • src/components/Send/link/views/Initial.link.send.view.tsx
  • src/components/Send/link/views/Success.link.send.view.tsx
  • src/components/Send/link/views/__tests__/Initial.link.send.view.test.tsx
  • src/components/Send/views/Contacts.view.tsx
  • src/components/Send/views/SendRouter.view.tsx
  • src/components/Settings/DeleteAccountButton.tsx
  • src/components/Settings/LanguageView.tsx
  • src/components/Settings/__tests__/DeleteAccountButton.test.tsx
  • src/components/Setup/Setup.consts.tsx
  • src/components/Setup/Setup.types.ts
  • src/components/Setup/Setup.utils.ts
  • src/components/Setup/Views/InstallPWA.tsx
  • src/components/Setup/Views/JoinWaitlist.tsx
  • src/components/Setup/Views/Landing.tsx
  • src/components/Setup/Views/PasskeySetupHelpModal.tsx
  • src/components/Setup/Views/SetupPasskey.tsx
  • src/components/Setup/Views/SignTestTransaction.tsx
  • src/components/Setup/Views/Signup.tsx
  • src/components/Setup/components/SetupWrapper.tsx
  • src/components/TransactionDetails/PerkIcon.tsx
  • src/components/TransactionDetails/TransactionCard.tsx
  • src/components/TransactionDetails/TransactionDetailsDrawer.tsx
  • src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx
  • src/components/TransactionDetails/TransactionDetailsReceipt.tsx
  • src/components/TransactionDetails/__tests__/CardUsdAbroadNotice.test.tsx
  • src/components/TransactionDetails/__tests__/LocalRailNudge.test.tsx
  • src/components/TransactionDetails/__tests__/TransactionCard.test.tsx
  • src/components/TransactionDetails/__tests__/transaction-details.utils.test.ts
  • src/components/TransactionDetails/__tests__/transactionTransformer.test.ts
  • src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx
  • src/components/TransactionDetails/provider-actions/__tests__/CancelDepositActions.test.tsx
  • src/components/TransactionDetails/provider-receipts/PerkRewardReceipt.tsx
  • src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx
  • src/components/TransactionDetails/provider-rows/CardPaymentRows.tsx
  • src/components/TransactionDetails/provider-rows/CardUsdAbroadNotice.tsx
  • src/components/TransactionDetails/provider-rows/LocalRailNudge.tsx
  • src/components/TransactionDetails/provider-rows/MantecaDepositInfo.tsx
  • src/components/TransactionDetails/provider-rows/__tests__/BridgeDepositInstructions.test.tsx
  • src/components/TransactionDetails/provider-rows/__tests__/CardPaymentRows.settlement-adjustment.test.tsx
  • src/components/TransactionDetails/provider-rows/__tests__/dispute-label.test.ts
  • src/components/TransactionDetails/strategies/fallback.ts
  • src/components/TransactionDetails/strategies/intent/card.ts
  • src/components/TransactionDetails/strategies/intent/crypto.ts
  • src/components/TransactionDetails/strategies/intent/fiat-offramp.ts
  • src/components/TransactionDetails/strategies/intent/fiat-onramp.ts
  • src/components/TransactionDetails/strategies/intent/p2p-send.ts
  • src/components/TransactionDetails/strategies/intent/perk-reward.ts
  • src/components/TransactionDetails/strategies/intent/refund.ts
  • src/components/TransactionDetails/strategies/intent/send-link.ts
  • src/components/TransactionDetails/strategies/types.ts
  • src/components/TransactionDetails/transaction-details.utils.ts
  • src/components/TransactionDetails/transaction-name-keys.ts
  • src/components/TransactionDetails/transactionTransformer.ts
  • src/components/TransactionDetails/useReceiptDateFormatter.ts
  • src/components/User/UserCard.tsx
  • src/components/UserHeader/index.tsx
  • src/components/Withdraw/views/Confirm.withdraw.view.tsx
  • src/components/Withdraw/views/Initial.withdraw.view.tsx
  • src/components/Withdraw/views/PixKeySend.view.tsx
  • src/components/index.ts
  • src/components/og/PaymentCardOG.tsx
  • src/components/og/ReceiptCardOG.tsx
  • src/config/index.ts
  • src/config/peanut.config.tsx
  • src/config/underMaintenance.config.ts
  • src/constants/__tests__/chainRegistry.test.ts
  • src/constants/__tests__/nonEvmLeak.test.ts
  • src/constants/__tests__/routes.test.ts
  • src/constants/actionlist.consts.ts
  • src/constants/analytics.consts.ts
  • src/constants/app-lock.consts.ts
  • src/constants/cache.consts.ts
  • src/constants/capability-reason-labels.consts.ts
  • src/constants/general.consts.ts
  • src/constants/invites.consts.ts
  • src/constants/kyc.consts.ts
  • src/constants/loadingStates.consts.ts
  • src/constants/migration.consts.ts
  • src/constants/routes.ts
  • src/constants/sumsub-reject-labels.consts.ts
  • src/constants/zerodev.consts.ts
  • src/context/ClaimBankFlowContext.tsx
  • src/context/LinkSendFlowContext.tsx
  • src/context/ModalsContext.tsx
  • src/context/PeanutDebug.tsx
  • src/context/RainCooldownContext.tsx
  • src/context/RequestFulfillmentFlowContext.tsx
  • src/context/WithdrawFlowContext.tsx
  • src/context/__tests__/RainCooldownContext.test.tsx
  • src/context/authContext.tsx
  • src/context/index.ts
  • src/context/kernelClient.context.tsx
  • src/context/loadingStates.context.tsx
  • src/context/tokenSelector.context.tsx
  • src/features/limits/components/CryptoLimitsSection.tsx
  • src/features/limits/components/FiatLimitsLockedCard.tsx
  • src/features/limits/components/IncreaseLimitsButton.tsx
  • src/features/limits/components/LimitsDocsLink.tsx
  • src/features/limits/components/LimitsError.tsx
  • src/features/limits/components/LimitsWarningCard.tsx
  • src/features/limits/components/PeriodToggle.tsx
  • src/features/limits/hooks/useLimitsValidation.ts
  • src/features/limits/utils.ts
  • src/features/limits/views/BridgeLimitsView.tsx
  • src/features/limits/views/LimitsPageView.tsx
  • src/features/limits/views/MantecaLimitsView.tsx
  • src/features/payments/flows/contribute-pot/ContributePotPageWrapper.tsx
  • src/features/payments/flows/contribute-pot/components/ContributorsDrawer.tsx
  • src/features/payments/flows/contribute-pot/components/RequestPotActionList.tsx
  • src/features/payments/flows/contribute-pot/useContributePotFlow.ts
  • src/features/payments/flows/contribute-pot/views/ContributePotInputView.tsx
  • src/features/payments/flows/contribute-pot/views/ContributePotSuccessView.tsx
  • src/features/payments/flows/contribute-pot/views/ExternalWalletPaymentView.tsx
  • src/features/payments/flows/direct-send/DirectSendPageWrapper.tsx
  • src/features/payments/flows/direct-send/useDirectSendFlow.ts
  • src/features/payments/flows/direct-send/views/SendInputView.tsx
  • src/features/payments/flows/direct-send/views/SendSuccessView.tsx
  • src/features/payments/flows/semantic-request/SemanticRequestPageWrapper.tsx
  • src/features/payments/flows/semantic-request/useSemanticRequestFlow.ts
  • src/features/payments/flows/semantic-request/views/SemanticRequestConfirmView.tsx
  • src/features/payments/flows/semantic-request/views/SemanticRequestExternalWalletView.tsx
  • src/features/payments/flows/semantic-request/views/SemanticRequestInputView.tsx
  • src/features/payments/flows/semantic-request/views/SemanticRequestReceiptView.tsx
  • src/features/payments/flows/semantic-request/views/SemanticRequestSuccessView.tsx
  • src/features/payments/shared/components/PaymentMethodActionList.tsx
  • src/features/payments/shared/components/PaymentSuccessView.tsx
  • src/features/payments/shared/components/SendWithPeanutCta.tsx
  • src/features/payments/shared/components/__tests__/PaymentMethodActionList.test.tsx
  • src/hooks/__tests__/useGetExchangeRate.test.ts
  • src/hooks/__tests__/useNativePlugins.test.tsx
  • src/hooks/__tests__/useStaleDeploymentReload.test.tsx
  • src/hooks/__tests__/useSumsubKycFlow.test.ts
  • src/hooks/__tests__/useUserAutoRefresh.test.ts
  • src/hooks/__tests__/useWaitingOnProviderModal.test.ts
  • src/hooks/query/__tests__/user.test.tsx
  • src/hooks/query/user.ts
  • src/hooks/useAccountSetup.ts
  • src/hooks/useAccountSetupRedirect.ts
  • src/hooks/useActivationStatus.ts
  • src/hooks/useAppLocked.ts
  • src/hooks/useCapabilities.test.ts
  • src/hooks/useContacts.ts
  • src/hooks/useCreateOnramp.ts
  • src/hooks/useCrispProxyUrl.ts
  • src/hooks/useCrispUserData.ts
  • src/hooks/useDetermineBankClaimType.ts
  • src/hooks/useDetermineBankRequestType.ts
  • src/hooks/useFeatureFlag.ts
  • src/hooks/useFriendlyError.ts
  • src/hooks/useGeoLocation.ts
  • src/hooks/useGetBrowserType.ts
  • src/hooks/useGetExchangeRate.tsx
  • src/hooks/useGuestStoreHandoff.tsx
  • src/hooks/useHomeCarouselCTAs.tsx
  • src/hooks/useKeepWebBypass.ts
  • src/hooks/useLimits.ts
  • src/hooks/useLogin.tsx
  • src/hooks/useMigrationFlag.ts
  • src/hooks/useNativePlugins.ts
  • src/hooks/useNotifications.ts
  • src/hooks/useOnrampQuote.ts
  • src/hooks/usePWAStatus.ts
  • src/hooks/useSendFlowOrigin.test.ts
  • src/hooks/useSendFlowOrigin.ts
  • src/hooks/useSetupFlow.ts
  • src/hooks/useStaleDeploymentReload.ts
  • src/hooks/useSumsubActionFlow.ts
  • src/hooks/useSumsubKycFlow.ts
  • src/hooks/useTokenPrice.ts
  • src/hooks/useTranslationMutationHandler.ts
  • src/hooks/useUserAutoRefresh.ts
  • src/hooks/useWaitingOnProviderModal.ts
  • src/hooks/useZeroDev.ts
  • src/hooks/wallet/__tests__/useSendMoney.test.tsx
  • src/hooks/wallet/useGrantSessionKey.ts
  • src/hooks/wallet/useSendMoney.ts
  • src/hooks/wallet/useSpendBundle.ts
  • src/i18n/__tests__/locale-bridge.test.ts
  • src/i18n/__tests__/messages.test.ts
  • src/i18n/app/AppIntlProvider.tsx
  • src/i18n/app/__tests__/loading-states.test.ts
  • src/i18n/app/__tests__/locale-store.test.ts
  • src/i18n/app/__tests__/messages.test.ts
  • src/i18n/app/__tests__/reject-labels.test.ts
  • src/i18n/app/__tests__/resolve-locale.test.ts
  • src/i18n/app/__tests__/shhhhh-catalog.test.ts
  • src/i18n/app/config.ts
  • src/i18n/app/loading-states.ts
  • src/i18n/app/locale-store.ts
  • src/i18n/app/messages.ts
  • src/i18n/app/messages/en.json
  • src/i18n/app/messages/es-419.json
  • src/i18n/app/messages/es-AR.json
  • src/i18n/app/messages/pt-BR.json
  • src/i18n/app/next-intl.d.ts
  • src/i18n/config.ts
  • src/i18n/en.json
  • src/i18n/es-419.json
  • src/i18n/es-ar.json
  • src/i18n/es-es.json
  • src/i18n/index.ts
  • src/i18n/localeBridge.ts
  • src/i18n/localeMeta.ts
  • src/i18n/pt-br.json
  • src/i18n/types.ts
  • src/i18n/useUrlLocale.ts
  • src/interfaces/index.ts
  • src/interfaces/interfaces.ts
  • src/lib/blog.ts
  • src/lib/content.test.ts
  • src/lib/content.ts
  • src/lib/mdx.ts
  • src/lib/seo/landing.ts
  • src/lib/seo/schemas.tsx
  • src/lib/url-parser/parser.ts
  • src/lib/validation/recipient.ts
  • src/proxy.ts
  • src/redux/slices/user-slice.ts
  • src/redux/types/user.types.ts
  • src/services/api-error.ts
  • src/services/card.ts
  • src/services/charges.ts
  • src/services/manteca.ts
  • src/services/quests.ts
  • src/services/rain.ts
  • src/services/rhino-bridge.ts
  • src/services/rhino-sda.ts
  • src/services/sendLinks.ts
  • src/services/tokens-price.ts
  • src/services/users.ts
  • src/services/websocket.ts
  • src/test-utils/intl.tsx
  • src/types/api.openapi.json
  • src/types/global.d.ts
  • src/types/react-force-graph.d.ts
  • src/types/sumsub-cordova.d.ts
  • src/utils/__mocks__/simplewebauthn-browser.ts
  • src/utils/__tests__/api-fetch.test.ts
  • src/utils/__tests__/app-lock-state.test.ts
  • src/utils/__tests__/auth-token.test.ts
  • src/utils/__tests__/capacitor.test.ts
  • src/utils/__tests__/cardDeclineReason.test.ts
  • src/utils/__tests__/demo-api.test.ts
  • src/utils/__tests__/demo-balance.test.ts
  • src/utils/__tests__/friendly-error.utils.test.tsx
  • src/utils/__tests__/general.utils.test.ts
  • src/utils/__tests__/migration.utils.test.ts
  • src/utils/__tests__/native-routes.test.ts
  • src/utils/__tests__/railGate.utils.test.ts
  • src/utils/__tests__/secure-token-store.test.ts
  • src/utils/__tests__/url.utils.test.ts
  • src/utils/api-fetch.ts
  • src/utils/app-lock-state.ts
  • src/utils/app-lock.ts
  • src/utils/auth-token.ts
  • src/utils/balance.utils.ts
  • src/utils/bridge.utils.ts
  • src/utils/cache.utils.ts
  • src/utils/capability-gate.ts
  • src/utils/capacitor.ts
  • src/utils/cardDeclineReason.ts
  • src/utils/clipboard-extract.utils.ts
  • src/utils/crisp.ts
  • src/utils/dateGrouping.utils.ts
  • src/utils/demo-api.ts
  • src/utils/friendly-error.utils.tsx
  • src/utils/general.utils.ts
  • src/utils/history.utils.ts
  • src/utils/kyc-grouping.utils.ts
  • src/utils/migration.utils.ts
  • src/utils/native-auth-capture.ts
  • src/utils/native-canary.ts
  • src/utils/native-routes.ts
  • src/utils/no-cache.ts
  • src/utils/passkeyDebug.ts
  • src/utils/peanut-claim.utils.ts
  • src/utils/provider-rejection.utils.ts
  • src/utils/qr-payment.utils.ts
  • src/utils/railGate.utils.ts
  • src/utils/regions.utils.ts
  • src/utils/secure-token-store.ts
  • src/utils/sentry.utils.ts
  • src/utils/token.utils.ts
  • src/utils/webauthn.utils.ts
  • tsconfig.test.json
  • vercel.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 6345.36 → 7065.51 (+720.15)
Findings: +151 net (+1908 new, -1757 resolved)

🆕 New findings (1908)

  • critical complexity — src/components/Global/InvitesGraph/index.tsx — CC 515, MI 53.18, SLOC 1713
  • critical complexity — src/app/(mobile-ui)/qr-pay/page.tsx — CC 306, MI 52.56, SLOC 1078
  • critical complexity — src/components/Claim/Link/Initial.view.tsx — CC 213, MI 50.68, SLOC 731
  • critical complexity — src/utils/general.utils.ts — CC 199, MI 57.59, SLOC 758
  • critical complexity — src/components/TransactionDetails/TransactionDetailsReceipt.tsx — CC 163, MI 51.34, SLOC 426
  • critical complexity — src/app/(mobile-ui)/withdraw/manteca/page.tsx — CC 157, MI 51.57, SLOC 594
  • critical complexity — src/components/AddWithdraw/DynamicBankAccountForm.tsx — CC 152, MI 51.95, SLOC 465
  • critical complexity — src/app/(mobile-ui)/card/page.tsx — CC 128, MI 56.73, SLOC 495
  • critical complexity — src/components/Global/TokenSelector/TokenSelector.tsx — CC 127, MI 60.45, SLOC 353
  • critical complexity — src/components/AddWithdraw/AddWithdrawCountriesList.tsx — CC 122, MI 56.36, SLOC 370
  • critical complexity — src/app/(mobile-ui)/withdraw/page.tsx — CC 121, MI 53.24, SLOC 364
  • critical complexity — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — CC 112, MI 57.43, SLOC 392
  • critical complexity — src/components/Claim/Link/views/BankFlowManager.view.tsx — CC 110, MI 46.92, SLOC 426
  • critical method-complexity — src/components/TransactionDetails/TransactionDetailsReceipt.tsx:89 — CC 109 SLOC 217
  • critical complexity — src/utils/demo-api.ts — CC 107, MI 59.5, SLOC 917
  • critical complexity — src/features/payments/flows/semantic-request/useSemanticRequestFlow.ts — CC 106, MI 49.11, SLOC 457
  • critical complexity — src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx — CC 104, MI 53.33, SLOC 386
  • critical complexity — src/components/Home/HomeHistory.tsx — CC 104, MI 57.65, SLOC 321
  • critical complexity — src/context/kernelClient.context.tsx — CC 101, MI 57.09, SLOC 477
  • critical complexity — src/components/Claim/Claim.tsx — CC 100, MI 53.54, SLOC 404

…and 1888 more.

✅ Resolved (1757)

  • src/components/Global/InvitesGraph/index.tsx — CC 518, MI 53.17, SLOC 1709
  • src/app/(mobile-ui)/qr-pay/page.tsx — CC 305, MI 53.59, SLOC 971
  • src/components/Claim/Link/Initial.view.tsx — CC 212, MI 51.11, SLOC 686
  • src/utils/general.utils.ts — CC 202, MI 57.68, SLOC 763
  • src/components/TransactionDetails/TransactionDetailsReceipt.tsx — CC 160, MI 52.91, SLOC 351
  • src/app/(mobile-ui)/withdraw/manteca/page.tsx — CC 155, MI 52.57, SLOC 528
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx — CC 149, MI 53.51, SLOC 410
  • src/app/(mobile-ui)/card/page.tsx — CC 126, MI 57.18, SLOC 478
  • src/components/Global/TokenSelector/TokenSelector.tsx — CC 126, MI 60.85, SLOC 331
  • src/app/(mobile-ui)/withdraw/page.tsx — CC 124, MI 54.12, SLOC 334
  • src/components/AddWithdraw/AddWithdrawCountriesList.tsx — CC 123, MI 56.91, SLOC 351
  • src/components/Claim/Link/views/BankFlowManager.view.tsx — CC 110, MI 47.15, SLOC 417
  • src/components/TransactionDetails/TransactionDetailsReceipt.tsx:74 — CC 108 SLOC 169
  • src/utils/demo-api.ts — CC 107, MI 59.52, SLOC 917
  • src/features/payments/flows/semantic-request/useSemanticRequestFlow.ts — CC 106, MI 49.34, SLOC 448
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx — CC 101, MI 54.48, SLOC 352
  • src/context/kernelClient.context.tsx — CC 101, MI 57.1, SLOC 477
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — CC 100, MI 57.56, SLOC 345
  • src/components/Claim/Claim.tsx — CC 100, MI 53.93, SLOC 389
  • src/components/Home/HomeHistory.tsx — CC 99, MI 58.51, SLOC 300

…and 1737 more.

📈 Painscore deltas (top movers)

File Before After Δ
src/components/Migration/MigrationDownloadModal.tsx 0.0 8.9 +8.9
src/components/Kyc/SumsubNativeSdk.tsx 0.0 8.6 +8.6
src/components/Migration/ReviewPromptModal.tsx 0.0 8.1 +8.1
src/i18n/app/AppIntlProvider.tsx 0.0 7.7 +7.7
src/hooks/useStaleDeploymentReload.ts 0.0 7.5 +7.5
src/app/app/page.tsx 0.0 7.5 +7.5
src/components/LandingPage/landingStrings.ts 0.0 7.4 +7.4
src/components/Marketing/LocaleSuggestion.tsx 0.0 7.1 +7.1
src/utils/native-auth-capture.ts 0.0 6.8 +6.8
src/components/Marketing/LocaleSwitcher.tsx 0.0 6.5 +6.5
src/hooks/useFriendlyError.ts 0.0 6.3 +6.3
src/i18n/app/locale-store.ts 0.0 6.2 +6.2
src/utils/secure-token-store.ts 0.0 6.2 +6.2
src/hooks/useGuestStoreHandoff.tsx 0.0 5.9 +5.9
src/utils/native-canary.ts 0.0 5.8 +5.8
src/i18n/app/config.ts 0.0 5.8 +5.8
src/i18n/app/messages.ts 0.0 5.8 +5.8
src/hooks/useSendFlowOrigin.ts 0.0 5.7 +5.7
src/components/TransactionDetails/useReceiptDateFormatter.ts 0.0 5.6 +5.6
src/app/(mobile-ui)/dev/journey/emailReview.ts 0.0 5.4 +5.4

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 2677 ran, 0 failed, 0 skipped, 34.5s

📊 Coverage (unit)

metric %
statements 64.4%
branches 48.6%
functions 54.0%
lines 65.1%
⏱ 10 slowest test cases
time test
2.6s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.0s src/utils/__tests__/demo-api.test.ts › isDemoMode() is false when not running under Capacitor
0.3s src/utils/__tests__/sentry.utils.test.ts › defaults to the client budget under a browser global
0.3s src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx › Bank withdrawal keeps the $1 minimum for sub-$1 amounts
0.3s src/utils/__tests__/sentry.utils.test.ts › still lets a per-call timeoutMs win over the default
0.2s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.2s src/utils/__tests__/auth-token.test.ts › ignores the guarded marker and falls back to the plain token
0.2s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in validateInviteCode body
0.2s src/utils/__tests__/auth-token.test.ts › returns the token hydrated from Preferences after authReady
0.2s src/utils/__tests__/auth-token.test.ts › is none — never guarded — when only the guarded marker is present
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

abalinda and others added 7 commits August 6, 2026 12:37
Send has no destination screens of its own — SendRouter navigates into the
withdraw routes (`/withdraw?method=crypto`, `?method=bank`), so `?method=` is
the only signal that the user framed this as a send. `/withdraw` honours it
("Send", "Amount to send") and forwards it to `/withdraw/crypto?method=crypto`,
but that page never read searchParams. The marker arrived and was dropped, so
every screen after the amount step reverted to withdraw copy: pick
Send → Exchange or Wallet, and the next screen says "You're withdrawing".

The word itself is not the bug. PeanutActionDetailsCard maps one
transactionType to one title, and WITHDRAW is genuinely both a withdrawal and
a send depending on how the user arrived — so it has already been flipped in
opposite directions twice (abd71b8 → "sending", d532b6a → "withdrawing"),
each engineer right about the flow in front of them. Flipping it a third time
would just re-break the real withdraw flow. Give the card the discriminator it
was missing instead.

isFromSendFlow is a narrow presentation flag, not a new transactionType: the
transaction really is a withdraw, and arrow-up/wallet-outline are already
correct for both framings, so only the verb branches. Same reason
PaymentSuccessView keeps isWithdrawFlow — it also suppresses the recipient
render and picks the "to" prefix, both right for a send to an address.

useSendFlowOrigin replaces four copies of the marker rule that had drifted into
three different definitions, which is how the screens came apart in the first
place. Manteca (Pix/Mercado Pago) has the same defect on its own page and is a
deliberate follow-up.
The Fit OKR needs the language a user's phone asks for vs the language they
actually use, to read the override rate (served their language, switched to
English). app_locale already ships; this adds device_language (raw device or
browser tag, kept un-resolved so a non-ES/PT phone stays itself instead of
collapsing to en) and platform as super properties. No KYC join, so it works
web and native (the Capacitor webview runs posthog-js as-is).
…dge call

Addresses code-review findings on the device_language/platform emit:
- the once-guard was set before the await, so any throw (or posthog.reset()
  on logout wiping super properties) permanently dropped device_language for
  the session. Cache the resolved context and re-register it on logout,
  mirroring app_locale; set the guard only after a successful register so a
  throw can retry.
- memoize the raw device tag so the native Device.getLanguageTag() bridge call
  on the splash-gated startup path is shared with resolveStartupLocale instead
  of fired twice.
- test: resetAllMocks so a mockImplementation can't leak between cases.
…nguage

Addresses the CodeRabbit nitpick — the Capacitor branch of the device-context
emit was untested; assert the native bridge tag is lowercased and registered
with the native platform.
CodeRabbit caught two instances of the exact seam this PR exists to close,
on the bank side rather than the crypto side.

The bank review CTA still read "Withdraw" while the header and amount card
above it already read "Send" — the same screen disagreeing with itself.

Three bank redirects also dropped ?method=bank, so the step the user was sent
back to silently reverted to withdraw copy: the existing-saved-account push in
DynamicBankAccountForm, and the no-amount / no-account replaces in the bank
page. A fourth in the same file (the unsupported-country bounce) had the same
defect and is fixed here too; that one needed the hook hoisted above the
effect that uses it.
Three follow-ups from CodeRabbit's full pass, all cases of the marker being
read too eagerly rather than too little.

The marker alone doesn't mean "send": the add-money flow navigates with its
own ?method=bank, so AddWithdrawCountriesList — which serves both flows —
needs the same `flow === 'withdraw'` guard its sibling AddWithdrawRouterView
already had. (CodeRabbit's stated consequence pointed at
enforceSupportedCountries, which actually lives in the sibling and was already
guarded; the guard is still right here for the navigation branches.) Behaviour
is unchanged from before this PR — the previous expression had the same gap.

Entering as /withdraw?method=bank and then picking Crypto lands on
/withdraw/crypto?method=bank, where the back target hard-coded ?method=crypto
and silently rewrote the marker, changing the amount step's back behaviour.
The hook now exposes the raw value so callers forward it verbatim instead of
re-deriving it.

actionDetailsProps is a Partial of the card's full props, so now that
isFromSendFlow is one of them a caller could override the flow-guarded value.
Moved after the spread to keep the derived value authoritative.
…d-docs-locale

fix(i18n): stop app copy drifting between locales, and localize /shhhhh
abalinda and others added 3 commits August 6, 2026 16:13
dev landed six i18n commits, including a pass that dedups app copy across
locales. One real conflict, in es-419's peanutActionDetailsCard block: this
branch added `youreSending` while dev retranslated `youWillReceive`
("Recibirás" -> "Vas a recibir").

Resolved as a union — dev's retranslation wins for its own key, this branch's
new key is kept. Neither side loses an entry, which is the hazard git flags
here.

Everything else auto-merged, including dev's `t('confirm.sponsoredByPeanut')`
-> `tCommon('sponsoredByPeanut')` move inside Confirm.withdraw.view.tsx, which
sits next to this branch's CTA change in the same file.
…-analytics

feat(i18n): emit device_language + platform for localization OKR
fix(send): keep the send framing past the amount step
feat(card): geo-blocked state — stop prohibited-country users before the apply funnel
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants