Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { render } from '@testing-library/react';
import { AccountTypeLabel } from './account-type-label';

describe('AccountTypeLabel', () => {
it('should return null when label is undefined', () => {
const { container } = render(<AccountTypeLabel label={undefined} />);
expect(container.firstChild).toBeNull();
});

it('should render Tag component when label is provided', () => {
const { container, getByText } = render(
<AccountTypeLabel label="Native SegWit" />,
);

expect(container.firstChild).not.toBeNull();
expect(getByText('Native SegWit')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

import { Tag } from '../../../../../components/component-library';

export const AccountTypeLabel = ({ label }: { label?: string }) => {
if (!label) {
return null;
}

return <Tag label={label} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AccountTypeLabel } from './account-type-label';
11 changes: 11 additions & 0 deletions ui/pages/confirmations/components/UI/asset/asset.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { fireEvent } from '@testing-library/react';
import { BtcAccountType } from '@metamask/keyring-api';
import createMockStore from 'redux-mock-store';

import { renderWithProvider } from '../../../../../../test/jest';
Expand Down Expand Up @@ -184,4 +185,14 @@ describe('NFTAsset', () => {
const image = getByAltText('Test NFT');
expect(image).toHaveAttribute('src', 'https://example.com/collection.png');
});

it('renders account type label when account type is provided', () => {
const assetWithAccountType = {
...mockTokenAsset,
accountType: BtcAccountType.P2wpkh,
};
const { getByText } = render(<Asset asset={assetWithAccountType} />);

expect(getByText('Native SegWit')).toBeInTheDocument();
});
});
22 changes: 19 additions & 3 deletions ui/pages/confirmations/components/UI/asset/asset.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { KeyringAccountType } from '@metamask/keyring-api';
import {
AvatarToken,
AvatarNetwork,
Expand All @@ -22,7 +23,9 @@ import {
NFT_STANDARDS,
} from '../../../types/send';
import { useNftImageUrl } from '../../../hooks/useNftImageUrl';
import { accountTypeLabel } from '../../../constants/network';
import { useFormatters } from '../../../../../hooks/useFormatters';
import { AccountTypeLabel } from '../account-type-label';

type AssetProps = {
asset: AssetType;
Expand Down Expand Up @@ -119,6 +122,8 @@ const TokenAsset = ({ asset, onClick, isSelected }: AssetProps) => {
const { formatCurrencyWithMinThreshold, formatTokenQuantity } =
useFormatters();

const typeLabel = accountTypeLabel[asset.accountType as KeyringAccountType];

return (
<Box
alignItems={AlignItems.center}
Expand Down Expand Up @@ -161,9 +166,20 @@ const TokenAsset = ({ asset, onClick, isSelected }: AssetProps) => {
flexDirection={FlexDirection.Column}
style={{ flex: 1, overflow: 'hidden' }}
>
<Text variant={TextVariant.bodyMdMedium} color={TextColor.textDefault}>
{name}
</Text>
<Box
display={Display.Flex}
flexDirection={FlexDirection.Row}
alignItems={AlignItems.center}
>
<Text
variant={TextVariant.bodyMdMedium}
color={TextColor.textDefault}
marginRight={1}
>
{name}
</Text>
<AccountTypeLabel label={typeLabel} />
</Box>
<Text
variant={TextVariant.bodySmMedium}
color={TextColor.textAlternative}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { BtcAccountType } from '@metamask/keyring-api';
import { fireEvent } from '@testing-library/react';
import { renderWithProvider } from '../../../../../../test/lib/render-helpers-navigate';
import configureStore from '../../../../../store/store';
Expand Down Expand Up @@ -138,4 +139,19 @@ describe('Recipient', () => {

expect(getByText('0x12345...45678')).toBeInTheDocument();
});

it('renders account type label when account type is provided', () => {
const { getByText } = render(
<Recipient
isAccount={true}
recipient={{
...mockAccountRecipient,
accountType: BtcAccountType.P2wpkh,
}}
onClick={jest.fn()}
/>,
);

expect(getByText('Native SegWit')).toBeInTheDocument();
});
});
24 changes: 19 additions & 5 deletions ui/pages/confirmations/components/UI/recipient/recipient.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import { AvatarAccountSize } from '@metamask/design-system-react';
import { KeyringAccountType } from '@metamask/keyring-api';

import { PreferredAvatar } from '../../../../../components/app/preferred-avatar';
import { Box, Text } from '../../../../../components/component-library';
import {
Expand All @@ -12,6 +14,8 @@ import {
} from '../../../../../helpers/constants/design-system';
import { type Recipient as RecipientType } from '../../../hooks/send/useRecipients';
import { shortenAddress } from '../../../../../helpers/utils/util';
import { accountTypeLabel } from '../../../constants/network';
import { AccountTypeLabel } from '../account-type-label';

export const Recipient = ({
isAccount,
Expand All @@ -28,6 +32,8 @@ export const Recipient = ({
const recipientName = isAccount
? recipient.accountGroupName
: recipient.contactName;
const typeLabel =
accountTypeLabel[recipient.accountType as KeyringAccountType];

return (
<Box
Expand All @@ -54,12 +60,20 @@ export const Recipient = ({
/>
<Box>
<Text variant={TextVariant.bodyMdMedium}>{recipientName}</Text>
<Text
variant={TextVariant.bodySmMedium}
color={TextColor.textAlternative}
<Box
display={Display.Flex}
flexDirection={FlexDirection.Row}
alignItems={AlignItems.center}
>
{shortenAddress(address)}
</Text>
<Text
variant={TextVariant.bodySmMedium}
color={TextColor.textAlternative}
marginRight={2}
>
{shortenAddress(address)}
</Text>
<AccountTypeLabel label={typeLabel} />
</Box>
</Box>
</Box>
);
Expand Down
10 changes: 10 additions & 0 deletions ui/pages/confirmations/constants/network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BtcAccountType, KeyringAccountType } from '@metamask/keyring-api';

// This map is used to display the account type label next to the token / account name
// Add more account type here to support labels in case we need them for other networks
export const accountTypeLabel: Partial<Record<KeyringAccountType, string>> = {
[BtcAccountType.P2pkh]: 'Legacy',
[BtcAccountType.P2sh]: 'Nested SegWit',
[BtcAccountType.P2wpkh]: 'Native SegWit',
[BtcAccountType.P2tr]: 'Taproot',
};
19 changes: 19 additions & 0 deletions ui/pages/confirmations/hooks/send/useAccountRecipients.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { BtcAccountType } from '@metamask/keyring-api';

import { cloneDeep } from 'lodash';
import { renderHookWithProvider } from '../../../../../test/lib/render-helpers';
import mockState from '../../../../../test/data/mock-state.json';
import { ConsolidatedWallets } from '../../../../selectors/multichain-accounts/account-tree.types';
Expand Down Expand Up @@ -141,6 +144,20 @@ describe('useAccountRecipients', () => {
isSolanaSendType: false,
isBitcoinSendType: true,
} as unknown as ReturnType<typeof useSendType>);
const accountsWithAccountType = cloneDeep(mockWalletsWithAccounts);
(
accountsWithAccountType.wallet1.groups.group1.accounts[0] as {
address: string;
type: BtcAccountType;
}
).type = BtcAccountType.P2wpkh;
(
accountsWithAccountType.wallet1.groups.group1.accounts[1] as {
address: string;
type: BtcAccountType;
}
).type = BtcAccountType.P2sh;
mockGetWalletsWithAccounts.mockReturnValue(accountsWithAccountType);
mockIsEVMAccountForSend.mockReturnValue(false);
mockIsSolanaAccountForSend.mockReturnValue(false);
mockIsBitcoinAccountForSend.mockReturnValue(true);
Expand All @@ -153,11 +170,13 @@ describe('useAccountRecipients', () => {
expect(result.current).toEqual([
{
accountGroupName: 'Account Group 1',
accountType: BtcAccountType.P2wpkh,
address: '0x1234567890abcdef1234567890abcdef12345678',
walletName: 'MetaMask Wallet',
},
{
accountGroupName: 'Account Group 1',
accountType: BtcAccountType.P2sh,
Copy link

Choose a reason for hiding this comment

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

Bug: Test Fails Due to Undefined Account Type

The 'returns Bitcoin account recipients...' test case expects the third recipient to omit the accountType property. However, the implementation always includes accountType: account.type, which is undefined for the third account, causing a test failure due to the mismatch.

Fix in Cursor Fix in Web

address: '0xabcdef1234567890abcdef1234567890abcdef12',
walletName: 'MetaMask Wallet',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const useAccountRecipients = (): Recipient[] => {
if (shouldInclude) {
recipients.push({
accountGroupName,
accountType: account.type,
address: account.address,
walletName,
});
Expand Down
2 changes: 2 additions & 0 deletions ui/pages/confirmations/hooks/send/useRecipients.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { KeyringAccountType } from '@metamask/keyring-api';
import { useContactRecipients } from './useContactRecipients';
import { useAccountRecipients } from './useAccountRecipients';

export type Recipient = {
accountGroupName?: string;
accountType?: KeyringAccountType;
address: string;
contactName?: string;
isContact?: boolean;
Expand Down
2 changes: 2 additions & 0 deletions ui/pages/confirmations/types/send.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { KeyringAccountType } from '@metamask/keyring-api';
import { Hex } from '@metamask/utils';

export enum AssetStandard {
Expand All @@ -12,6 +13,7 @@ export const NFT_STANDARDS = [AssetStandard.ERC721, AssetStandard.ERC1155];
export type Asset = {
accountAddress?: string;
accountId?: string;
accountType?: KeyringAccountType;
address?: string;
assetId?: string;
balance?: string | number | undefined;
Expand Down
Loading