Skip to content

refactor: migrate multichain account components to DS#30249

Open
gantunesr wants to merge 4 commits into
mainfrom
gar/refactor/mul-1693
Open

refactor: migrate multichain account components to DS#30249
gantunesr wants to merge 4 commits into
mainfrom
gar/refactor/mul-1693

Conversation

@gantunesr
Copy link
Copy Markdown
Member

@gantunesr gantunesr commented May 15, 2026

Description

Migrates the MultichainAccounts temporary component internals away from deprecated component-library imports and onto @metamask/design-system-react-native equivalents.

This updates account rows, external account rows, account selector list pieces, address rows, checkboxes, search fields, text, icons, sensitive text, and avatar usage. It also adds a small avatar variant compatibility helper so legacy persisted selector values such as Maskicon, JazzIcon, and Blockies continue to map to the DS AvatarAccountVariant API.

Changelog

CHANGELOG entry: null

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1693

Manual testing steps

Feature: Multichain account component DS migration

  Scenario: account selector and address rows preserve existing behavior
    Given a wallet with multichain account groups and network addresses

    When the account selector and multichain address list are opened
    Then account rows, external account rows, network avatars, checkboxes, copy actions, and search fields render and behave as before

Screenshots/Recordings

Screen.Recording.2026-05-15.at.4.13.43.PM.mov

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
Medium risk because it swaps core UI primitives (avatars, text, search, checkbox, toast) used across multichain account selection/address flows, which could introduce visual or interaction regressions despite largely being API-level refactors.

Overview
Migrates the temporary MultichainAccounts UI components off deprecated component-library primitives and onto @metamask/design-system-react-native equivalents (e.g., AvatarAccount/AvatarNetwork, Text/SensitiveText, Icon, Checkbox, and TextFieldSearch).

Adds avatarAccountVariant compatibility helpers so persisted legacy avatar type strings (Maskicon/JazzIcon/Blockies) map cleanly to DS AvatarAccountVariant, and updates affected components/tests to use the new variant API and updated test IDs.

Refactors MultichainAddressRow to use DS toast/button/icon/network avatar APIs and adjusts tests to properly handle async copy feedback and timers.

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

@github-actions github-actions Bot added the pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. label May 15, 2026
@metamaskbotv2 metamaskbotv2 Bot added the team-accounts-framework Accounts team label May 15, 2026
@gantunesr gantunesr marked this pull request as ready for review May 15, 2026 20:01
@gantunesr gantunesr requested a review from a team as a code owner May 15, 2026 20:01
@gantunesr gantunesr removed the pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. label May 15, 2026
@gantunesr gantunesr added the no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed label May 20, 2026
closeButtonOptions: {
variant: ButtonIconVariant.Icon,
iconName: ToastIconName.Close,
variant: 'Icon',
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.

I see some ButtonIconVariant in the DS package, but none of them matches 'Icon', should we use ButtonIconVariant.Default instead?

Copy link
Copy Markdown
Member Author

@gantunesr gantunesr May 20, 2026

Choose a reason for hiding this comment

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

I don't think so because the interface expects the value Icon and ButtonIconVariant.Default is set to default. @MetaMask/design-system can you double check this?

@ccharly lets wait for the team to chime in and lets not block the PR

(typeof AvatarAccountType)[keyof typeof AvatarAccountType];

export const getAvatarAccountVariant = (
avatarAccountType: AccountAvatarVariant,
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.

Should this also use LegacyAvatarAccountType?

Suggested change
avatarAccountType: AccountAvatarVariant,
avatarAccountType: AccountAvatarVariant | LegacyAvatarAccountType,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

AccountAvatarVariant already takes into account the legacy type:

export type AccountAvatarVariant =
  | AvatarAccountVariant
  | LegacyAvatarAccountType;

Comment on lines +229 to +232

act(() => {
jest.advanceTimersByTime(400);
});
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.

Do we need this part? Is it to avoid an in-flight promise based on time (maybe animation)?

If yes, we could add a comment explaining that!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

ok, done in 168d775

interface AccountCellProps {
accountGroup: AccountGroupObject;
avatarAccountType: AvatarAccountType;
avatarAccountType: AccountAvatarVariant;
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.

Nit: IDK if we want to align naming here too? Might not really be part of the DS migration initiative (I couldn't find a AvatarAccountType on the DS package, so "variant" seems to be the only term we use for this now)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

What are you suggesting specifically? Change the type name or the prop name?

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts, SmokeWalletPlatform, SmokeIdentity, SmokeConfirmations, SmokeNetworkExpansion, SmokeNetworkAbstractions, SmokeSwap
  • Selected Performance tags: @PerformanceAccountList
  • Risk Level: medium
  • AI Confidence: 82%
click to see 🤖 AI reasoning details

E2E Test Selection:

The PR migrates MultichainAccounts component library components from the legacy internal design system to @metamask/design-system-react-native. Key changes include:

  1. AccountCell.tsx: Migrates AvatarAccount, Text, SensitiveText, Icon, Avatar components. Updates prop names (type→variant, accountAddress→address, imageSource→src, TextColor.Default→TextColor.TextDefault, etc.)

  2. MultichainAccountSelectorList.tsx: Migrates Text, TextFieldSearch. Importantly, the testID for TextFieldSearch search input is now nested inside inputProps object instead of being a direct prop - this could break E2E tests that query by this testID.

  3. AccountListCell.tsx: Migrates Checkbox component. Props changed: isChecked→isSelected, onPress→onChange. This could affect E2E tests that interact with checkboxes in multi-account selection flows.

  4. ExternalAccountCell.tsx: Migrates AvatarAccount, Avatar, Text components.

  5. MultichainAddressRow.tsx: Migrates Avatar to AvatarNetwork, removes deprecated ToastRef dependency.

  6. avatarAccountVariant.ts (new): Adapter between legacy AvatarAccountType and new AvatarAccountVariant.

These components are used across critical flows:

  • AccountSelector (used in account switching, dApp connections, confirmations) → SmokeAccounts, SmokeWalletPlatform, SmokeIdentity
  • MultichainAccountConnect (dApp connection flows) → SmokeNetworkAbstractions, SmokeNetworkExpansion
  • Bridge RecipientSelectorModal → SmokeSwap
  • Confirmations AccountSelector → SmokeConfirmations
  • MultichainAddressRow → WalletDetails, AddressList, PrivateKeyList → SmokeAccounts, SmokeWalletPlatform

The risk is medium because while the changes are UI-only (no business logic changes), the prop API changes could cause rendering failures or break E2E test selectors. The testID placement change in TextFieldSearch is particularly notable.

SmokeSwap is included because Bridge RecipientSelectorModal directly uses MultichainAccountSelectorList.
SmokeConfirmations is included because the confirmations AccountSelector uses MultichainAccountSelectorList.
SmokeNetworkAbstractions and SmokeNetworkExpansion are included because MultichainAccountConnect (dApp connection flows) uses these components.
SmokeIdentity is included per SmokeAccounts tag description (multi-SRP architecture changes).

Performance Test Selection:
The MultichainAccountSelectorList uses FlashList for rendering account lists. The migration to new design system components (AvatarAccount, Text, Checkbox) could affect rendering performance of the account list. The @PerformanceAccountList tag covers account selector and multi-account scenarios which directly exercise these changed components.

View GitHub Actions results

@sonarqubecloud
Copy link
Copy Markdown

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

Labels

no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed size-M team-accounts-framework Accounts team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants