Skip to content

feat: [MUSD-816] show transfers in money account activity#30537

Open
Jwhiles wants to merge 3 commits into
mainfrom
MUSD-816
Open

feat: [MUSD-816] show transfers in money account activity#30537
Jwhiles wants to merge 3 commits into
mainfrom
MUSD-816

Conversation

@Jwhiles
Copy link
Copy Markdown
Contributor

@Jwhiles Jwhiles commented May 21, 2026

Description

This PR updates the money activity list to show transfers into the money account as well as deposits.

Changelog

CHANGELOG entry: show transfers in the money account account activity list

Related issues

Fixes: MUSD-816

Manual testing steps

Feature: money activity list

  Scenario: user transfers from their primary account to their money account address
    Given the the transfer is in MUSD and on Monad

    When user checks the activity list
    Then they see a single received item corresponding to the transfer

  Scenario: user receives a transfer from an unknown account to their money account address
    Given the the transfer is in MUSD and on Monad

    When user checks the activity list
    Then they see a single received item corresponding to the transfer

Screenshots/Recordings

Before

image image

After

image image image

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Medium Risk
Changes which transactions appear in Money activity and how mUSD amounts/fiat are computed; scoped to Monad and covered by broad tests, but incorrect filtering or peg logic could mislead users about balances.

Overview
Money Account activity now surfaces inbound mUSD on Monad—both polled incoming transfers to the Money address and locally signed tokenMethodTransfer / tokenMethodTransferFrom when calldata’s recipient matches—while excluding the same token on Mainnet/Linea/BSC and non–Money-account recipients. List rows use a “Received” label/icon (vs “Deposited” for moneyAccountDeposit), and the details sheet uses a dedicated MoneyReceivedDetails view (fiat hero, From, token received) for those types.

Classification & amounts: New helpers (isMusdTokenOnChain, isMusdOnMoneyAccountChain, isMusdErc20Transfer) scope mUSD to Money Account chains; resolveMusdTransferMeta fills amounts from ERC-20 calldata via BigInt when transferInformation is missing. Fiat lines always use the 1:1 USD peg for mUSD, ignoring erroneous market prices. Phantom rows are suppressed by only showing confirmed / submitted / failed statuses for the new inbound paths.

Reviewed by Cursor Bugbot for commit 7e966e7. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions
Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@github-actions github-actions Bot added pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. size-M labels May 21, 2026
@Jwhiles Jwhiles force-pushed the MUSD-816 branch 2 times, most recently from 9f4fafc to 70099e0 Compare May 26, 2026 15:03
@github-actions github-actions Bot added size-L and removed size-M labels May 26, 2026
@Jwhiles Jwhiles changed the title wip feat: [MUSD-816] show transfers in money account activity May 26, 2026
@Jwhiles Jwhiles added team-earn and removed pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. labels May 26, 2026
…ision

Skip mid-compose (unapproved/approved/signed) and aborted
(rejected/dropped/cancelled) rows in the new mUSD activity branches so a
cancelled send to the money account no longer renders as a phantom
"Received". Pass isRounding=false to fromTokenMinimalUnit so the manual
BigInt calldata decode isn't undone by the default Number() cast.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added size-XL and removed size-L labels May 26, 2026
@Jwhiles Jwhiles marked this pull request as ready for review May 26, 2026 19:09
@Jwhiles Jwhiles requested a review from a team as a code owner May 26, 2026 19:09
if (isMusdLike) {
const rateEntry = resolveCurrencyRateEntry(currencyRates, ETH_TICKER);
if (rateEntry !== undefined && rateEntry.usdConversionRate !== 0) {
const tokenToEthPricePeg = 1 / rateEntry.usdConversionRate;
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.

Null usdConversionRate passes guard, causes Infinity

Medium Severity

The guard rateEntry.usdConversionRate !== 0 does not catch null, which is a valid value in CurrencyRateState. When usdConversionRate is null, 1 / null evaluates to Infinity, producing tokenToEthPricePeg = Infinity. This is then passed to balanceToFiatNumber, which would yield an infinite fiat value displayed to the user. Previously this code was in a fallback branch (only hit when market data was missing), but the reordering makes it the primary path for all mUSD transactions, significantly increasing the likelihood of hitting this edge case in production.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e6d58c3. Configure here.

@Jwhiles Jwhiles requested a review from Matt561 May 26, 2026 20:06
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeMoney
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: medium
  • AI Confidence: 85%
click to see 🤖 AI reasoning details

E2E Test Selection:
All 18 changed files are scoped to the Money/Card feature area and mUSD token constants:

  1. musd.ts (Earn constants): Added isMusdTokenOnChain, isMusdOnMoneyAccountChain, and MUSD_MONEY_ACCOUNT_CHAIN_IDS - new chain-aware mUSD validation functions used by Money activity filtering.

  2. moneyActivityFilters.ts: Added isMusdErc20Transfer function and updated isMoneyActivityDeposit to classify mUSD ERC-20 transfers as deposits - this changes which transactions appear in Money activity.

  3. activityStyles.ts: Added resolveMusdTransferMeta and related helpers for resolving mUSD token metadata from transaction calldata.

  4. useMoneyAccountTransactions.ts: Extended transaction filtering logic to include inbound mUSD transfers (incoming polling) and locally-signed mUSD ERC-20 transfers to the Money account address.

  5. MoneyTransactionDetailsSheet.tsx: Added conditional rendering - shows new MoneyReceivedDetails component for incoming/transfer transaction types instead of generic TransactionDetails.

  6. MoneyReceivedDetails.tsx (new file): New component displaying received transaction details with fiat amount hero, status, date, from address, and token received rows.

  7. moneyActivityFiat.ts: New utility for building fiat display lines for Money activity rows.

  8. useMoneyTransactionDisplayInfo.ts: Updated display info hook for Money transactions.

  9. locales/languages/en.json: Added money_account_received, from, and token_received locale strings.

Risk factors:

  • Changes to transaction filtering logic (useMoneyAccountTransactions) could affect which transactions appear in Money activity
  • New MoneyReceivedDetails component is a new UI path in MoneyTransactionDetailsSheet
  • mUSD chain validation changes could affect Earn/mUSD flows

Tag selection rationale:

  • SmokeMoney is the primary tag covering Card and Ramps flows, which exercise the Money UI including transaction details sheets and activity views
  • No changes to SmokeConfirmations flows (no changes to confirmation screens themselves)
  • No changes to SmokeStake, SmokeSwap, SmokeWalletPlatform, or other feature areas
  • The Earn/musd.ts changes are additive (new exports only) and don't modify existing mUSD behavior for Earn flows, so SmokeStake is not required

Performance tests: No performance impact expected - changes are UI display logic and transaction filtering within the Money feature, not affecting rendering performance of account lists, login, or other performance-sensitive flows.

Performance Test Selection:
Changes are scoped to Money feature UI components and transaction filtering logic. No changes to performance-sensitive areas like account list rendering, app startup, login flows, or asset loading. The new MoneyReceivedDetails component and updated transaction filtering are not in performance-critical paths measured by existing performance tests.

View GitHub Actions results

Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

There are 4 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7e966e7. Configure here.

@@ -0,0 +1,96 @@
import React from 'react';
import { ScrollView } from 'react-native';
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.

ScrollView from react-native inside BottomSheet breaks scrolling

Medium Severity

ScrollView is imported from react-native in MoneyReceivedDetails, but this component is rendered inside a BottomSheet (in MoneyTransactionDetailsSheet). The gesture-handler version is required for scroll/gesture coordination inside bottom sheets — without it, scroll gestures conflict with the sheet's pan gesture, causing broken scrolling or accidental sheet dismissal. The import needs to come from react-native-gesture-handler instead.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by learned rule: ScrollView inside BottomSheet must be imported from react-native-gesture-handler

Reviewed by Cursor Bugbot for commit 7e966e7. Configure here.

// `0x` + 8 hex chars selector + 64 hex chars (address) + 64 hex chars (uint256).
const ERC20_TRANSFER_CALLDATA_LENGTH = 138;
// `0x` + 8 hex chars selector + 3 × 64 hex chars (from, to, uint256).
const ERC20_TRANSFER_FROM_CALLDATA_LENGTH = 202;
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.

Duplicate ERC20 calldata constants across two files

Low Severity

ERC20_TRANSFER_CALLDATA_LENGTH and ERC20_TRANSFER_FROM_CALLDATA_LENGTH are defined identically in both useMoneyAccountTransactions.ts and activityStyles.ts. Duplicating these magic-number constants increases maintenance burden — if the value changes in one file, the other risks becoming silently out of sync. These could be defined once and shared.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7e966e7. Configure here.


it('renders the fiat hero when buildMoneyActivityFiatLine returns a value', () => {
const { queryByTestId } = render();
expect(queryByTestId('money-received-hero')).toBeTruthy();
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.

Tests use toBeTruthy instead of toBeOnTheScreen

Low Severity

Several new test assertions use toBeTruthy() to verify element presence (e.g., expect(getByText('Token received')).toBeTruthy() and expect(getByTestId('money-received-details')).toBeTruthy()). The unit testing guidelines mandate toBeOnTheScreen() for element presence checks — toBeTruthy() is listed as a banned weak matcher for this purpose.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by project rule: Unit Testing Guidelines

Reviewed by Cursor Bugbot for commit 7e966e7. Configure here.

@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant