Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: show localized snap name in snap tag #29049

Merged
merged 10 commits into from
Jan 9, 2025
2 changes: 2 additions & 0 deletions app/scripts/lib/accounts/BalancesController.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ControllerMessenger } from '@metamask/base-controller';
import { Balance, BtcAccountType, CaipAssetType } from '@metamask/keyring-api';
import { InternalAccount } from '@metamask/keyring-internal-api';
import { KeyringTypes } from '@metamask/keyring-controller';
import { createMockInternalAccount } from '../../../../test/jest/mocks';
import { MultichainNetworks } from '../../../../shared/constants/multichain/networks';
import {
Expand All @@ -25,6 +26,7 @@ const mockBtcAccount = createMockInternalAccount({
options: {
scope: MultichainNetworks.BITCOIN_TESTNET,
},
keyringType: KeyringTypes.snap,
});

const mockBalanceResult = {
Expand Down
2 changes: 1 addition & 1 deletion test/data/mock-send-state.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
}
}
},
"snaps": [{}],
"snaps": {},
"preferences": {
"hideZeroBalanceTokens": false,
"showFiatInTestnets": false,
Expand Down
35 changes: 34 additions & 1 deletion test/data/mock-state.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,39 @@
"version": "5.1.2"
}
]
},
"local:snap-id": {
"id": "local:snap-id",
"origin": "local:snap-id",
"version": "5.1.2",
"iconUrl": null,
"initialPermissions": {},
"manifest": {
"description": "mock snap description",
"proposedName": "mock snap name",
"repository": {
"type": "git",
"url": "https://127.0.0.1"
},
"source": {
"location": {
"npm": {
"filePath": "dist/bundle.js",
"packageName": "@metamask/test-snap-dialog",
"registry": "https://registry.npmjs.org"
}
},
"shasum": "L1k+dT9Q+y3KfIqzaH09MpDZVPS9ZowEh9w01ZMTWMU="
},
"version": "5.1.2"
},
"versionHistory": [
{
"date": 1680686075921,
"origin": "https://metamask.github.io",
"version": "5.1.2"
}
]
}
},
"preferences": {
Expand Down Expand Up @@ -541,7 +574,7 @@
},
"snap": {
"enabled": true,
"id": "snap-id",
"id": "local:snap-id",
"name": "snap-name"
}
},
Expand Down
8 changes: 6 additions & 2 deletions test/jest/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,11 @@ export function createMockInternalAccount({
type = EthAccountType.Eoa,
keyringType = KeyringTypes.hd,
lastSelected = 0,
snapOptions = undefined,
snapOptions = {
enabled: true,
id: 'npm:snap-id',
name: 'snap-name',
},
options = undefined,
}: {
name?: string;
Expand Down Expand Up @@ -236,7 +240,7 @@ export function createMockInternalAccount({
keyring: {
type: keyringType,
},
snap: snapOptions,
snap: keyringType === KeyringTypes.snap ? snapOptions : undefined,
lastSelected,
},
options: options ?? {},
Expand Down
22 changes: 14 additions & 8 deletions ui/components/multichain/account-list-item/account-list-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import classnames from 'classnames';

import { useSelector } from 'react-redux';
import { useI18nContext } from '../../../hooks/useI18nContext';
import { shortenAddress } from '../../../helpers/utils/util';
import { getSnapName, shortenAddress } from '../../../helpers/utils/util';

import { AccountListItemMenu } from '../account-list-item-menu';
import { AvatarGroup } from '../avatar-group';
Expand Down Expand Up @@ -53,6 +53,7 @@ import {
getIsTokenNetworkFilterEqualCurrentNetwork,
getShowFiatInTestnets,
getChainIdsToPoll,
getSnapsMetadata,
} from '../../../selectors';
import {
getMultichainIsTestnet,
Expand All @@ -73,6 +74,7 @@ import { normalizeSafeAddress } from '../../../../app/scripts/lib/multichain/add
import { useMultichainSelector } from '../../../hooks/useMultichainSelector';
import { useGetFormattedTokensPerChain } from '../../../hooks/useGetFormattedTokensPerChain';
import { useAccountTotalCrossChainFiatBalance } from '../../../hooks/useAccountTotalCrossChainFiatBalance';
import { getAccountLabel } from '../../../helpers/utils/accounts';
import { AccountListItemMenuTypes } from './account-list-item.types';

const MAXIMUM_CURRENCY_DECIMALS = 3;
Expand All @@ -99,6 +101,14 @@ const AccountListItem = ({
const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false);
const [accountListItemMenuElement, setAccountListItemMenuElement] =
useState();
const snapMetadata = useSelector(getSnapsMetadata);
const accountLabel = getAccountLabel(
account.metadata.keyring.type,
account,
account.metadata.keyring.type === KeyringType.snap
? getSnapName(snapMetadata)(account.metadata?.snap.id)
: null,
);

const useBlockie = useSelector(getUseBlockie);
const { isEvmNetwork } = useMultichainSelector(getMultichainNetwork, account);
Expand Down Expand Up @@ -402,9 +412,9 @@ const AccountListItem = ({
</Box>
)}
</Box>
{account.label ? (
{accountLabel ? (
<Tag
label={account.label}
label={accountLabel}
labelProps={{
variant: TextVariant.bodyXs,
color: Color.textAlternative,
Expand Down Expand Up @@ -446,7 +456,7 @@ const AccountListItem = ({
account={account}
onClose={() => setAccountOptionsMenuOpen(false)}
isOpen={accountOptionsMenuOpen}
isRemovable={account.keyring.type !== KeyringType.hdKeyTree}
isRemovable={account.metadata.keyring.type !== KeyringType.hdKeyTree}
closeMenu={closeMenu}
isPinned={isPinned}
isHidden={isHidden}
Expand Down Expand Up @@ -487,10 +497,6 @@ AccountListItem.propTypes = {
type: PropTypes.string.isRequired,
}).isRequired,
}).isRequired,
keyring: PropTypes.shape({
type: PropTypes.string.isRequired,
}).isRequired,
label: PropTypes.string,
}).isRequired,
/**
* Represents if this account is currently selected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const SNAP_ACCOUNT = {
},
snap: {
name: 'Test Snap Name',
id: 'snap-id',
id: 'npm:snap-id',
enabled: true,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ const mockAccount = {
'cf8dace4-9439-4bd4-b3a8-88c821c8fcb3'
],
balance: '0x152387ad22c3f0',
keyring: {
type: 'HD Key Tree',
},
};

const mockNonEvmAccount = {
Expand All @@ -31,6 +28,40 @@ const mockNonEvmAccount = {
type: 'bip122:p2wpkh',
};

const mockSnap = {
id: 'local:mock-snap',
origin: 'local:mock-snap',
version: '1.3.7',
iconUrl: null,
initialPermissions: {},
manifest: {
description: 'mock-description',
proposedName: 'mock-snap-name',
repository: {
type: 'git',
url: 'https://127.0.0.1',
},
source: {
location: {
npm: {
filePath: 'dist/bundle.js',
packageName: 'local:mock-snap',
},
},
shasum: 'L1k+dT9Q+y3KfIqzaH09MpDZVPS9ZowEh9w01ZMTWMU=',
locales: ['en'],
},
version: '1.3.7',
},
versionHistory: [
{
date: 1680686075921,
origin: 'https://metamask.github.io',
version: '1.3.7',
},
],
};

const DEFAULT_PROPS = {
account: mockAccount,
selected: false,
Expand Down Expand Up @@ -64,6 +95,10 @@ const render = (props = {}, state = {}) => {
conversionRate: '100000',
},
},
snaps: {
...mockState.metamask.snaps,
[mockSnap.id]: mockSnap,
},
},
activeTab: {
id: 113,
Expand Down Expand Up @@ -172,30 +207,25 @@ describe('AccountListItem', () => {
});

///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps)
it('renders the snap label for unnamed snap accounts', () => {
const { container } = render({
account: {
...mockAccount,
balance: '0x0',
keyring: 'Snap Keyring',
label: 'Snaps (Beta)',
},
});
const tag = container.querySelector('.mm-tag');
expect(tag.textContent).toBe('Snaps (Beta)');
});

it('renders the snap name for named snap accounts', () => {
const { container } = render({
account: {
...mockAccount,
metadata: {
...mockAccount.metadata,
snap: {
id: mockSnap.id,
},
keyring: {
type: 'Snap Keyring',
},
},

balance: '0x0',
keyring: 'Snap Keyring',
label: 'Test Snap Name (Beta)',
},
});
const tag = container.querySelector('.mm-tag');
expect(tag.textContent).toBe('Test Snap Name (Beta)');
expect(tag.textContent).toBe(`${mockSnap.manifest.proposedName} (Beta)`);
});
///: END:ONLY_INCLUDE_IF

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,9 @@ describe('AccountListMenu', () => {
keyring: {
type: 'Snap Keyring',
},
snap: {
id: 'local:snap-id',
},
},
},
},
Expand All @@ -491,7 +494,7 @@ describe('AccountListMenu', () => {
'.multichain-account-list-item',
);
const tag = listItems[0].querySelector('.mm-tag') as Element;
expect(tag.textContent).toBe('Snaps (Beta)');
expect(tag.textContent).toBe('mock snap name (Beta)');
});

it('displays the correct label for named snap accounts', () => {
Expand All @@ -511,7 +514,7 @@ describe('AccountListMenu', () => {
},
snap: {
name: 'Test Snap Name',
id: 'test-snap-id',
id: 'local:snap-id',
},
},
},
Expand All @@ -524,7 +527,7 @@ describe('AccountListMenu', () => {
'.multichain-account-list-item',
);
const tag = listItems[0].querySelector('.mm-tag') as Element;
expect(tag.textContent).toBe('Test Snap Name (Beta)');
expect(tag.textContent).toBe('mock snap name (Beta)');
});
///: END:ONLY_INCLUDE_IF

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
///: END:ONLY_INCLUDE_IF
} from '@metamask/keyring-api';
///: BEGIN:ONLY_INCLUDE_IF(build-flask)
import { InternalAccount } from '@metamask/keyring-internal-api';
import {
BITCOIN_WALLET_NAME,
BITCOIN_WALLET_SNAP_ID,
Expand Down Expand Up @@ -96,7 +95,6 @@ import {
// eslint-disable-next-line import/no-restricted-paths
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
import { getAccountLabel } from '../../../helpers/utils/accounts';
///: BEGIN:ONLY_INCLUDE_IF(build-flask)
import {
ACCOUNT_WATCHER_NAME,
Expand Down Expand Up @@ -185,36 +183,6 @@ export const getActionTitle = (
}
};

/**
* Merges ordered accounts with balances with each corresponding account data from internal accounts
*
* @param accountsWithBalances - ordered accounts with balances
* @param internalAccounts - internal accounts
* @returns merged accounts list with balances and internal account data
*/
export const mergeAccounts = (
accountsWithBalances: MergedInternalAccount[],
internalAccounts: InternalAccount[],
) => {
return accountsWithBalances.map((account) => {
const internalAccount = internalAccounts.find(
(intAccount) => intAccount.address === account.address,
);
if (internalAccount) {
return {
...account,
...internalAccount,
keyring: internalAccount.metadata.keyring,
label: getAccountLabel(
internalAccount.metadata.keyring.type,
internalAccount,
),
};
}
return account;
});
};

type AccountListMenuProps = {
onClose: () => void;
privacyMode?: boolean;
Expand Down Expand Up @@ -345,7 +313,6 @@ export const AccountListMenu = ({
fuse.setCollection(filteredAccounts);
searchResults = fuse.search(searchQuery);
}
searchResults = mergeAccounts(searchResults, filteredAccounts);

const title = useMemo(
() => getActionTitle(t as (text: string) => string, actionMode),
Expand Down
Loading
Loading