Skip to content

post-cutover: TRANSACTION_INTENT completeness + masking + run-mode banner + cheat polish#1912

Open
Hugo0 wants to merge 4 commits intodevfrom
qa/post-cutover-fe-fixes
Open

post-cutover: TRANSACTION_INTENT completeness + masking + run-mode banner + cheat polish#1912
Hugo0 wants to merge 4 commits intodevfrom
qa/post-cutover-fe-fixes

Conversation

@Hugo0
Copy link
Copy Markdown
Contributor

@Hugo0 Hugo0 commented Apr 29, 2026

Summary

FE counterpart to peanut-api-ts#676. Four-PR-bundle of post-decomplexify fixes from the 2026-04-29 playtest.

Commit Slice Confidence
82faa1311 Table-driven test scaffold for transactionTransformer (33 cases) High
b16c0e712 Complete TRANSACTION_INTENT switch + bankAccountDetails plumbing + per-rail masking + invite-friends desktop toast Medium-high — wants design eyes on the masking strings
246c6847c Run-mode banner pill + %c-styled console log (yellow=sandbox, red=real-money) High
b4c974c47 Debug cheats: friendly errors + listUsers, harnessSigner, mode commands High

Why this exists

Hugo's playtest screenshots all traced to the same root: the new case EHistoryEntryType.TRANSACTION_INTENT switch in transactionTransformer.ts was shaped much shallower than the legacy switches it replaced — missing userRole=RECIPIENT branches, missing kind cases (no CRYPTO_DEPOSIT, no LINK_CREATE-claimer-resolution), and downstream visibility gates in useReceiptViewModel.ts + the bankAccountDetails projection still gated on legacy entry types only.

Manifested as:

  • (a) Send-via-link receipt no claimer (pre-existing, not regression)
  • (b) Invite-friends button silent on desktop
  • (c) No IBAN masking (feature)
  • (d) EU flag instead of ES — bankAccountDetails dropped for intent-routed offramps
  • (e) $2 PENDING zombie rows from Feb 18 with no Cancel — addressed via reaper in BE PR [TASK-8600] feat: validate usernames #676 + muted-FAIL copy here
  • (f) CRYPTO_DEPOSIT no avatar, not clickable — kind case missing entirely
  • (g) QR_PAY no points (BE listener gap, separate)

What changed

transactionTransformer.ts — fill the missing cases

  • New CRYPTO_DEPOSIT kind case. Sets isPeerActuallyUser=true when senderAccount.isUser (improvement over legacy DEPOSIT which always forced false).
  • New LINK_CREATE × RECIPIENT branch — claimer resolution mirroring legacy SEND_LINK.
  • New FIAT_OFFRAMP × RECIPIENT branch.
  • New REQUEST_PAY bridge-fulfillment subcase.
  • default arm: Sentry breadcrumb on unhandled kinds (defensive — a future BE-added kind no longer silently maps to 'send').
  • Reaper-failed branch: failReason='\${kind}_timeout' overrides userName to user-friendly copy ("Send didn't complete", "Bank transfer didn't complete", etc.) so zombie rows don't pretend the action succeeded.

bankAccountDetails plumbing (the EU/ES flag bug)

New shouldPlumbBankAccountDetails(entry) extends the gate to TRANSACTION_INTENT/kind=FIAT_OFFRAMP/CRYPTO_WITHDRAW + (legacy) MANTECA_OFFRAMP. Without this, intent-routed withdrawals lost the IBAN row and getBankAccountCountryCode fell back to currency-flag.

Visibility gates in useReceiptViewModel.ts

  • depositInstructions: extended to TRANSACTION_INTENT/kind=ONRAMP
  • mantecaDepositInfo: same extension

Per-rail account masking (utils/account-mask.utils.ts — new)

  • IBAN, CLABE, CBU, CVU: **** **** **** 0217
  • US ACH, GB: account-number-only mask (routing stays plain — bank-public)
  • PIX, MANTECA_ALIAS: NOT masked. PIX keys carry meaning (emails/phones/CPFs/UUIDs); masking would mangle. Truncate at 32 chars if needed.
  • Copy icon yields the FULL identifier — masking is for visual privacy, not interaction.

Run-mode banner (utils/mode.ts — new)

Classifies env into sandbox / staging-mirror / prod-real / custom. Banner pill in dev: yellow for sandbox, red for real-money. logRunMode() styles a 22px bold console banner on every page load via %c. Same helper backs the new debug.mode() cheat.

Debug cheats

  • debug.impersonate('username') is one-shot now — default harness PK hardcoded; resolution always overwrites stale localStorage values.
  • 404 errors render multi-line hints with username suggestions + "did you mean X, Y, Z?".
  • New: debug.listUsers(prefix?, limit?), debug.harnessSigner(pk?), debug.mode().
  • Network errors throw with "is the API running on $URL? Check 'qa status'".

Invite-friends desktop fix

navigator.share is mobile-only; desktop falls through to clipboard.writeText — added toast.info('Invite link copied!') matching existing ShareButton pattern.

Test plan

  • npm test — 962 passing
  • npm run typecheck — clean
  • Manual: /history row-clicks for each kind render correctly (verified during playtest)
  • Run-mode banner visible in dev, hidden in production builds
  • debug.impersonate('hugostagqa') is one-shot (no {pk} needed) on local clone

Out of scope (filed in api repo todo.md)

  • Avatar URL plumbing for CRYPTO_DEPOSIT senderAccount (needs BE schema change)
  • Send-link external-claimer info (pre-existing UX gap)
  • FE order-flip for charge-create (the structural fix for B2; reaper handles user-visible symptom)

Hugo0 added 4 commits April 29, 2026 13:33
…rmer

Decomplexify added a TRANSACTION_INTENT branch to the transformer with no
tests. A 40-line cyclomatic switch covering 8 kinds × 4 userRoles × isUser
combinations had zero coverage — that's how Hugo's playtest screenshots
snuck through (UUID-as-recipient, EU flag instead of ES, missing avatars).

33 fixture cases covering:
  - Every legacy entry type (DIRECT_SEND, SEND_LINK, REQUEST, BRIDGE_OFFRAMP,
    MANTECA_OFFRAMP, BRIDGE_ONRAMP, MANTECA_ONRAMP, DEPOSIT, MANTECA_QR_PAYMENT,
    PERK_REWARD, BANK_SEND_LINK_CLAIM)
  - Every TRANSACTION_INTENT kind × userRole that exists in the new switch
  - The default-arm guard so a future BE-added kind doesn't silently fall
    through to direction='send'
  - Reaper-failed rows: failReason='\${kind}_timeout' renders user-friendly
    copy instead of the kind's default name

Asserts direction, transactionCardType, userName, isLinkTransaction,
bankAccountDetailsDefined, and isPeerActuallyUser (proxied via the
isVerified output gate). 33/33 green.
…asking

Decomplexify added a TRANSACTION_INTENT switch to transactionTransformer
that was shaped much shallower than the legacy switches it replaced. Hugo's
playtest screenshots (a-g) were all instances of the same class — missing
userRole=RECIPIENT branches, missing kind cases, missing fullName plumbing,
missing visibility-gate updates downstream.

Transformer changes:
  - CRYPTO_DEPOSIT: new case. Mirrors legacy DEPOSIT but lifts the
    isPeerActuallyUser=false hardcode so a deposit from a Peanut user shows
    a clickable avatar (Hugo's screenshot f).
  - LINK_CREATE: full SENDER/RECIPIENT/BOTH branch logic mirroring legacy
    SEND_LINK. Resolves claimer username when the claimer is a Peanut user.
  - FIAT_OFFRAMP: userRole=RECIPIENT branch — multi-user fulfillment edge
    case where viewer received the offramp's USDC.
  - REQUEST_PAY: bridge-fulfillment subcase (direction='bank_request_fulfillment'
    when extraData.fulfillmentType==='bridge' and userRole=SENDER).
  - default arm: Sentry breadcrumb on unhandled kinds. A future BE-added
    kind no longer silently maps to 'send' — the warning fires within
    minutes of the kind appearing in production.
  - Reaper-failed branch: failReason='\${kind}_timeout' overrides userName
    to user-friendly copy ("Send didn't complete", etc.) so zombie rows
    don't pretend the action succeeded.

bankAccountDetails plumbing (the EU-vs-ES flag bug, screenshot d):
  - shouldPlumbBankAccountDetails() now extends the gate to TRANSACTION_INTENT
    kind=FIAT_OFFRAMP/CRYPTO_WITHDRAW. Previously the gate only fired for
    legacy BRIDGE_OFFRAMP/BANK_SEND_LINK_CLAIM, so intent-routed withdrawals
    silently dropped the IBAN row and getBankAccountCountryCode fell back
    to the EUR currency flag.
  - Also adds MANTECA_OFFRAMP — independent legacy bug, was never plumbed
    even pre-decomplexify.

Visibility gates in useReceiptViewModel:
  - depositInstructions: extended to TRANSACTION_INTENT/kind=ONRAMP.
  - mantecaDepositInfo: same extension.

New per-rail account masking (utils/account-mask.utils.ts):
  - IBAN, CLABE, CBU, CVU: '**** **** **** 0217' (last 4)
  - US ACH, GB: 'last-4-account-only' (routing stays plain — bank-public)
  - PIX, MANTECA_ALIAS: NOT masked. PIX keys are emails/phones/CPFs/UUIDs;
    masking would mangle meaning. Truncate at 32 chars if needed.
Wired into the bankAccountDetails row in TransactionDetailsReceipt — copy
icon still yields the FULL identifier (mask is for visual privacy, not
interaction).

Invite-friends desktop fix:
  - navigator.share is mobile-only; desktop fell through to clipboard.writeText
    with no toast (screenshot b — silent click). Added toast.info('Invite
    link copied!') matching the existing ShareButton pattern.
…eal-money

Without this, "wait, am I pointing at staging right now?" was answered by
reading 4 env vars across 2 repos. Now the dev banner has a high-contrast
pill (yellow=sandbox, red=real-money), and a styled banner logs to console
on every page load — visually impossible to miss.

utils/mode.ts: classifies the env constellation into 3 coherent presets:
  sandbox        = local API + arb-sepolia + harness-ecdsa
  staging-mirror = staging API + arb-sepolia
  prod-real      = prod API + arb-mainnet  (DANGER)
  custom         = anything else (tagged with components)

logRunMode() uses %c console styling — 22px bold yellow background for
sandbox, 22px bold red background for real-money. Same call backs the
Banner mount log + the new debug.mode() cheat.

Production builds skip both the pill and the log (gated on IS_PRODUCTION).
…, mode)

Three pain-point fixes from today's playtest:

(1) impersonate('hugostagqa') is now one-shot. Previously needed { pk: '0x...' }
    or the kernel didn't init. Default harness PK hardcoded (sandbox key,
    matches the local-clone wallet override). Resolution order changed:
    impersonate ALWAYS resets to opts.pk ?? DEFAULT — doesn't honor stale
    localStorage values that broke earlier sessions.

(2) Errors are friendly now:
      Old: "Error: username 'hugostagqasfsaasfafsa' not found"
      New: "Error: username 'hugostagqasfsaasfafsa' not found in app.users
              Did you mean: 'hugostagqa', 'hugodev', 'hugolocal', ...?
              (875 users in this DB)
              Tip: list available users with debug.listUsers()."
    BE 404s now return suggestions[] + totalUsers; mint-jwt 404/500s return
    a hint field. Network errors throw with "is the API running on $URL?"

(3) New commands:
      debug.listUsers(prefix?, limit=20)  — browse usernames
      debug.harnessSigner(pk?)            — re-arm signer w/o changing JWT
                                            (PK format validated)
      debug.mode()                        — log api/chain/signing in big
                                            yellow text (red if real money)

All gated by HARNESS_ENABLED + requireTestMode; refuse to run against prod.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 29, 2026

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

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview, Comment Apr 29, 2026 0:41am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 29, 2026

Walkthrough

Changes introduce run-mode detection utilities, bank account masking for receipt display, comprehensive transaction data mapping tests, and enhanced debug API commands. Modifications extend transaction onramp flow handling, refine transaction intent display logic, mask sensitive banking information, and add developer debugging capabilities including user impersonation, signer configuration, and run-mode introspection.

Changes

Cohort / File(s) Summary
Run-Mode Detection & Banner Integration
src/utils/mode.ts, src/components/Global/Banner/index.tsx
New mode.ts utility exports RunMode interface and functions (getRunMode(), isRealMoneyMode(), logRunMode()) to classify API tier, blockchain chain, and signing mode. Banner integrates run-mode detection with useEffect to log mode on mount and conditionally render a styled "mode" pill indicating real-money vs. sandbox status.
Bank Account Masking
src/utils/account-mask.utils.ts
New utility exports maskAccountIdentifier() function that masks account identifiers (IBAN, CLABE, US, PIX, MANTECA) by applying mode-specific transformations: last-4, last-4-account-only, truncate-32, or plain.
Transaction Receipt Display
src/components/TransactionDetails/TransactionDetailsReceipt.tsx
Updates receipt to display masked account identifiers via maskAccountIdentifier() instead of full IBANs, while preserving unmasked clipboard copy behavior. Adds toast notification when invite link is copied via desktop fallback path.
Transaction Data Mapping Logic
src/components/TransactionDetails/transactionTransformer.ts, src/components/TransactionDetails/useReceiptViewModel.ts
Expands bankAccountDetails eligibility with new shouldPlumbBankAccountDetails helper for FIAT_OFFRAMP, CRYPTO_WITHDRAW, and legacy MANTECA_OFFRAMP. Refines TRANSACTION_INTENT display mapping for P2P, link create, and crypto flows with role-aware direction/card-type logic. Adds Sentry warning for unknown intent kinds and timeout failure messaging. Broadens pending receipt conditions for onramp flows in useReceiptViewModel.
Transaction Mapping Test Suite
src/components/TransactionDetails/__tests__/transactionTransformer.test.ts
Adds comprehensive Jest test suite for mapTransactionDataForDrawer with fixtures, builders, and 402+ lines covering direct send/receive, link transactions, bridge flows, and extensive TRANSACTION_INTENT variants (P2P, QR pay, crypto withdraw/deposit, fiat on/off ramps, card spend, refund). Includes "known bug" regression cases and defensive unknown-intent handling assertions.
Debug API Enhancement
src/context/PeanutDebug.tsx
Extends debug context with enhanced error capture (try/catch, status/JSON/network logging) and new console commands: impersonate() (username/userId resolution and JWT minting), harnessSigner() (ECDSA signer configuration), mode() (run-mode logging), listUsers() (user listing and validation), and logout(). Updates debug.help() documentation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main changes: TRANSACTION_INTENT completeness, account masking, run-mode banner, and debug cheat improvements.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the four-PR bundle of post-cutover fixes with clear rationale, changes, and test plan.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Review rate limit: 3/5 reviews remaining, refill in 23 minutes and 5 seconds.

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

@github-actions
Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 5542.68 → 5670.99 (+128.31)
Findings: +7 net (+41 new, -34 resolved)

🆕 New findings (41)

  • critical complexity — src/components/TransactionDetails/transactionTransformer.ts — CC 175, MI 32.35, SLOC 539
  • critical method-complexity — src/components/TransactionDetails/transactionTransformer.ts:244 — mapTransactionDataForDrawer CC 159 SLOC 498
  • critical complexity — src/components/TransactionDetails/TransactionDetailsReceipt.tsx — CC 158, MI 53.11, SLOC 343
  • critical method-complexity — src/components/TransactionDetails/TransactionDetailsReceipt.tsx:64 — CC 111 SLOC 165
  • critical complexity — src/components/TransactionDetails/useReceiptViewModel.ts — CC 92, MI 62.17, SLOC 157
  • critical complexity — src/context/PeanutDebug.tsx — CC 52, MI 49.41, SLOC 341
  • high method-complexity — src/components/TransactionDetails/useReceiptViewModel.ts:136 — CC 43 SLOC 28
  • high hotspot — src/components/TransactionDetails/TransactionDetailsReceipt.tsx — 37 commits, +467/-1040 lines since 6 months ago
  • high complexity — src/utils/account-mask.utils.ts — CC 10, MI 48.45, SLOC 55
  • medium react-long-component — src/context/PeanutDebug.tsx:21 — PeanutDebug is 482 lines — split it
  • medium high-mdd — src/components/TransactionDetails/transactionTransformer.ts:244 — mapTransactionDataForDrawer: MDD 262.0 (uses across many lines from declarations)
  • medium high-mdd — src/components/TransactionDetails/TransactionDetailsReceipt.tsx:64 — TransactionDetailsReceipt: MDD 181.6 (uses across many lines from declarations)
  • medium high-mdd — src/context/PeanutDebug.tsx:21 — PeanutDebug: MDD 120.8 (uses across many lines from declarations)
  • medium high-mdd — src/context/PeanutDebug.tsx:22 — : MDD 120.8 (uses across many lines from declarations)
  • medium high-mdd — src/components/TransactionDetails/useReceiptViewModel.ts:76 — useReceiptViewModel: MDD 88.6 (uses across many lines from declarations)
  • medium high-dlt — src/components/TransactionDetails/TransactionDetailsReceipt.tsx:64 — TransactionDetailsReceipt: DLT 77 (calls 77 distinct functions — high context load)
  • medium high-dlt — src/context/PeanutDebug.tsx:21 — PeanutDebug: DLT 35 (calls 35 distinct functions — high context load)
  • medium high-dlt — src/context/PeanutDebug.tsx:22 — : DLT 34 (calls 34 distinct functions — high context load)
  • medium complexity — src/utils/mode.ts — CC 29, MI 60.11, SLOC 67
  • medium method-complexity — src/context/PeanutDebug.tsx:22 — CC 25 SLOC 257

…and 21 more.

✅ Resolved (34)

  • src/components/TransactionDetails/TransactionDetailsReceipt.tsx — CC 158, MI 53.14, SLOC 342
  • src/components/TransactionDetails/transactionTransformer.ts — CC 139, MI 28.57, SLOC 429
  • src/components/TransactionDetails/transactionTransformer.ts:194 — mapTransactionDataForDrawer CC 133 SLOC 419
  • src/components/TransactionDetails/TransactionDetailsReceipt.tsx:63 — CC 111 SLOC 165
  • src/components/TransactionDetails/useReceiptViewModel.ts — CC 88, MI 62.3, SLOC 157
  • src/context/PeanutDebug.tsx — CC 40, MI 51.68, SLOC 256
  • src/components/TransactionDetails/useReceiptViewModel.ts:136 — CC 39 SLOC 28
  • src/components/TransactionDetails/TransactionDetailsReceipt.tsx — 36 commits, +455/-1039 lines since 6 months ago
  • src/context/PeanutDebug.tsx:20 — PeanutDebug is 350 lines — split it
  • src/components/TransactionDetails/transactionTransformer.ts:194 — mapTransactionDataForDrawer: MDD 203.6 (uses across many lines from declarations)
  • src/components/TransactionDetails/TransactionDetailsReceipt.tsx:63 — TransactionDetailsReceipt: MDD 175.1 (uses across many lines from declarations)
  • src/context/PeanutDebug.tsx:20 — PeanutDebug: MDD 87.6 (uses across many lines from declarations)
  • src/context/PeanutDebug.tsx:21 — : MDD 87.6 (uses across many lines from declarations)
  • src/components/TransactionDetails/useReceiptViewModel.ts:76 — useReceiptViewModel: MDD 84.5 (uses across many lines from declarations)
  • src/components/TransactionDetails/TransactionDetailsReceipt.tsx:63 — TransactionDetailsReceipt: DLT 75 (calls 75 distinct functions — high context load)
  • src/context/PeanutDebug.tsx:21 — CC 16 SLOC 186
  • src/context/PeanutDebug.tsx — 11 any annotation(s)
  • src/context/PeanutDebug.tsx:21 — useEffect for async data fetching — use TanStack Query / server components
  • src/context/PeanutDebug.tsx:20 — PeanutDebug: DLT 27 (calls 27 distinct functions — high context load)
  • src/context/PeanutDebug.tsx:21 — : DLT 26 (calls 26 distinct functions — high context load)

