1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

Fix details when transferring NFT not added to wallet (#19045)

This commit is contained in:
Jyoti Puri 2023-06-02 18:33:10 +05:30 committed by GitHub
parent 37af04374a
commit f1de905be7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 173 additions and 20 deletions

View File

@ -50,7 +50,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
// Confirm transfer
await driver.waitForSelector({
css: '.confirm-page-container-summary__title',
css: '.mm-text--heading-md',
text: 'TestDappCollectibles',
});
await driver.clickElement({ text: 'Confirm', tag: 'button' });

View File

@ -282,6 +282,26 @@ describe('Confirm Page Container Container Test', () => {
});
});
describe('Rendering NetworkAccountBalanceHeader', () => {
const store = configureMockStore()(mockState);
it('should render NetworkAccountBalanceHeader if displayAccountBalanceHeader is true', () => {
const { getByText } = renderWithProvider(
<ConfirmPageContainer {...props} displayAccountBalanceHeader />,
store,
);
expect(getByText('Balance')).toBeInTheDocument();
});
it('should not render NetworkAccountBalanceHeader if displayAccountBalanceHeader is false', () => {
const { queryByText } = renderWithProvider(
<ConfirmPageContainer {...props} displayAccountBalanceHeader={false} />,
store,
);
expect(queryByText('Balance')).toBeNull();
});
});
describe('Contact/AddressBook name should appear in recipient header', () => {
it('should not show add to address dialog if recipient is in contact list and should display contact name', () => {
const addressBookName = 'test save name';

View File

@ -98,6 +98,7 @@ const ConfirmPageContainer = (props) => {
txData,
assetStandard,
isApprovalOrRejection,
displayAccountBalanceHeader,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
noteComponent,
///: END:ONLY_INCLUDE_IN
@ -169,9 +170,7 @@ const ConfirmPageContainer = (props) => {
<GasFeeContextProvider transaction={currentTransaction}>
<div className="page-container" data-testid="page-container">
<ConfirmPageContainerNavigation />
{assetStandard === TokenStandard.ERC20 ||
assetStandard === TokenStandard.ERC721 ||
assetStandard === TokenStandard.ERC1155 ? (
{displayAccountBalanceHeader ? (
<NetworkAccountBalanceHeader
accountName={fromName}
accountBalance={accountBalance}
@ -401,6 +400,7 @@ ConfirmPageContainer.propTypes = {
supportsEIP1559: PropTypes.bool,
nativeCurrency: PropTypes.string,
isApprovalOrRejection: PropTypes.bool,
displayAccountBalanceHeader: PropTypes.bool,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
noteComponent: PropTypes.node,
///: END:ONLY_INCLUDE_IN

View File

@ -3,25 +3,27 @@ import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { SECONDARY } from '../../../helpers/constants/common';
import { Text } from '../../component-library';
import {
Color,
FONT_WEIGHT,
TextVariant,
} from '../../../helpers/constants/design-system';
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display';
import { isNFTAssetStandard } from '../../../helpers/utils/transactions.util';
import { getShouldShowFiat } from '../../../selectors';
import { useTransactionInfo } from '../../../hooks/useTransactionInfo';
import { Text } from '../../component-library';
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display';
const ConfirmSubTitle = ({
txData,
hexTransactionAmount,
subtitleComponent,
assetStandard,
}) => {
const shouldShowFiat = useSelector(getShouldShowFiat);
const { isNftTransfer } = useTransactionInfo(txData);
if (!shouldShowFiat && !isNftTransfer) {
if (!shouldShowFiat && !isNftTransfer && !isNFTAssetStandard(assetStandard)) {
return null;
}
@ -48,6 +50,7 @@ const ConfirmSubTitle = ({
};
ConfirmSubTitle.propTypes = {
assetStandard: PropTypes.string,
hexTransactionAmount: PropTypes.string,
subtitleComponent: PropTypes.element,
txData: PropTypes.object.isRequired,

View File

@ -1,7 +1,8 @@
import React from 'react';
import { hexToDecimal } from '../../../../shared/modules/conversion.utils';
import { ERC1155, ERC721 } from '@metamask/controller-utils';
import mockState from '../../../../test/data/mock-state.json';
import { hexToDecimal } from '../../../../shared/modules/conversion.utils';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import configureStore from '../../../store/store';
import ConfirmSubTitle from './confirm-subtitle';
@ -42,7 +43,7 @@ describe('ConfirmSubTitle', () => {
expect(container.firstChild).toStrictEqual(null);
});
it('should not null if showFiatInTestnets preference if false but it is NFT Transfer', async () => {
it('should not return null if it is NFT Transfer', async () => {
mockState.metamask.preferences.showFiatInTestnets = false;
mockState.metamask.allNftContracts = {
[mockState.metamask.selectedAddress]: {
@ -67,6 +68,44 @@ describe('ConfirmSubTitle', () => {
expect(await findByText('0.00001')).toBeInTheDocument();
});
it('should not return null if assetStandard is ERC1155', async () => {
mockState.metamask.preferences.showFiatInTestnets = false;
store = configureStore(mockState);
const { findByText } = renderWithProvider(
<ConfirmSubTitle
txData={{
txParams: {
to: '0x9',
},
}}
assetStandard={ERC1155}
hexTransactionAmount="0x9184e72a000"
/>,
store,
);
expect(await findByText('0.00001')).toBeInTheDocument();
});
it('should not return null if assetStandard is ERC712', async () => {
mockState.metamask.preferences.showFiatInTestnets = false;
store = configureStore(mockState);
const { findByText } = renderWithProvider(
<ConfirmSubTitle
txData={{
txParams: {
to: '0x9',
},
}}
assetStandard={ERC721}
hexTransactionAmount="0x9184e72a000"
/>,
store,
);
expect(await findByText('0.00001')).toBeInTheDocument();
});
it('should render subtitleComponent if passed', () => {
const { getByText } = renderWithProvider(
<ConfirmSubTitle

View File

@ -1,5 +1,6 @@
import { MethodRegistry } from 'eth-method-registry';
import log from 'loglevel';
import { ERC1155, ERC721 } from '@metamask/controller-utils';
import { addHexPrefix } from '../../../app/scripts/lib/util';
import {
@ -215,3 +216,12 @@ export function getTransactionTypeTitle(t, type, nativeCurrency = 'ETH') {
}
}
}
/**
* Method to check if asset standard passed is NFT
*
* @param {*} assetStandard - string
* @returns boolean
*/
export const isNFTAssetStandard = (assetStandard) =>
assetStandard === ERC1155 || assetStandard === ERC721;

View File

@ -319,6 +319,7 @@ export default function ConfirmApprove({
hideSenderToRecipient
customTxParamsData={customData}
assetStandard={assetStandard}
displayAccountBalanceHeader
/>
</GasFeeContextProvider>
);

View File

@ -188,6 +188,7 @@ export default function ConfirmTokenTransactionBase({
return (
<ConfirmTransactionBase
assetStandard={assetStandard}
toAddress={toAddress}
image={assetImage}
onEdit={onEdit}

View File

@ -140,6 +140,7 @@ export default class ConfirmTransactionBase extends Component {
isApprovalOrRejection: PropTypes.bool,
assetStandard: PropTypes.string,
useCurrencyRateCheck: PropTypes.bool,
displayAccountBalanceHeader: PropTypes.bool,
};
state = {
@ -735,13 +736,15 @@ export default class ConfirmTransactionBase extends Component {
}
renderSubtitleComponent() {
const { subtitleComponent, hexTransactionAmount, txData } = this.props;
const { assetStandard, subtitleComponent, hexTransactionAmount, txData } =
this.props;
return (
<ConfirmSubTitle
hexTransactionAmount={hexTransactionAmount}
subtitleComponent={subtitleComponent}
txData={txData}
assetStandard={assetStandard}
/>
);
}
@ -837,6 +840,7 @@ export default class ConfirmTransactionBase extends Component {
image,
isApprovalOrRejection,
assetStandard,
displayAccountBalanceHeader,
title,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
isNoteToTraderSupported,
@ -952,6 +956,7 @@ export default class ConfirmTransactionBase extends Component {
isApprovalOrRejection={isApprovalOrRejection}
assetStandard={assetStandard}
txData={txData}
displayAccountBalanceHeader={displayAccountBalanceHeader}
/>
</TransactionModalContextProvider>
);

View File

@ -154,8 +154,8 @@ export default class SendAssetRow extends Component {
isEqualCaseInsensitive(address, details.address) &&
tokenId === details.tokenId,
);
if (nft) {
return this.renderNft(nft);
if (nft || details) {
return this.renderNft(nft ?? details);
}
}
return this.renderNativeCurrency();
@ -184,8 +184,13 @@ export default class SendAssetRow extends Component {
renderNativeCurrency(insideDropdown = false) {
const { t } = this.context;
const { accounts, selectedAddress, nativeCurrency, nativeCurrencyImage } =
this.props;
const {
accounts,
selectedAddress,
nativeCurrency,
nativeCurrencyImage,
sendAsset,
} = this.props;
const { sendableTokens, sendableNfts } = this.state;
@ -204,11 +209,15 @@ export default class SendAssetRow extends Component {
onClick={() => this.selectToken(AssetType.native)}
>
<div className="send-v2__asset-dropdown__asset-icon">
{sendAsset?.type === AssetType.NFT && sendAsset?.details?.image ? (
<img width={36} src={sendAsset.details.image} />
) : (
<Identicon
diameter={36}
image={nativeCurrencyImage}
address={nativeCurrency}
/>
)}
</div>
<div className="send-v2__asset-dropdown__asset-data">
<div className="send-v2__asset-dropdown__symbol">
@ -277,7 +286,7 @@ export default class SendAssetRow extends Component {
</div>
<div className="send-v2__asset-dropdown__asset-data">
<div className="send-v2__asset-dropdown__symbol">
{nftCollection.name || name}
{nftCollection?.name || name}
</div>
<div className="send-v2__asset-dropdown__name">
<span className="send-v2__asset-dropdown__name__label">

View File

@ -0,0 +1,65 @@
import React from 'react';
import configureMockStore from 'redux-mock-store';
import mockSendState from '../../../../../test/data/mock-send-state.json';
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
import SendAssetRow from './send-asset-row.component';
const mockStore = configureMockStore()(mockSendState);
const props = {
tokens: [],
selectedAddress: '0x0',
nfts: [],
collections: [],
sendAsset: {
balance: '0x1',
details: {
address: '0xb9b9c1592e737a2c71d80d3b8495049990161e0c',
tokenId: '2',
standard: 'ERC721',
tokenURI:
'data:application/json;base64,eyJuYW1lIjogIlRlc3QgRGFwcCBDb2xsZWN0aWJsZXMgIzIiLCAiZGVzY3JpcHRpb24iOiAiVGVzdCBEYXBwIENvbGxlY3RpYmxlcyBmb3IgdGVzdGluZy4iLCAiaW1hZ2UiOiAiZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCb1pXbG5hSFE5SWpNMU1DSWdkMmxrZEdnOUlqTTFNQ0lnZG1sbGQwSnZlRDBpTUNBd0lERXdNQ0F4TURBaUlIaHRiRzV6UFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eU1EQXdMM04yWnlJK1BHUmxabk0rUEhCaGRHZ2dhV1E5SWsxNVVHRjBhQ0lnWm1sc2JEMGlibTl1WlNJZ2MzUnliMnRsUFNKeVpXUWlJR1E5SWsweE1DdzVNQ0JST1RBc09UQWdPVEFzTkRVZ1VUa3dMREV3SURVd0xERXdJRkV4TUN3eE1DQXhNQ3cwTUNCUk1UQXNOekFnTkRVc056QWdVVGN3TERjd0lEYzFMRFV3SWlBdlBqd3ZaR1ZtY3o0OGRHVjRkRDQ4ZEdWNGRGQmhkR2dnYUhKbFpqMGlJMDE1VUdGMGFDSStVWFZwWTJzZ1luSnZkMjRnWm05NElHcDFiWEJ6SUc5MlpYSWdkR2hsSUd4aGVua2daRzluTGp3dmRHVjRkRkJoZEdnK1BDOTBaWGgwUGp3dmMzWm5QZz09IiwgImF0dHJpYnV0ZXMiOiBbeyJ0cmFpdF90eXBlIjogIlRva2VuIElkIiwgInZhbHVlIjogIjIifV19',
symbol: 'TDC',
name: 'TestDappCollectibles',
image:
'data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjM1MCIgd2lkdGg9IjM1MCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdGggaWQ9Ik15UGF0aCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZWQiIGQ9Ik0xMCw5MCBROTAsOTAgOTAsNDUgUTkwLDEwIDUwLDEwIFExMCwxMCAxMCw0MCBRMTAsNzAgNDUsNzAgUTcwLDcwIDc1LDUwIiAvPjwvZGVmcz48dGV4dD48dGV4dFBhdGggaHJlZj0iI015UGF0aCI+UXVpY2sgYnJvd24gZm94IGp1bXBzIG92ZXIgdGhlIGxhenkgZG9nLjwvdGV4dFBhdGg+PC90ZXh0Pjwvc3ZnPg==',
},
error: null,
type: 'NFT',
},
accounts: {
'0x0': {
address: '0x0',
balance: '0x4cc191087ecfcee6',
},
'0x1': {
address: '0x1',
balance: '0x041813d3a1fc67ed',
},
},
};
describe('SendAssetRow', () => {
describe('Sending NFT', () => {
it('should render NFT image even if NFT is not imported into metamask', async () => {
const { getByRole } = renderWithProvider(
<SendAssetRow {...props} />,
mockStore,
);
const image = getByRole('img');
expect(image).toBeDefined();
expect(image).toHaveAttribute('src', props.sendAsset.details.image);
});
it('should render token id even if NFT is not imported into metamask', async () => {
const { getByText } = renderWithProvider(
<SendAssetRow {...props} />,
mockStore,
);
expect(getByText('Token ID:')).toBeInTheDocument();
});
});
});