Skip to content

Conversation

@nickewansmith
Copy link
Contributor

@nickewansmith nickewansmith commented Jan 8, 2026

Description

  1. What is the reason for the change?
    To enable mUSD (MetaMask USD stablecoin) deposits in the Earn feature, users need to see a confirmation screen when depositing mUSD to earn yield via Aave. This requires:
    New lending deposit confirmation UI components
    Transaction lifecycle tracking for lending transactions
    Token snapshot fetching for receipt tokens (aTokens)
    Integration with the redesigned confirmations flow

  2. What is the improvement/solution?
    New Lending Deposit Confirmation UI
    lending-deposit-info/ - New confirmation info components:
    lending-deposit-info.tsx - Main container with metrics tracking
    lending-hero.tsx - Token avatar and deposit amount display
    lending-details.tsx - APR, estimated rewards, withdrawal time, protocol info
    lending-receive-section.tsx - Receipt token (aToken) preview
    useLendingDepositDetails.ts - Hook to extract/calculate deposit details from transaction metadata

Transaction Lifecycle Tracking
useEarnLendingTransactionStatus.ts - Hook that subscribes to transaction events (submitted, confirmed, rejected, dropped, failed) and:
Automatically adds receipt tokens to wallet on confirmation
Pre-fetches token data on submission

Token Utilities
lending-transaction.ts - Utilities for decoding Aave supply/withdraw transaction data
token-snapshot.ts - Utilities for fetching and caching token metadata from TokenSearchDiscoveryDataController
Added LendingDepositInfo to info-root.tsx for confirmations routing
Added tooltipIconName prop to InfoRow for custom tooltip icons
Updated EarnInputView and EarnTransactionMonitor for lending flow support

Changelog

CHANGELOG entry: Added Earn 1 click deposit flow and mUSD support

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-94

Manual testing steps

To see mUSD flow you mus add DEV env to EarnController constructor and stakeSdkProvider

Feature: Earn mUSD Deposit Confirmation

  Scenario: User views lending deposit confirmation
    Given user initiates a mUSD deposit to Aave
    When the confirmation screen loads
    Then user sees deposit amount and token
    And user sees APR and estimated annual rewards
    And user sees receipt token they will receive

  Scenario: Lending transaction is confirmed
    Given user submits a lending deposit transaction
    When the transaction is confirmed on-chain
    Then the receipt token is added to wallet
    And analytics events are tracked

  Scenario: Token metadata is fetched
    Given user does not have the receipt token
    When deposit confirmation loads
    Then token metadata is fetched from discovery controller

Screenshots/Recordings

Before

After

Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-01-07.at.20.59.57.mp4

Pre-merge author checklist

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

Introduces lending deposit confirmation and end-to-end tx monitoring for Earn, plus navigation and utility updates.

  • New confirmation UI: lending-deposit-info (hero, details, receive sections) with useLendingDepositDetails; wired in info-root for both direct and batch lendingDeposit txs
  • Global tx monitoring: useEarnLendingTransactionStatus + EarnTransactionMonitor subscribe to lifecycle events, track analytics, prefetch token snapshots on submit, and auto-add receipt/underlying tokens on confirm
  • Flow integration: EarnInputView uses useConfirmNavigation to navigate to redesigned confirmations with a loader before adding the tx batch
  • Utils: add lending-transaction (decode Aave supply/withdraw, event props) and token-snapshot (fetch/read token metadata); export via utils/index; useEarnToken now uses fetchTokenSnapshot
  • UI infra: InfoRow accepts tooltipIconName
  • Tests: comprehensive unit tests for new hooks/components; withdrawal confirmation tests simplified (token add handled by monitor); minor locale additions

Written by Cursor Bugbot for commit e32d999. This will update automatically on new commits. Configure here.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2026

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.

@nickewansmith nickewansmith force-pushed the MUSD-94-as-a-user-i-want-to-be-able-to-earn-yield-on-my-m-usd-in-mm branch from 85d9656 to b992065 Compare January 8, 2026 02:02
@nickewansmith nickewansmith marked this pull request as ready for review January 8, 2026 03:02
@nickewansmith nickewansmith requested review from a team as code owners January 8, 2026 03:02
const createEventBuilderRef = useRef(createEventBuilder);

trackEventRef.current = trackEvent;
createEventBuilderRef.current = createEventBuilder;
Copy link

Choose a reason for hiding this comment

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

Stale closure captures token lookup functions

Medium Severity