…and 14 more.

📈 Painscore deltas (top movers)

File Before After Δ
src/utils/account-mask.utils.ts 0.0 8.2 +8.2
src/utils/mode.ts 0.0 6.4 +6.4
src/context/PeanutDebug.tsx 13.9 15.3 +1.4
src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx 10.0 11.4 +1.4
src/components/Global/Banner/index.tsx 5.2 6.5 +1.3
src/app/quests/page.tsx 9.3 10.6 +1.2
src/components/TransactionDetails/TransactionAvatarBadge.tsx 12.0 13.2 +1.2
src/components/Profile/components/ProfileMenuItem.tsx 8.5 9.6 +1.1
src/app/lp/card/CardLandingPage.tsx 15.8 17.0 +1.1
src/utils/passkeyPreflight.ts 16.4 17.5 +1.1
src/app/api/health/zerodev/route.ts 13.7 14.8 +1.1
src/components/IdentityVerification/StartVerificationModal.tsx 9.0 10.0 +0.9
src/app/[...recipient]/payment-layout-wrapper.tsx 8.1 9.0 +0.8
src/components/Card/CardGeoScreen.tsx 9.3 10.1 +0.8
src/components/Global/StatusPill/index.tsx 8.1 8.9 +0.7
src/components/Profile/AvatarWithBadge.tsx 9.4 10.1 +0.7
src/app/(mobile-ui)/dev/page.tsx 8.2 8.9 +0.7
src/utils/friendly-error.utils.tsx 10.8 11.5 +0.7
src/components/Card/CardDetailsScreen.tsx 5.7 6.4 +0.7
src/app/api/og/route.tsx 14.8 15.5 +0.7

@github-actions
Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 965 ran, 0 failed, 0 skipped, 16.1s

📊 Coverage (unit)

metric %
statements 44.5%
branches 24.7%
functions 23.3%
lines 44.3%
⏱ 10 slowest test cases
time test
0.4s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in updateUserById
0.4s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in updateUserById body
0.3s src/components/Request/__tests__/request-states.test.tsx › API failure shows error message and toast
0.2s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › SimpleFi WebSocket waiting shows processing indicator
0.1s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Manteca PIX form ready shows merchant card + amount input + pay button
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid 9-digit US account
0.1s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in createOnrampForGuest body
0.1s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Perk claim in progress shows disabled button + progress
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle too long for US account
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle invalid ETH address (too short)
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/utils/account-mask.utils.ts (1)

50-87: Minor naming inconsistency in truncate-32 mode.

The mode is named truncate-32 but the implementation truncates to 30 characters (29 + ellipsis). This is functionally fine — it's a display limit, not a hard constraint. Consider renaming to truncate-30 or adjusting to identifier.slice(0, 31) + '…' for 32-char output if the naming is meant to be precise.

If you want the name to match behavior:
 type MaskMode =
     /** "**** **** **** 0217" — keep last 4, format in groups of 4. IBAN/CLABE/CBU/CVU. */
     | 'last-4'
     /** Last 4 of account number; routing number stays plain. US ACH / GB sort code. */
     | 'last-4-account-only'
-    /** Truncate at 32 chars with ellipsis. PIX (email/phone/CPF/UUID — masking corrupts). */
-    | 'truncate-32'
+    /** Truncate at 30 chars with ellipsis. PIX (email/phone/CPF/UUID — masking corrupts). */
+    | 'truncate-30'
     /** Show as-is. Manteca aliases — short user-chosen strings. */
     | 'plain'

And update MASK_RULES accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/account-mask.utils.ts` around lines 50 - 87, The truncate-32 mode
in maskAccountIdentifier is misaligned with its name: it currently returns 29
chars + '…' (30 chars total). To make the behavior match 'truncate-32', change
the truncation in the 'truncate-32' case to take the first 31 characters and
append '…' (i.e., use identifier.slice(0, 31) + '…'), and ensure any related
MASK_RULES entries using 'truncate-32' remain correct; alternatively, if you
prefer the current 30-char behavior, rename the mode in MASK_RULES and usages to
'truncate-30' to keep names consistent.
🤖 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/utils/mode.ts`:
- Around line 95-105: The console banner in logRunMode() uses the boolean
realMoney to set tag (⚠ REAL MONEY MODE vs 🟢 SANDBOX MODE) which can disagree
with m.preset (e.g., staging-mirror or custom) and confuse readers; update the
logic so the tag is derived from m.preset (or a small helper that maps presets
to modes) instead of only realMoney, and then use that computed tag when logging
(ensure symbols like logRunMode, realMoney, tag, and m.preset are the points of
change) so the printed headline always aligns with the computed preset.
- Around line 65-67: The preset logic omits checking signing for the staging and
prod branches, so combinations like staging+arb-sepolia+harness-ecdsa are
incorrectly labeled; update the conditional expressions that set preset (the
lines using api, chain and assigning to preset) to also include signing ===
'harness-ecdsa' (i.e., require signing in the second and third branches just
like the first) so staging + arb-sepolia + harness-ecdsa yields 'staging-mirror'
and prod + arb-mainnet + harness-ecdsa yields 'prod-real'.

---

Nitpick comments:
In `@src/utils/account-mask.utils.ts`:
- Around line 50-87: The truncate-32 mode in maskAccountIdentifier is misaligned
with its name: it currently returns 29 chars + '…' (30 chars total). To make the
behavior match 'truncate-32', change the truncation in the 'truncate-32' case to
take the first 31 characters and append '…' (i.e., use identifier.slice(0, 31) +
'…'), and ensure any related MASK_RULES entries using 'truncate-32' remain
correct; alternatively, if you prefer the current 30-char behavior, rename the
mode in MASK_RULES and usages to 'truncate-30' to keep names consistent.
🪄 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: d9fb9246-7f43-4ecd-ae8e-140d30bd2c72

📥 Commits

Reviewing files that changed from the base of the PR and between 3c57e56 and b4c974c.

📒 Files selected for processing (8)
  • src/components/Global/Banner/index.tsx
  • src/components/TransactionDetails/TransactionDetailsReceipt.tsx
  • src/components/TransactionDetails/__tests__/transactionTransformer.test.ts
  • src/components/TransactionDetails/transactionTransformer.ts
  • src/components/TransactionDetails/useReceiptViewModel.ts
  • src/context/PeanutDebug.tsx
  • src/utils/account-mask.utils.ts
  • src/utils/mode.ts

Comment thread src/utils/mode.ts
Comment on lines +65 to +67
if (api === 'local' && chain === 'arb-sepolia' && signing === 'harness-ecdsa') preset = 'sandbox'
else if (api === 'staging' && chain === 'arb-sepolia') preset = 'staging-mirror'
else if (api === 'prod' && chain === 'arb-mainnet') preset = 'prod-real'
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.

⚠️ Potential issue | 🟠 Major

Include signing in the named preset checks.

Right now staging + arb-sepolia + harness-ecdsa is still labeled staging-mirror, and prod + arb-mainnet + harness-ecdsa is still labeled prod-real. That hides the passkey bypass state in the exact summary this helper is supposed to provide.

♻️ Proposed fix
-    if (api === 'local' && chain === 'arb-sepolia' && signing === 'harness-ecdsa') preset = 'sandbox'
-    else if (api === 'staging' && chain === 'arb-sepolia') preset = 'staging-mirror'
-    else if (api === 'prod' && chain === 'arb-mainnet') preset = 'prod-real'
+    if (api === 'local' && chain === 'arb-sepolia' && signing === 'harness-ecdsa') preset = 'sandbox'
+    else if (api === 'staging' && chain === 'arb-sepolia' && signing === 'passkey') preset = 'staging-mirror'
+    else if (api === 'prod' && chain === 'arb-mainnet' && signing === 'passkey') preset = 'prod-real'
     else preset = `custom (${api} · ${chain} · ${signing})`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/mode.ts` around lines 65 - 67, The preset logic omits checking
signing for the staging and prod branches, so combinations like
staging+arb-sepolia+harness-ecdsa are incorrectly labeled; update the
conditional expressions that set preset (the lines using api, chain and
assigning to preset) to also include signing === 'harness-ecdsa' (i.e., require
signing in the second and third branches just like the first) so staging +
arb-sepolia + harness-ecdsa yields 'staging-mirror' and prod + arb-mainnet +
harness-ecdsa yields 'prod-real'.

Comment thread src/utils/mode.ts
Comment on lines +95 to +105
const headlineStyle = realMoney
? 'background: #dc2626; color: #fff; font-size: 22px; font-weight: 900; padding: 10px 16px; border-radius: 4px; letter-spacing: 0.05em;'
: 'background: #facc15; color: #000; font-size: 22px; font-weight: 900; padding: 10px 16px; border-radius: 4px; letter-spacing: 0.05em;'

const detailStyle = 'font-size: 13px; font-weight: 600; line-height: 1.6em;'
const tag = realMoney ? '⚠ REAL MONEY MODE' : '🟢 SANDBOX MODE'

// eslint-disable-next-line no-console
console.log(
`${prefix ? prefix + ' ' : ''}%c${tag} · ${m.preset}%c\n` +
` api = ${m.api} (${m.apiUrl})\n` +
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.

⚠️ Potential issue | 🟡 Minor

Keep the console headline aligned with the computed preset.

logRunMode() prints 🟢 SANDBOX MODE for staging-mirror and custom too, so the first line can contradict m.preset. That makes the warning banner easier to misread.

♻️ Proposed fix
-    const tag = realMoney ? '⚠ REAL MONEY MODE' : '🟢 SANDBOX MODE'
+    const tag =
+        m.preset === 'sandbox'
+            ? '🟢 SANDBOX MODE'
+            : m.preset === 'staging-mirror'
+              ? '🟡 STAGING MIRROR'
+              : realMoney
+                ? '⚠ REAL MONEY MODE'
+                : '⚙ CUSTOM MODE'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/mode.ts` around lines 95 - 105, The console banner in logRunMode()
uses the boolean realMoney to set tag (⚠ REAL MONEY MODE vs 🟢 SANDBOX MODE)
which can disagree with m.preset (e.g., staging-mirror or custom) and confuse
readers; update the logic so the tag is derived from m.preset (or a small helper
that maps presets to modes) instead of only realMoney, and then use that
computed tag when logging (ensure symbols like logRunMode, realMoney, tag, and
m.preset are the points of change) so the printed headline always aligns with
the computed preset.

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.

1 participant