diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index 71ea87943..09fb496b4 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -58,6 +58,10 @@
"message": "$1 may access and spend up to this max amount",
"description": "$1 is the url of the site requesting ability to spend"
},
+ "accessAndSpendNoticeNFT": {
+ "message": "$1 may access and spend this asset",
+ "description": "$1 is the url of the site requesting ability to spend"
+ },
"accessingYourCamera": {
"message": "Accessing your camera..."
},
@@ -279,6 +283,9 @@
"approvedAmountWithColon": {
"message": "Approved amount:"
},
+ "approvedAsset": {
+ "message": "Approved asset"
+ },
"areYouDeveloper": {
"message": "Are you a developer?"
},
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 9b2fc8783..aa337c864 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -1271,7 +1271,6 @@ export default class MetamaskController extends EventEmitter {
appStateController,
collectiblesController,
collectibleDetectionController,
- assetsContractController,
currencyRateController,
detectTokensController,
ensController,
@@ -1427,9 +1426,7 @@ export default class MetamaskController extends EventEmitter {
setTheme: preferencesController.setTheme.bind(preferencesController),
// AssetsContractController
- getTokenStandardAndDetails: assetsContractController.getTokenStandardAndDetails.bind(
- assetsContractController,
- ),
+ getTokenStandardAndDetails: this.getTokenStandardAndDetails.bind(this),
// CollectiblesController
addCollectible: collectiblesController.addCollectible.bind(
@@ -1758,6 +1755,19 @@ export default class MetamaskController extends EventEmitter {
};
}
+ async getTokenStandardAndDetails(address, userAddress, tokenId) {
+ const details = await this.assetsContractController.getTokenStandardAndDetails(
+ address,
+ userAddress,
+ tokenId,
+ );
+ return {
+ ...details,
+ decimals: details?.decimals?.toString(10),
+ balance: details?.balance?.toString(10),
+ };
+ }
+
//=============================================================================
// VAULT / KEYRING RELATED METHODS
//=============================================================================
diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js
index fea0e00b7..3d8e46f4a 100644
--- a/test/e2e/helpers.js
+++ b/test/e2e/helpers.js
@@ -16,6 +16,7 @@ const { ensureXServerIsRunning } = require('./x-server');
const tinyDelayMs = 200;
const regularDelayMs = tinyDelayMs * 2;
const largeDelayMs = regularDelayMs * 2;
+const veryLargeDelayMs = largeDelayMs * 2;
const dappPort = 8080;
const convertToHexValue = (val) => `0x${new BigNumber(val, 10).toString(16)}`;
@@ -276,6 +277,7 @@ module.exports = {
tinyDelayMs,
regularDelayMs,
largeDelayMs,
+ veryLargeDelayMs,
withFixtures,
connectDappWithExtensionPopup,
completeImportSRPOnboardingFlow,
diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js
index 3600ec109..30ca8d43b 100644
--- a/test/e2e/metamask-ui.spec.js
+++ b/test/e2e/metamask-ui.spec.js
@@ -3,7 +3,12 @@ const path = require('path');
const enLocaleMessages = require('../../app/_locales/en/messages.json');
const createStaticServer = require('../../development/create-static-server');
-const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers');
+const {
+ tinyDelayMs,
+ regularDelayMs,
+ largeDelayMs,
+ veryLargeDelayMs,
+} = require('./helpers');
const { buildWebDriver } = require('./webdriver');
const Ganache = require('./ganache');
const { ensureXServerIsRunning } = require('./x-server');
@@ -272,7 +277,7 @@ describe('MetaMask', function () {
const gasPriceInput = inputs[1];
await gasLimitInput.fill('4700000');
await gasPriceInput.fill('20');
- await driver.delay(1000);
+ await driver.delay(veryLargeDelayMs);
await driver.clickElement({ text: 'Save', tag: 'button' });
await driver.clickElement({ text: 'Confirm', tag: 'button' });
@@ -343,10 +348,11 @@ describe('MetaMask', function () {
// Continue to next screen
await driver.delay(largeDelayMs);
await driver.clickElement({ text: 'Next', tag: 'button' });
- await driver.delay(regularDelayMs);
+ await driver.delay(largeDelayMs);
});
it('displays the token transfer data', async function () {
+ await driver.delay(largeDelayMs);
await driver.clickElement({ text: 'Hex', tag: 'button' });
await driver.delay(regularDelayMs);
@@ -386,7 +392,7 @@ describe('MetaMask', function () {
const gasPriceInput = inputs[1];
await gasLimitInput.fill('100000');
await gasPriceInput.fill('100');
- await driver.delay(1000);
+ await driver.delay(veryLargeDelayMs);
await driver.clickElement({ text: 'Save', tag: 'button' });
});
@@ -449,19 +455,20 @@ describe('MetaMask', function () {
});
it('customizes gas', async function () {
+ await driver.delay(veryLargeDelayMs);
await driver.clickElement({ text: 'Edit', tag: 'button' });
- await driver.delay(largeDelayMs);
+ await driver.delay(veryLargeDelayMs);
await driver.clickElement(
{ text: 'Edit suggested gas fee', tag: 'button' },
10000,
);
- await driver.delay(1000);
+ await driver.delay(veryLargeDelayMs);
const inputs = await driver.findElements('input[type="number"]');
const gasLimitInput = inputs[0];
const gasPriceInput = inputs[1];
await gasLimitInput.fill('60000');
await gasPriceInput.fill('10');
- await driver.delay(1000);
+ await driver.delay(veryLargeDelayMs);
await driver.clickElement({ text: 'Save', tag: 'button' });
await driver.findElement({ tag: 'span', text: '0.0006' });
});
@@ -586,7 +593,7 @@ describe('MetaMask', function () {
await gasLimitInput.fill('60001');
- await driver.delay(1000);
+ await driver.delay(veryLargeDelayMs);
await driver.clickElement({ text: 'Save', tag: 'button' });
@@ -752,7 +759,7 @@ describe('MetaMask', function () {
});
it('submits the transaction', async function () {
- await driver.delay(1000);
+ await driver.delay(veryLargeDelayMs);
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.delay(regularDelayMs);
});
diff --git a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js
index 089b359b8..7da4ddeba 100644
--- a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js
+++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js
@@ -11,6 +11,8 @@ import useAddressDetails from '../../../../../hooks/useAddressDetails';
import Identicon from '../../../../ui/identicon';
import InfoTooltip from '../../../../ui/info-tooltip';
import NicknamePopovers from '../../../modals/nickname-popovers';
+import Typography from '../../../../ui/typography';
+import { TYPOGRAPHY } from '../../../../../helpers/constants/design-system';
const ConfirmPageContainerSummary = (props) => {
const {
@@ -116,9 +118,15 @@ const ConfirmPageContainerSummary = (props) => {
{renderImage()}
{!hideTitle ? (
-
+
{titleComponent || title}
-
+
) : null}
{hideSubtitle ? null : (
diff --git a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss
index 0f4941976..53fb24a22 100644
--- a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss
+++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss
@@ -77,6 +77,14 @@
text-overflow: ellipsis;
}
+ &__title-text-long {
+ @include H3;
+
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
&__subtitle {
@include H5;
diff --git a/ui/components/ui/typography/typography.js b/ui/components/ui/typography/typography.js
index 9496533ba..166ad4ac1 100644
--- a/ui/components/ui/typography/typography.js
+++ b/ui/components/ui/typography/typography.js
@@ -82,6 +82,7 @@ export default function Typography({
fontStyle = 'normal',
align,
overflowWrap,
+ title,
tag,
margin = [1, 0],
boxProps = {},
@@ -117,7 +118,10 @@ export default function Typography({
return (
{(boxClassName) => (
-
+
{children}
)}
@@ -175,6 +179,10 @@ Typography.propTypes = {
* Additional className to assign the Typography component
*/
className: PropTypes.string,
+ /**
+ * Title attribute to include on the element. Will show as tooltip on hover.
+ */
+ title: PropTypes.string,
/**
* The text content of the Typography component
*/
diff --git a/ui/helpers/utils/token-util.js b/ui/helpers/utils/token-util.js
index 68431dde5..a75db6da6 100644
--- a/ui/helpers/utils/token-util.js
+++ b/ui/helpers/utils/token-util.js
@@ -4,8 +4,12 @@ import {
conversionUtil,
multiplyCurrencies,
} from '../../../shared/modules/conversion.utils';
+import { getTokenStandardAndDetails } from '../../store/actions';
+import { ERC1155, ERC721 } from '../constants/common';
+import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
import * as util from './util';
import { formatCurrency } from './confirm-tx.util';
+import { getTransactionData } from './transactions.util';
const DEFAULT_SYMBOL = '';
@@ -212,3 +216,48 @@ export function getTokenFiatAmount(
}
return result;
}
+
+export async function getAssetDetails(
+ tokenAddress,
+ currentUserAddress,
+ transactionData,
+ existingCollectibles,
+) {
+ const tokenData = getTransactionData(transactionData);
+ if (!tokenData) {
+ throw new Error('Unable to detect valid token data');
+ }
+
+ const tokenId = getTokenValueParam(tokenData);
+ let tokenDetails;
+ try {
+ tokenDetails = await getTokenStandardAndDetails(
+ tokenAddress,
+ currentUserAddress,
+ tokenId,
+ );
+ } catch (error) {
+ log.warn(error);
+ return {};
+ }
+
+ if (tokenDetails?.standard) {
+ const { standard } = tokenDetails;
+ if (standard === ERC721 || standard === ERC1155) {
+ const existingCollectible = existingCollectibles.find(({ address }) =>
+ isEqualCaseInsensitive(tokenAddress, address),
+ );
+
+ if (existingCollectible) {
+ return {
+ ...existingCollectible,
+ standard,
+ };
+ }
+ }
+ // else if not a collectible already in state or standard === ERC20 just return tokenDetails as it contains all required data
+ return tokenDetails;
+ }
+
+ return {};
+}
diff --git a/ui/hooks/useAssetDetails.js b/ui/hooks/useAssetDetails.js
new file mode 100644
index 000000000..ac12ed494
--- /dev/null
+++ b/ui/hooks/useAssetDetails.js
@@ -0,0 +1,118 @@
+import { useState, useEffect } from 'react';
+import { useSelector, useDispatch } from 'react-redux';
+import { getCollectibles, getTokens } from '../ducks/metamask/metamask';
+import { ERC1155, ERC721, ERC20 } from '../helpers/constants/common';
+import {
+ calcTokenAmount,
+ getAssetDetails,
+ getTokenAddressParam,
+ getTokenValueParam,
+} from '../helpers/utils/token-util';
+import { getTransactionData } from '../helpers/utils/transactions.util';
+import { getTokenList } from '../selectors';
+import { hideLoadingIndication, showLoadingIndication } from '../store/actions';
+import { usePrevious } from './usePrevious';
+
+export function useAssetDetails(tokenAddress, userAddress, transactionData) {
+ const dispatch = useDispatch();
+
+ // state selectors
+ const tokens = useSelector(getTokens);
+ const collectibles = useSelector(getCollectibles);
+ const tokenList = useSelector(getTokenList);
+
+ // in-hook state
+ const [currentAsset, setCurrentAsset] = useState(null);
+
+ // previous state checkers
+ const prevTokenAddress = usePrevious(tokenAddress);
+ const prevUserAddress = usePrevious(userAddress);
+ const prevTransactionData = usePrevious(transactionData);
+
+ useEffect(() => {
+ async function getAndSetAssetDetails() {
+ dispatch(showLoadingIndication());
+ const assetDetails = await getAssetDetails(
+ tokenAddress,
+ userAddress,
+ transactionData,
+ collectibles,
+ tokens,
+ tokenList,
+ );
+ setCurrentAsset(assetDetails);
+ dispatch(hideLoadingIndication());
+ }
+ if (
+ tokenAddress !== prevTokenAddress ||
+ userAddress !== prevUserAddress ||
+ transactionData !== prevTransactionData
+ ) {
+ getAndSetAssetDetails();
+ }
+ }, [
+ dispatch,
+ prevTokenAddress,
+ prevTransactionData,
+ prevUserAddress,
+ tokenAddress,
+ userAddress,
+ transactionData,
+ collectibles,
+ tokens,
+ tokenList,
+ ]);
+
+ let assetStandard,
+ assetName,
+ assetAddress,
+ tokenSymbol,
+ decimals,
+ tokenImage,
+ userBalance,
+ tokenValue,
+ toAddress,
+ tokenAmount,
+ tokenId;
+
+ if (currentAsset) {
+ const {
+ standard,
+ symbol,
+ image,
+ name,
+ balance,
+ decimals: currentAssetDecimals,
+ } = currentAsset;
+ const tokenData = getTransactionData(transactionData);
+ assetStandard = standard;
+ assetAddress = tokenAddress;
+ tokenSymbol = symbol;
+ tokenImage = image;
+ toAddress = getTokenAddressParam(tokenData);
+ if (assetStandard === ERC721 || assetStandard === ERC1155) {
+ assetName = name;
+ tokenId = getTokenValueParam(tokenData);
+ }
+ if (assetStandard === ERC20) {
+ userBalance = balance;
+ decimals = Number(currentAssetDecimals?.toString(10));
+ tokenAmount =
+ tokenData &&
+ calcTokenAmount(getTokenValueParam(tokenData), decimals).toString(10);
+ }
+ }
+ return {
+ assetStandard,
+ assetName,
+ assetAddress,
+ userBalance,
+ tokenSymbol,
+ decimals,
+ tokenImage,
+ tokenValue,
+ toAddress,
+ tokenAmount,
+ tokenId,
+ };
+}
diff --git a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js
index e1ab67009..5fe8c59db 100644
--- a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js
+++ b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js
@@ -28,6 +28,7 @@ import { SECOND } from '../../../../shared/constants/time';
import { ConfirmPageContainerWarning } from '../../../components/app/confirm-page-container/confirm-page-container-content';
import GasDetailsItem from '../../../components/app/gas-details-item';
import LedgerInstructionField from '../../../components/app/ledger-instruction-field';
+import { ERC1155, ERC20, ERC721 } from '../../../helpers/constants/common';
export default class ConfirmApproveContent extends Component {
static contextTypes = {
@@ -60,13 +61,15 @@ export default class ConfirmApproveContent extends Component {
warning: PropTypes.string,
txData: PropTypes.object,
fromAddressIsLedger: PropTypes.bool,
- tokenImage: PropTypes.string,
chainId: PropTypes.string,
rpcPrefs: PropTypes.object,
isContract: PropTypes.bool,
hexTransactionTotal: PropTypes.string,
isMultiLayerFeeNetwork: PropTypes.bool,
supportsEIP1559V2: PropTypes.bool,
+ assetName: PropTypes.string,
+ tokenId: PropTypes.string,
+ assetStandard: PropTypes.string,
};
state = {
@@ -178,7 +181,60 @@ export default class ConfirmApproveContent extends Component {
);
}
- renderPermissionContent() {
+ renderERC721OrERC1155PermissionContent() {
+ const { t } = this.context;
+ const { origin, toAddress, isContract, assetName, tokenId } = this.props;
+
+ const displayedAddress = isContract
+ ? `${t('contract')} (${addressSummary(toAddress)})`
+ : addressSummary(toAddress);
+ return (
+
+
+ {t('accessAndSpendNoticeNFT', [origin])}
+
+
+
+ {t('approvedAsset')}:
+
+
+ {`${assetName} #${tokenId}`}
+
+
+
+
+ {t('grantedToWithColon')}
+
+
+ {displayedAddress}
+
+
+
+
+
+
+ );
+ }
+
+ renderERC20PermissionContent() {
const { t } = this.context;
const {
customTokenAmount,
@@ -188,6 +244,7 @@ export default class ConfirmApproveContent extends Component {
toAddress,
isContract,
} = this.props;
+
const displayedAddress = isContract
? `${t('contract')} (${addressSummary(toAddress)})`
: addressSummary(toAddress);
@@ -252,6 +309,75 @@ export default class ConfirmApproveContent extends Component {
);
}
+ renderFullDetails() {
+ const { t } = this.context;
+ const {
+ assetStandard,
+ showEditApprovalPermissionModal,
+ customTokenAmount,
+ tokenAmount,
+ decimals,
+ origin,
+ setCustomAmount,
+ tokenSymbol,
+ tokenBalance,
+ } = this.props;
+ if (assetStandard === ERC20) {
+ return (
+
+
+ {this.renderApproveContentCard({
+ symbol:
,
+ title: t('permissionRequest'),
+ content: this.renderERC20PermissionContent(),
+ showEdit: true,
+ onEditClick: () =>
+ showEditApprovalPermissionModal({
+ customTokenAmount,
+ decimals,
+ origin,
+ setCustomAmount,
+ tokenAmount,
+ tokenSymbol,
+ tokenBalance,
+ }),
+ })}
+
+
+ {this.renderApproveContentCard({
+ symbol: ,
+ title: 'Data',
+ content: this.renderDataContent(),
+ noBorder: true,
+ })}
+
+
+ );
+ } else if (assetStandard === ERC721 || assetStandard === ERC1155) {
+ return (
+
+
+ {this.renderApproveContentCard({
+ symbol:
,
+ title: t('permissionRequest'),
+ content: this.renderERC721OrERC1155PermissionContent(),
+ showEdit: false,
+ })}
+
+
+ {this.renderApproveContentCard({
+ symbol: ,
+ title: t('data'),
+ content: this.renderDataContent(),
+ noBorder: true,
+ })}
+
+
+ );
+ }
+ return null;
+ }
+
renderCustomNonceContent() {
const { t } = this.context;
const {
@@ -321,11 +447,13 @@ export default class ConfirmApproveContent extends Component {
warning,
txData,
fromAddressIsLedger,
- tokenImage,
toAddress,
chainId,
rpcPrefs,
isContract,
+ assetStandard,
+ tokenId,
+ assetName,
} = this.props;
const { showFullTxDetails } = this.state;
@@ -368,7 +496,11 @@ export default class ConfirmApproveContent extends Component {
- {t('allowSpendToken', [tokenSymbol])}
+ {t('allowSpendToken', [
+ assetStandard === ERC20
+ ? tokenSymbol
+ : `${assetName} (#${tokenId})`,
+ ])}
{t('trustSiteApprovePermission', [
@@ -383,7 +515,6 @@ export default class ConfirmApproveContent extends Component {
className="confirm-approve-content__address-identicon"
diameter={20}
address={toAddress}
- image={tokenImage}
/>
-
-
- showEditApprovalPermissionModal({
- customTokenAmount,
- decimals,
- origin,
- setCustomAmount,
- tokenAmount,
- tokenSymbol,
- tokenBalance,
- })
- }
- >
- {t('editPermission')}
+ {assetStandard === ERC20 ? (
+
+
+ showEditApprovalPermissionModal({
+ customTokenAmount,
+ decimals,
+ origin,
+ setCustomAmount,
+ tokenAmount,
+ tokenSymbol,
+ tokenBalance,
+ })
+ }
+ >
+ {t('editPermission')}
+
-
+ ) : null}
{this.renderApproveContentCard({
symbol: ,
@@ -527,36 +660,7 @@ export default class ConfirmApproveContent extends Component {
) : null}
- {showFullTxDetails ? (
-
-
- {this.renderApproveContentCard({
- symbol:
,
- title: t('permissionRequest'),
- content: this.renderPermissionContent(),
- showEdit: true,
- onEditClick: () =>
- showEditApprovalPermissionModal({
- customTokenAmount,
- decimals,
- origin,
- setCustomAmount,
- tokenAmount,
- tokenSymbol,
- tokenBalance,
- }),
- })}
-
-
- {this.renderApproveContentCard({
- symbol: ,
- title: 'Data',
- content: this.renderDataContent(),
- noBorder: true,
- })}
-
-
- ) : null}
+ {showFullTxDetails ? this.renderFullDetails() : null}
);
}
diff --git a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.test.js b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.test.js
index 162332853..52ecdeece 100644
--- a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.test.js
+++ b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.test.js
@@ -2,6 +2,7 @@ import React from 'react';
import configureMockStore from 'redux-mock-store';
import { fireEvent } from '@testing-library/react';
import { renderWithProvider } from '../../../../test/jest/rendering';
+import { ERC20 } from '../../../helpers/constants/common';
import ConfirmApproveContent from '.';
const renderComponent = (props) => {
@@ -16,6 +17,7 @@ const props = {
tokenAmount: '10',
origin: 'https://metamask.github.io/test-dapp/',
tokenSymbol: 'TST',
+ assetStandard: ERC20,
tokenImage: 'https://metamask.github.io/test-dapp/metamask-fox.svg',
tokenBalance: '15',
showCustomizeGasModal: jest.fn(),
diff --git a/ui/pages/confirm-approve/confirm-approve.js b/ui/pages/confirm-approve/confirm-approve.js
index 1a2663367..246baca77 100644
--- a/ui/pages/confirm-approve/confirm-approve.js
+++ b/ui/pages/confirm-approve/confirm-approve.js
@@ -1,6 +1,6 @@
import React, { useEffect, useRef, useState, useCallback } from 'react';
+import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
-import { useParams } from 'react-router-dom';
import ConfirmTransactionBase from '../confirm-transaction-base';
import { EDIT_GAS_MODES } from '../../../shared/constants/gas';
import {
@@ -8,24 +8,15 @@ import {
updateCustomNonce,
getNextNonce,
} from '../../store/actions';
-import { getTransactionData } from '../../helpers/utils/transactions.util';
-import {
- calcTokenAmount,
- getTokenAddressParam,
- getTokenValueParam,
-} from '../../helpers/utils/token-util';
+import { calcTokenAmount } from '../../helpers/utils/token-util';
import { readAddressAsContract } from '../../../shared/modules/contract-utils';
import { GasFeeContextProvider } from '../../contexts/gasFee';
import { TransactionModalContextProvider } from '../../contexts/transaction-modal';
-import { useTokenTracker } from '../../hooks/useTokenTracker';
import {
- getTokens,
getNativeCurrency,
isAddressLedger,
} from '../../ducks/metamask/metamask';
import {
- transactionFeeSelector,
- txDataSelector,
getCurrentCurrency,
getSubjectMetadata,
getUseNonceField,
@@ -38,12 +29,11 @@ import {
getEIP1559V2Enabled,
} from '../../selectors';
import { useApproveTransaction } from '../../hooks/useApproveTransaction';
-import { currentNetworkTxListSelector } from '../../selectors/transactions';
import AdvancedGasFeePopover from '../../components/app/advanced-gas-fee-popover';
import EditGasFeePopover from '../../components/app/edit-gas-fee-popover';
import EditGasPopover from '../../components/app/edit-gas-popover/edit-gas-popover.component';
import Loading from '../../components/ui/loading-screen';
-import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
+import { ERC20, ERC1155, ERC721 } from '../../helpers/constants/common';
import { getCustomTxParamsData } from './confirm-approve.util';
import ConfirmApproveContent from './confirm-approve-content';
@@ -51,19 +41,28 @@ const isAddressLedgerByFromAddress = (address) => (state) => {
return isAddressLedger(state, address);
};
-export default function ConfirmApprove() {
+export default function ConfirmApprove({
+ assetStandard,
+ assetName,
+ userBalance,
+ tokenSymbol,
+ decimals,
+ tokenImage,
+ tokenAmount,
+ tokenId,
+ userAddress,
+ toAddress,
+ transaction,
+ ethTransactionTotal,
+ fiatTransactionTotal,
+ hexTransactionTotal,
+}) {
const dispatch = useDispatch();
- const { id: paramsTransactionId } = useParams();
- const {
- id: transactionId,
- txParams: { to: tokenAddress, data, from } = {},
- } = useSelector(txDataSelector);
+ const { txParams: { data: transactionData } = {} } = transaction;
const currentCurrency = useSelector(getCurrentCurrency);
const nativeCurrency = useSelector(getNativeCurrency);
- const currentNetworkTxList = useSelector(currentNetworkTxListSelector);
const subjectMetadata = useSelector(getSubjectMetadata);
- const tokens = useSelector(getTokens);
const useNonceField = useSelector(getUseNonceField);
const nextNonce = useSelector(getNextSuggestedNonce);
const customNonceValue = useSelector(getCustomNonceValue);
@@ -73,45 +72,17 @@ export default function ConfirmApprove() {
const networkAndAccountSupports1559 = useSelector(
checkNetworkAndAccountSupports1559,
);
-
- const fromAddressIsLedger = useSelector(isAddressLedgerByFromAddress(from));
-
- const transaction =
- currentNetworkTxList.find(
- ({ id }) => id === (Number(paramsTransactionId) || transactionId),
- ) || {};
- const {
- ethTransactionTotal,
- fiatTransactionTotal,
- hexTransactionTotal,
- } = useSelector((state) => transactionFeeSelector(state, transaction));
+ const fromAddressIsLedger = useSelector(
+ isAddressLedgerByFromAddress(userAddress),
+ );
+ const [customPermissionAmount, setCustomPermissionAmount] = useState('');
+ const [submitWarning, setSubmitWarning] = useState('');
+ const [isContract, setIsContract] = useState(false);
const eip1559V2Enabled = useSelector(getEIP1559V2Enabled);
const supportsEIP1559V2 = eip1559V2Enabled && networkAndAccountSupports1559;
- const currentToken = (tokens &&
- tokens.find(({ address }) =>
- isEqualCaseInsensitive(tokenAddress, address),
- )) || {
- address: tokenAddress,
- };
-
- const { tokensWithBalances } = useTokenTracker([currentToken]);
- const tokenTrackerBalance = tokensWithBalances[0]?.balance || '';
-
- const tokenSymbol = currentToken?.symbol;
- const decimals = Number(currentToken?.decimals);
- const tokenImage = currentToken?.image;
- const tokenData = getTransactionData(data);
- const tokenValue = getTokenValueParam(tokenData);
- const toAddress = getTokenAddressParam(tokenData);
- const tokenAmount =
- tokenData && calcTokenAmount(tokenValue, decimals).toString(10);
-
- const [customPermissionAmount, setCustomPermissionAmount] = useState('');
-
const previousTokenAmount = useRef(tokenAmount);
-
const {
approveTransaction,
showCustomizeGasPopover,
@@ -125,7 +96,6 @@ export default function ConfirmApprove() {
previousTokenAmount.current = tokenAmount;
}, [customPermissionAmount, tokenAmount]);
- const [submitWarning, setSubmitWarning] = useState('');
const prevNonce = useRef(nextNonce);
const prevCustomNonce = useRef(customNonceValue);
useEffect(() => {
@@ -145,7 +115,6 @@ export default function ConfirmApprove() {
prevNonce.current = nextNonce;
}, [customNonceValue, nextNonce]);
- const [isContract, setIsContract] = useState(false);
const checkIfContract = useCallback(async () => {
const { isContractAddress } = await readAddressAsContract(
global.eth,
@@ -153,6 +122,7 @@ export default function ConfirmApprove() {
);
setIsContract(isContractAddress);
}, [setIsContract, toAddress]);
+
useEffect(() => {
checkIfContract();
}, [checkIfContract]);
@@ -162,21 +132,30 @@ export default function ConfirmApprove() {
const { iconUrl: siteImage = '' } = subjectMetadata[origin] || {};
- const tokensText = `${Number(tokenAmount)} ${tokenSymbol}`;
- const tokenBalance = tokenTrackerBalance
- ? calcTokenAmount(tokenTrackerBalance, decimals).toString(10)
+ let tokensText;
+ if (assetStandard === ERC20) {
+ tokensText = `${Number(tokenAmount)} ${tokenSymbol}`;
+ } else if (assetStandard === ERC721 || assetStandard === ERC1155) {
+ tokensText = assetName;
+ }
+
+ const tokenBalance = userBalance
+ ? calcTokenAmount(userBalance, decimals).toString(10)
: '';
const customData = customPermissionAmount
- ? getCustomTxParamsData(data, { customPermissionAmount, decimals })
+ ? getCustomTxParamsData(transactionData, {
+ customPermissionAmount,
+ decimals,
+ })
: null;
- return tokenSymbol === undefined ? (
+ return tokenSymbol === undefined && assetName === undefined ? (
) : (
);
}
+
+ConfirmApprove.propTypes = {
+ assetStandard: PropTypes.string,
+ assetName: PropTypes.string,
+ userBalance: PropTypes.string,
+ tokenSymbol: PropTypes.string,
+ decimals: PropTypes.string,
+ tokenImage: PropTypes.string,
+ tokenAmount: PropTypes.string,
+ tokenId: PropTypes.string,
+ userAddress: PropTypes.string,
+ toAddress: PropTypes.string,
+ transaction: PropTypes.shape({
+ origin: PropTypes.string,
+ txParams: PropTypes.shape({
+ data: PropTypes.string,
+ to: PropTypes.string,
+ from: PropTypes.string,
+ }),
+ }),
+ ethTransactionTotal: PropTypes.string,
+ fiatTransactionTotal: PropTypes.string,
+ hexTransactionTotal: PropTypes.string,
+};
diff --git a/ui/pages/confirm-send-token/confirm-send-token.js b/ui/pages/confirm-send-token/confirm-send-token.js
new file mode 100644
index 000000000..a03fb9835
--- /dev/null
+++ b/ui/pages/confirm-send-token/confirm-send-token.js
@@ -0,0 +1,118 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { useDispatch, useSelector } from 'react-redux';
+import { useHistory } from 'react-router-dom';
+import ConfirmTokenTransactionBase from '../confirm-token-transaction-base/confirm-token-transaction-base';
+import { SEND_ROUTE } from '../../helpers/constants/routes';
+import { ASSET_TYPES, editTransaction } from '../../ducks/send';
+import {
+ contractExchangeRateSelector,
+ getCurrentCurrency,
+} from '../../selectors';
+import {
+ getConversionRate,
+ getNativeCurrency,
+} from '../../ducks/metamask/metamask';
+import { ERC20, ERC721 } from '../../helpers/constants/common';
+import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck';
+import { showSendTokenPage } from '../../store/actions';
+
+export default function ConfirmSendToken({
+ assetStandard,
+ toAddress,
+ tokenAddress,
+ assetName,
+ tokenSymbol,
+ tokenAmount,
+ tokenId,
+ transaction,
+ image,
+ ethTransactionTotal,
+ fiatTransactionTotal,
+ hexMaximumTransactionFee,
+}) {
+ const dispatch = useDispatch();
+ const history = useHistory();
+
+ const handleEditTransaction = ({
+ txData,
+ tokenData,
+ tokenProps: assetDetails,
+ }) => {
+ const { id } = txData;
+ dispatch(
+ editTransaction(
+ ASSET_TYPES.TOKEN,
+ id.toString(),
+ tokenData,
+ assetDetails,
+ ),
+ );
+ dispatch(clearConfirmTransaction());
+ dispatch(showSendTokenPage());
+ };
+
+ const handleEdit = (confirmTransactionData) => {
+ handleEditTransaction(confirmTransactionData);
+ history.push(SEND_ROUTE);
+ };
+ const conversionRate = useSelector(getConversionRate);
+ const nativeCurrency = useSelector(getNativeCurrency);
+ const currentCurrency = useSelector(getCurrentCurrency);
+ const contractExchangeRate = useSelector(contractExchangeRateSelector);
+
+ let title, subtitle;
+
+ if (assetStandard === ERC721) {
+ title = assetName;
+ subtitle = `#${tokenId}`;
+ } else if (assetStandard === ERC20) {
+ title = `${tokenAmount} ${tokenSymbol}`;
+ }
+
+ return (
+
+ );
+}
+
+ConfirmSendToken.propTypes = {
+ tokenAmount: PropTypes.string,
+ assetStandard: PropTypes.string,
+ assetName: PropTypes.string,
+ tokenSymbol: PropTypes.string,
+ image: PropTypes.string,
+ tokenId: PropTypes.string,
+ toAddress: PropTypes.string,
+ tokenAddress: PropTypes.string,
+ transaction: PropTypes.shape({
+ origin: PropTypes.string,
+ txParams: PropTypes.shape({
+ data: PropTypes.string,
+ to: PropTypes.string,
+ from: PropTypes.string,
+ }),
+ }),
+ ethTransactionTotal: PropTypes.string,
+ fiatTransactionTotal: PropTypes.string,
+ hexMaximumTransactionFee: PropTypes.string,
+};
diff --git a/ui/pages/confirm-send-token/index.js b/ui/pages/confirm-send-token/index.js
index 25067ca43..3bf86d319 100644
--- a/ui/pages/confirm-send-token/index.js
+++ b/ui/pages/confirm-send-token/index.js
@@ -1 +1 @@
-export { default } from './confirm-send-token.container';
+export { default } from './confirm-send-token';
diff --git a/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js b/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js
deleted file mode 100644
index 5ab40cd65..000000000
--- a/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import { connect } from 'react-redux';
-import { compose } from 'redux';
-import { withRouter } from 'react-router-dom';
-import {
- contractExchangeRateSelector,
- transactionFeeSelector,
-} from '../../selectors';
-import { getCollectibles, getTokens } from '../../ducks/metamask/metamask';
-import { getTransactionData } from '../../helpers/utils/transactions.util';
-import {
- calcTokenAmount,
- getTokenAddressParam,
- getTokenValueParam,
-} from '../../helpers/utils/token-util';
-import { hexWEIToDecETH } from '../../helpers/utils/conversions.util';
-import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
-import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component';
-
-const mapStateToProps = (state, ownProps) => {
- const {
- match: { params = {} },
- } = ownProps;
- const { id: paramsTransactionId } = params;
- const {
- confirmTransaction,
- metamask: {
- currentCurrency,
- conversionRate,
- currentNetworkTxList,
- nativeCurrency,
- },
- } = state;
-
- const {
- txData: {
- id: transactionId,
- txParams: { to: tokenAddress, data } = {},
- } = {},
- } = confirmTransaction;
-
- const transaction =
- currentNetworkTxList.find(
- ({ id }) => id === (Number(paramsTransactionId) || transactionId),
- ) || {};
-
- const {
- ethTransactionTotal,
- fiatTransactionTotal,
- hexMaximumTransactionFee,
- } = transactionFeeSelector(state, transaction);
- const tokens = getTokens(state);
- const collectibles = getCollectibles(state);
-
- const transactionData = getTransactionData(data);
- const toAddress = getTokenAddressParam(transactionData);
- const tokenAmountOrTokenId = getTokenValueParam(transactionData);
- const ethTransactionTotalMaxAmount = Number(
- hexWEIToDecETH(hexMaximumTransactionFee),
- ).toFixed(6);
-
- const currentToken = tokens?.find(({ address }) =>
- isEqualCaseInsensitive(tokenAddress, address),
- );
- const currentCollectible = collectibles?.find(
- ({ address, tokenId }) =>
- isEqualCaseInsensitive(tokenAddress, address) &&
- tokenId === tokenAmountOrTokenId,
- );
-
- let image,
- tokenId,
- collectibleName,
- tokenAmount,
- contractExchangeRate,
- title,
- subtitle;
-
- if (currentCollectible) {
- ({ image, tokenId, name: collectibleName } = currentCollectible || {});
-
- title = collectibleName;
- subtitle = `#${tokenId}`;
- } else if (currentToken) {
- const { decimals, symbol: tokenSymbol } = currentToken || {};
- tokenAmount =
- transactionData &&
- calcTokenAmount(tokenAmountOrTokenId, decimals).toFixed();
- contractExchangeRate = contractExchangeRateSelector(state);
- title = `${tokenAmount} ${tokenSymbol}`;
- }
-
- return {
- title,
- subtitle,
- image,
- toAddress,
- tokenAddress,
- tokenAmount,
- currentCurrency,
- conversionRate,
- contractExchangeRate,
- fiatTransactionTotal,
- ethTransactionTotal,
- ethTransactionTotalMaxAmount,
- nativeCurrency,
- };
-};
-
-export default compose(
- withRouter,
- connect(mapStateToProps),
-)(ConfirmTokenTransactionBase);
diff --git a/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js b/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.js
similarity index 70%
rename from ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js
rename to ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.js
index 99f22d3c5..edacfaa8a 100644
--- a/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js
+++ b/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.js
@@ -1,6 +1,7 @@
import React, { useContext, useMemo } from 'react';
import PropTypes from 'prop-types';
import BigNumber from 'bignumber.js';
+import { useSelector } from 'react-redux';
import { I18nContext } from '../../contexts/i18n';
import ConfirmTransactionBase from '../confirm-transaction-base';
import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display';
@@ -10,26 +11,57 @@ import {
addFiat,
roundExponential,
} from '../../helpers/utils/confirm-tx.util';
-import { getWeiHexFromDecimalValue } from '../../helpers/utils/conversions.util';
-import { ETH, PRIMARY } from '../../helpers/constants/common';
+import {
+ getWeiHexFromDecimalValue,
+ hexWEIToDecETH,
+} from '../../helpers/utils/conversions.util';
+import {
+ ERC1155,
+ ERC20,
+ ERC721,
+ ETH,
+ PRIMARY,
+} from '../../helpers/constants/common';
+import {
+ contractExchangeRateSelector,
+ getCurrentCurrency,
+} from '../../selectors';
+import {
+ getConversionRate,
+ getNativeCurrency,
+} from '../../ducks/metamask/metamask';
export default function ConfirmTokenTransactionBase({
- image,
- title,
- subtitle,
+ image = '',
+ assetName,
toAddress,
tokenAddress,
tokenAmount = '0',
- fiatTransactionTotal,
- ethTransactionTotal,
- ethTransactionTotalMaxAmount,
- contractExchangeRate,
- conversionRate,
- currentCurrency,
- nativeCurrency,
+ tokenSymbol,
+ tokenId,
+ assetStandard,
onEdit,
+ ethTransactionTotal,
+ fiatTransactionTotal,
+ hexMaximumTransactionFee,
}) {
const t = useContext(I18nContext);
+ const contractExchangeRate = useSelector(contractExchangeRateSelector);
+ const nativeCurrency = useSelector(getNativeCurrency);
+ const currentCurrency = useSelector(getCurrentCurrency);
+ const conversionRate = useSelector(getConversionRate);
+
+ const ethTransactionTotalMaxAmount = Number(
+ hexWEIToDecETH(hexMaximumTransactionFee),
+ );
+
+ let title, subtitle;
+ if (assetStandard === ERC721 || assetStandard === ERC1155) {
+ title = assetName;
+ subtitle = `#${tokenId}`;
+ } else if (assetStandard === ERC20) {
+ title = `${tokenAmount} ${tokenSymbol}`;
+ }
const hexWeiValue = useMemo(() => {
if (tokenAmount === '0' || !contractExchangeRate) {
@@ -105,17 +137,15 @@ export default function ConfirmTokenTransactionBase({
ConfirmTokenTransactionBase.propTypes = {
image: PropTypes.string,
- title: PropTypes.string,
- subtitle: PropTypes.string,
- tokenAddress: PropTypes.string,
+ assetName: PropTypes.string,
toAddress: PropTypes.string,
+ tokenAddress: PropTypes.string,
tokenAmount: PropTypes.string,
- fiatTransactionTotal: PropTypes.string,
- ethTransactionTotal: PropTypes.string,
- contractExchangeRate: PropTypes.number,
- conversionRate: PropTypes.number,
- currentCurrency: PropTypes.string,
+ tokenSymbol: PropTypes.string,
+ tokenId: PropTypes.string,
+ assetStandard: PropTypes.string,
onEdit: PropTypes.func,
- nativeCurrency: PropTypes.string,
- ethTransactionTotalMaxAmount: PropTypes.string,
+ ethTransactionTotal: PropTypes.string,
+ fiatTransactionTotal: PropTypes.string,
+ hexMaximumTransactionFee: PropTypes.string,
};
diff --git a/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.stories.js b/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.stories.js
index ffe86e3ee..b1d5cf9f3 100644
--- a/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.stories.js
+++ b/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.stories.js
@@ -1,6 +1,6 @@
import React from 'react';
import { store } from '../../../.storybook/preview';
-import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component';
+import ConfirmTokenTransactionBase from './confirm-token-transaction-base';
export default {
title: 'Pages/ConfirmTokenTransactionBase',
diff --git a/ui/pages/confirm-token-transaction-base/index.js b/ui/pages/confirm-token-transaction-base/index.js
index e5b6df031..9c9fb78c4 100644
--- a/ui/pages/confirm-token-transaction-base/index.js
+++ b/ui/pages/confirm-token-transaction-base/index.js
@@ -1,2 +1 @@
-export { default } from './confirm-token-transaction-base.container';
-export { default as ConfirmTokenTransactionBase } from './confirm-token-transaction-base.component';
+export { default } from './confirm-token-transaction-base';
diff --git a/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js
index 6a2313c97..e5c325242 100644
--- a/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js
+++ b/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js
@@ -174,7 +174,7 @@ const mapStateToProps = (state, ownProps) => {
}
const isCollectibleTransfer = Boolean(
- allCollectibleContracts?.[selectedAddress]?.[chainId].find((contract) => {
+ allCollectibleContracts?.[selectedAddress]?.[chainId]?.find((contract) => {
return isEqualCaseInsensitive(contract.address, fullTxData.txParams.to);
}),
);
diff --git a/ui/pages/confirm-transaction/confirm-token-transaction-switch.js b/ui/pages/confirm-transaction/confirm-token-transaction-switch.js
new file mode 100644
index 000000000..e6a89996b
--- /dev/null
+++ b/ui/pages/confirm-transaction/confirm-token-transaction-switch.js
@@ -0,0 +1,125 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { useSelector } from 'react-redux';
+import { Switch, Route } from 'react-router-dom';
+import {
+ CONFIRM_APPROVE_PATH,
+ CONFIRM_SEND_TOKEN_PATH,
+ CONFIRM_TRANSACTION_ROUTE,
+ CONFIRM_TRANSFER_FROM_PATH,
+} from '../../helpers/constants/routes';
+import { transactionFeeSelector } from '../../selectors';
+import ConfirmApprove from '../confirm-approve';
+import ConfirmSendToken from '../confirm-send-token';
+import ConfirmTokenTransactionBase from '../confirm-token-transaction-base';
+import ConfirmTransactionSwitch from '../confirm-transaction-switch';
+
+import { useAssetDetails } from '../../hooks/useAssetDetails';
+
+export default function ConfirmTokenTransactionSwitch({ transaction }) {
+ const {
+ txParams: { data, to: tokenAddress, from: userAddress } = {},
+ } = transaction;
+
+ const {
+ assetStandard,
+ assetName,
+ userBalance,
+ tokenSymbol,
+ decimals,
+ tokenImage,
+ tokenAmount,
+ tokenId,
+ toAddress,
+ } = useAssetDetails(tokenAddress, userAddress, data);
+
+ const {
+ ethTransactionTotal,
+ fiatTransactionTotal,
+ hexTransactionTotal,
+ hexMaximumTransactionFee,
+ } = useSelector((state) => transactionFeeSelector(state, transaction));
+
+ return (
+
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+
+
+ );
+}
+
+ConfirmTokenTransactionSwitch.propTypes = {
+ transaction: PropTypes.shape({
+ origin: PropTypes.string,
+ txParams: PropTypes.shape({
+ data: PropTypes.string,
+ to: PropTypes.string,
+ from: PropTypes.string,
+ }),
+ }),
+};
diff --git a/ui/pages/confirm-transaction/confirm-transaction.component.js b/ui/pages/confirm-transaction/confirm-transaction.component.js
index d28904544..01e876fdb 100644
--- a/ui/pages/confirm-transaction/confirm-transaction.component.js
+++ b/ui/pages/confirm-transaction/confirm-transaction.component.js
@@ -5,10 +5,7 @@ import Loading from '../../components/ui/loading-screen';
import ConfirmTransactionSwitch from '../confirm-transaction-switch';
import ConfirmTransactionBase from '../confirm-transaction-base';
import ConfirmSendEther from '../confirm-send-ether';
-import ConfirmSendToken from '../confirm-send-token';
import ConfirmDeployContract from '../confirm-deploy-contract';
-import ConfirmApprove from '../confirm-approve';
-import ConfirmTokenTransactionBaseContainer from '../confirm-token-transaction-base';
import ConfirmDecryptMessage from '../confirm-decrypt-message';
import ConfirmEncryptionPublicKey from '../confirm-encryption-public-key';
@@ -16,9 +13,6 @@ import {
CONFIRM_TRANSACTION_ROUTE,
CONFIRM_DEPLOY_CONTRACT_PATH,
CONFIRM_SEND_ETHER_PATH,
- CONFIRM_SEND_TOKEN_PATH,
- CONFIRM_APPROVE_PATH,
- CONFIRM_TRANSFER_FROM_PATH,
CONFIRM_TOKEN_METHOD_PATH,
SIGNATURE_REQUEST_PATH,
DECRYPT_MESSAGE_REQUEST_PATH,
@@ -31,6 +25,7 @@ import {
addPollingTokenToAppState,
removePollingTokenFromAppState,
} from '../../store/actions';
+import ConfirmTokenTransactionSwitch from './confirm-token-transaction-switch';
import ConfTx from './conf-tx';
export default class ConfirmTransaction extends Component {
@@ -49,7 +44,6 @@ export default class ConfirmTransaction extends Component {
getContractMethodData: PropTypes.func,
transactionId: PropTypes.string,
paramsTransactionId: PropTypes.string,
- getTokenParams: PropTypes.func,
isTokenMethodAction: PropTypes.bool,
setDefaultHomeActiveTabName: PropTypes.func,
};
@@ -74,12 +68,10 @@ export default class ConfirmTransaction extends Component {
sendTo,
history,
mostRecentOverviewPage,
- transaction: { txParams: { data, to } = {} } = {},
+ transaction: { txParams: { data } = {} } = {},
getContractMethodData,
transactionId,
paramsTransactionId,
- getTokenParams,
- isTokenMethodAction,
} = this.props;
getGasFeeEstimatesAndStartPolling().then((pollingToken) => {
@@ -100,9 +92,7 @@ export default class ConfirmTransaction extends Component {
}
getContractMethodData(data);
- if (isTokenMethodAction) {
- getTokenParams(to);
- }
+
const txId = transactionId || paramsTransactionId;
if (txId) {
this.props.setTransactionToConfirm(txId);
@@ -154,23 +144,30 @@ export default class ConfirmTransaction extends Component {
}
render() {
- const { transactionId, paramsTransactionId } = this.props;
+ const {
+ transactionId,
+ paramsTransactionId,
+ isTokenMethodAction,
+ transaction,
+ } = this.props;
+
+ const validTransactionId =
+ transactionId &&
+ (!paramsTransactionId || paramsTransactionId === transactionId);
+
+ if (isTokenMethodAction && validTransactionId) {
+ return ;
+ }
// Show routes when state.confirmTransaction has been set and when either the ID in the params
// isn't specified or is specified and matches the ID in state.confirmTransaction in order to
// support URLs of /confirm-transaction or /confirm-transaction/
- return transactionId &&
- (!paramsTransactionId || paramsTransactionId === transactionId) ? (
+ return validTransactionId ? (
-
-
-
{
},
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
getContractMethodData: (data) => dispatch(getContractMethodData(data)),
- getTokenParams: (tokenAddress) => dispatch(getTokenParams(tokenAddress)),
setDefaultHomeActiveTabName: (tabName) =>
dispatch(setDefaultHomeActiveTabName(tabName)),
};
diff --git a/ui/store/actions.js b/ui/store/actions.js
index 6d504bca6..698508883 100644
--- a/ui/store/actions.js
+++ b/ui/store/actions.js
@@ -8,7 +8,6 @@ import {
loadRelativeTimeFormatLocaleData,
} from '../helpers/utils/i18n-helper';
import { getMethodDataAsync } from '../helpers/utils/transactions.util';
-import { getSymbolAndDecimals } from '../helpers/utils/token-util';
import switchDirection from '../helpers/utils/switch-direction';
import {
ENVIRONMENT_TYPE_NOTIFICATION,
@@ -22,7 +21,6 @@ import {
getMetaMaskAccounts,
getPermittedAccountsForCurrentTab,
getSelectedAddress,
- getTokenList,
} from '../selectors';
import { computeEstimatedGasLimit, resetSendState } from '../ducks/send';
import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account';
@@ -2871,46 +2869,6 @@ export function loadingTokenParamsFinished() {
};
}
-export function getTokenParams(address) {
- return (dispatch, getState) => {
- const tokenList = getTokenList(getState());
- const existingTokens = getState().metamask.tokens;
- const { selectedAddress } = getState().metamask;
- const { chainId } = getState().metamask.provider;
- const existingCollectibles = getState().metamask?.allCollectibles?.[
- selectedAddress
- ]?.[chainId];
- const existingToken = existingTokens.find(({ address: tokenAddress }) =>
- isEqualCaseInsensitive(address, tokenAddress),
- );
- const existingCollectible = existingCollectibles?.find(
- ({ address: collectibleAddress }) =>
- isEqualCaseInsensitive(address, collectibleAddress),
- );
-
- if (existingCollectible) {
- return null;
- }
-
- if (existingToken) {
- return Promise.resolve({
- symbol: existingToken.symbol,
- decimals: existingToken.decimals,
- });
- }
-
- dispatch(loadingTokenParamsStarted());
- log.debug(`loadingTokenParams`);
-
- return getSymbolAndDecimals(address, tokenList).then(
- ({ symbol, decimals }) => {
- dispatch(addToken(address, symbol, Number(decimals)));
- dispatch(loadingTokenParamsFinished());
- },
- );
- };
-}
-
export function setSeedPhraseBackedUp(seedPhraseBackupState) {
return (dispatch) => {
log.debug(`background.setSeedPhraseBackedUp`);