The getEarnToken and getOutputToken functions from useEarnTokens() are captured in the useEffect closure at mount time (line 39), but the effect has an empty dependency array (line 460). While trackEvent and createEventBuilder are correctly stored in refs to avoid stale closures (lines 43-48), this same pattern isn't applied to the token lookup functions. If the underlying earn tokens data changes after mount, the event handlers will use stale function references that may return incorrect or missing token data, causing analytics to have wrong values or token addition to fail on transaction confirmation.

Additional Locations (1)

Fix in Cursor Fix in Web


navigation.navigate('StakeScreens', {
screen: Routes.FULL_SCREEN_CONFIRMATIONS.REDESIGNED_CONFIRMATIONS,
});
Copy link

Choose a reason for hiding this comment

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

Unawaited async call after navigation

Medium Severity

The addTransactionBatch function is called without await after navigating to the confirmation screen. Since addTransactionBatch is an async function that returns a Promise, any errors from the transaction batch creation will be unhandled. If the batch fails to be added (validation error, network issue), the user will already be on the confirmation screen with no transaction to confirm. Other uses of addTransactionBatch in the codebase (e.g., PredictController.ts) properly await the result.

Fix in Cursor Fix in Web

outputToken = getOutputToken({
chainId,
address: tokenPair.outputToken as Hex,
} as TokenI);
Copy link

Choose a reason for hiding this comment

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

Missing null check causes crash on undefined address

High Severity

When getEarnTokenPairAddressesFromState cannot find a matching market, it returns { earnToken: undefined, outputToken: undefined }. These undefined values are then passed to getEarnToken and getOutputToken (cast as Hex), which internally call token.address.toLowerCase(). This throws a TypeError: Cannot read properties of undefined (reading 'toLowerCase'), crashing the transaction event handler. This could occur when processing lending transactions for tokens not yet in the EarnController's markets list.

Fix in Cursor Fix in Web

| TransactionType.lendingWithdraw,
// @ts-expect-error TODO: fix this type mismatch
data: lendingTx.params?.data as string,
};
Copy link

Choose a reason for hiding this comment

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

Type Assertions Suppress TypeScript Errors for Potentially Mismatched Transaction Batch Structure

Medium Severity

The code uses @ts-expect-error comments to suppress TypeScript errors when accessing lendingTx.params.data from transactionBatchesMetadata.transactions. This indicates that the actual type of TransactionBatchTransaction from the TransactionBatchMeta type doesn't match the expected structure being accessed.

If the runtime data structure differs from what's expected (e.g., if params property doesn't exist on actual transaction batch transactions, or data is not a string), the code will either fail at runtime or produce incorrect results. The type suppression masks what could be a real incompatibility between the code's assumptions and the actual data structure provided by @metamask/transaction-controller.

Fix in Cursor Fix in Web

- Add tests for getEarnTokenPairAddressesFromState in token-snapshot
- Add deduplication and edge case tests for useEarnLendingTransactionStatus
- Add null approval request test for info-root
- Update EarnLendingWithdrawalConfirmationView tests (removed obsolete tests)
- Achieve 100% coverage for token-snapshot.ts and lending-receive-section.tsx
@github-actions
Copy link
Contributor

github-actions bot commented Jan 9, 2026

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeStake, SmokeConfirmationsRedesigned, SmokeTrade
  • Risk Level: medium
  • AI Confidence: 80%
click to see 🤖 AI reasoning details

This PR introduces a new lending deposit confirmation UI for the Earn feature. The changes include:

  1. New Lending Deposit Confirmation Components: A complete set of new components for displaying lending deposit confirmation info (hero, details, receive section) under app/components/Views/confirmations/components/info/lending-deposit-info/.

  2. Earn Transaction Monitoring: New hooks and utilities for monitoring lending transaction lifecycle (useEarnLendingTransactionStatus.ts, lending-transaction.ts, token-snapshot.ts).

  3. Confirmation Flow Integration: Updates to info-root.tsx to route lending deposit transactions to the new LendingDepositInfo component, and updates to EarnInputView.tsx to navigate to confirmation with a loader.

  4. Minor UI Updates: Added tooltipIconName prop to info-row.tsx component.

The changes are focused on:

  • Staking/Earn features (SmokeStake) - Core lending deposit functionality
  • Confirmations redesigned (SmokeConfirmationsRedesigned) - New confirmation info component integrated into the redesigned confirmations flow
  • Trade functionality (SmokeTrade) - The existing stake test (stake-action-smoke.spec.ts) uses SmokeTrade tag, and this PR extends similar functionality for lending

The risk is medium because:

  • These are new UI components that don't modify existing critical paths
  • The changes are well-scoped to the Earn/Lending feature
  • Unit tests are included for the new components
  • No changes to core Engine or Controllers

View GitHub Actions results

@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 9, 2026

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.

3 participants