diff --git a/ui/ducks/metamask/metamask.js b/ui/ducks/metamask/metamask.js
index 63ff92a11ccc..67f2764af3a4 100644
--- a/ui/ducks/metamask/metamask.js
+++ b/ui/ducks/metamask/metamask.js
@@ -338,6 +338,15 @@ export const getNfts = (state) => {
return allNfts?.[selectedAddress]?.[chainId] ?? [];
};
+export const getNFTsByChainId = (state, chainId) => {
+ const {
+ metamask: { allNfts },
+ } = state;
+ const { address: selectedAddress } = getSelectedInternalAccount(state);
+
+ return allNfts?.[selectedAddress]?.[chainId] ?? [];
+};
+
export const getNftContracts = (state) => {
const {
metamask: { allNftContracts },
diff --git a/ui/pages/confirmations/components/confirm/info/approve/approve-static-simulation/approve-static-simulation.tsx b/ui/pages/confirmations/components/confirm/info/approve/approve-static-simulation/approve-static-simulation.tsx
index c860556a359a..8d66b17a1f46 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/approve-static-simulation/approve-static-simulation.tsx
+++ b/ui/pages/confirmations/components/confirm/info/approve/approve-static-simulation/approve-static-simulation.tsx
@@ -14,7 +14,6 @@ import {
TextAlign,
} from '../../../../../../../helpers/constants/design-system';
import { useI18nContext } from '../../../../../../../hooks/useI18nContext';
-import { SPENDING_CAP_UNLIMITED_MSG } from '../../../../../constants';
import { useConfirmContext } from '../../../../../context/confirm';
import { useAssetDetails } from '../../../../../hooks/useAssetDetails';
import StaticSimulation from '../../shared/static-simulation/static-simulation';
@@ -37,8 +36,13 @@ export const ApproveStaticSimulation = () => {
const decimals = initialDecimals || '0';
- const { spendingCap, formattedSpendingCap, value, pending } =
- useApproveTokenSimulation(transactionMeta, decimals);
+ const {
+ spendingCap,
+ isUnlimitedSpendingCap,
+ formattedSpendingCap,
+ value,
+ pending,
+ } = useApproveTokenSimulation(transactionMeta, decimals);
const { isNFT } = useIsNFT(transactionMeta);
@@ -61,9 +65,7 @@ export const ApproveStaticSimulation = () => {
textAlign={TextAlign.Center}
alignItems={AlignItems.center}
>
- {spendingCap === SPENDING_CAP_UNLIMITED_MSG
- ? t('unlimited')
- : spendingCap}
+ {isUnlimitedSpendingCap ? t('unlimited') : formattedSpendingCap}
);
@@ -78,10 +80,9 @@ export const ApproveStaticSimulation = () => {
marginInlineEnd={1}
minWidth={BlockSize.Zero}
>
- {spendingCap === SPENDING_CAP_UNLIMITED_MSG ? (
-
- {formattedTokenText}
-
+ {Boolean(isUnlimitedSpendingCap) ||
+ spendingCap !== formattedSpendingCap ? (
+ {formattedTokenText}
) : (
formattedTokenText
)}
diff --git a/ui/pages/confirmations/components/confirm/info/approve/edit-spending-cap-modal/edit-spending-cap-modal.tsx b/ui/pages/confirmations/components/confirm/info/approve/edit-spending-cap-modal/edit-spending-cap-modal.tsx
index 1eb0ac2cde05..1cd080de96d4 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/edit-spending-cap-modal/edit-spending-cap-modal.tsx
+++ b/ui/pages/confirmations/components/confirm/info/approve/edit-spending-cap-modal/edit-spending-cap-modal.tsx
@@ -62,41 +62,38 @@ export const EditSpendingCapModal = ({
Number(decimals ?? '0'),
).toFixed();
- const { formattedSpendingCap } = useApproveTokenSimulation(
+ const { formattedSpendingCap, spendingCap } = useApproveTokenSimulation(
transactionMeta,
decimals || '0',
);
const [customSpendingCapInputValue, setCustomSpendingCapInputValue] =
- useState(formattedSpendingCap.toString());
+ useState(spendingCap);
useEffect(() => {
- if (formattedSpendingCap) {
- setCustomSpendingCapInputValue(formattedSpendingCap.toString());
+ if (spendingCap) {
+ setCustomSpendingCapInputValue(spendingCap);
}
- }, [formattedSpendingCap]);
+ }, [spendingCap]);
const handleCancel = useCallback(() => {
setIsOpenEditSpendingCapModal(false);
- setCustomSpendingCapInputValue(formattedSpendingCap.toString());
+ setCustomSpendingCapInputValue(spendingCap);
}, [
setIsOpenEditSpendingCapModal,
setCustomSpendingCapInputValue,
- formattedSpendingCap,
+ spendingCap,
]);
const [isModalSaving, setIsModalSaving] = useState(false);
const handleSubmit = useCallback(async () => {
setIsModalSaving(true);
- const parsedValue = parseInt(String(customSpendingCapInputValue), 10);
const customTxParamsData = getCustomTxParamsData(
transactionMeta?.txParams?.data,
{
- customPermissionAmount:
- // coerce negative numbers to zero
- parsedValue < 0 ? '0' : customSpendingCapInputValue || '0',
+ customPermissionAmount: customSpendingCapInputValue || '0',
decimals: decimals || '0',
},
);
@@ -117,8 +114,8 @@ export const EditSpendingCapModal = ({
setIsModalSaving(false);
setIsOpenEditSpendingCapModal(false);
- setCustomSpendingCapInputValue(formattedSpendingCap.toString());
- }, [customSpendingCapInputValue, formattedSpendingCap]);
+ setCustomSpendingCapInputValue(spendingCap);
+ }, [customSpendingCapInputValue, spendingCap]);
const showDecimalError =
decimals &&
diff --git a/ui/pages/confirmations/components/confirm/info/approve/hooks/use-approve-token-simulation.test.ts b/ui/pages/confirmations/components/confirm/info/approve/hooks/use-approve-token-simulation.test.ts
index 0178e2ffff62..e0a5a8165dfb 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/hooks/use-approve-token-simulation.test.ts
+++ b/ui/pages/confirmations/components/confirm/info/approve/hooks/use-approve-token-simulation.test.ts
@@ -65,7 +65,8 @@ describe('useApproveTokenSimulation', () => {
expect(result.current).toMatchInlineSnapshot(`
{
- "formattedSpendingCap": "7",
+ "formattedSpendingCap": "#7",
+ "isUnlimitedSpendingCap": false,
"pending": undefined,
"spendingCap": "#7",
"value": {
@@ -132,8 +133,9 @@ describe('useApproveTokenSimulation', () => {
expect(result.current).toMatchInlineSnapshot(`
{
"formattedSpendingCap": "1,000,000,000,000,000",
+ "isUnlimitedSpendingCap": true,
"pending": undefined,
- "spendingCap": "UNLIMITED MESSAGE",
+ "spendingCap": "1000000000000000",
"value": {
"data": [
{
@@ -197,7 +199,8 @@ describe('useApproveTokenSimulation', () => {
expect(result.current).toMatchInlineSnapshot(`
{
- "formattedSpendingCap": "0.0000000000001",
+ "formattedSpendingCap": "<0.000001",
+ "isUnlimitedSpendingCap": false,
"pending": undefined,
"spendingCap": "0.0000000000001",
"value": {
diff --git a/ui/pages/confirmations/components/confirm/info/approve/hooks/use-approve-token-simulation.ts b/ui/pages/confirmations/components/confirm/info/approve/hooks/use-approve-token-simulation.ts
index 8a95fdc3e35b..4944effcd17b 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/hooks/use-approve-token-simulation.ts
+++ b/ui/pages/confirmations/components/confirm/info/approve/hooks/use-approve-token-simulation.ts
@@ -1,11 +1,12 @@
import { TransactionMeta } from '@metamask/transaction-controller';
import { isHexString } from '@metamask/utils';
+import BigNumber from 'bignumber.js';
import { isBoolean } from 'lodash';
import { useMemo } from 'react';
import { useSelector } from 'react-redux';
import { calcTokenAmount } from '../../../../../../../../shared/lib/transactions-controller-utils';
import { getIntlLocale } from '../../../../../../../ducks/locale/locale';
-import { SPENDING_CAP_UNLIMITED_MSG } from '../../../../../constants';
+import { formatAmount } from '../../../../simulation-details/formatAmount';
import { useDecodedTransactionData } from '../../hooks/useDecodedTransactionData';
import { useIsNFT } from './use-is-nft';
@@ -46,22 +47,26 @@ export const useApproveTokenSimulation = (
).toFixed();
}, [value, decimals]);
+ const tokenPrefix = isNFT ? '#' : '';
+
const formattedSpendingCap = useMemo(() => {
- // formatting coerces small numbers to 0
- return isNFT || parseInt(decodedSpendingCap, 10) < 1
- ? decodedSpendingCap
- : new Intl.NumberFormat(locale).format(parseInt(decodedSpendingCap, 10));
+ return isNFT
+ ? `${tokenPrefix}${decodedSpendingCap}`
+ : formatAmount(locale, new BigNumber(decodedSpendingCap));
}, [decodedSpendingCap, isNFT, locale]);
- const spendingCap = useMemo(() => {
+ const { spendingCap, isUnlimitedSpendingCap } = useMemo(() => {
if (!isNFT && isSpendingCapUnlimited(parseInt(decodedSpendingCap, 10))) {
- return SPENDING_CAP_UNLIMITED_MSG;
+ return { spendingCap: decodedSpendingCap, isUnlimitedSpendingCap: true };
}
- const tokenPrefix = isNFT ? '#' : '';
- return `${tokenPrefix}${formattedSpendingCap}`;
+ return {
+ spendingCap: `${tokenPrefix}${decodedSpendingCap}`,
+ isUnlimitedSpendingCap: false,
+ };
}, [decodedSpendingCap, formattedSpendingCap, isNFT]);
return {
+ isUnlimitedSpendingCap,
spendingCap,
formattedSpendingCap,
value,
diff --git a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx
index 8e7b522f050a..29d009c5b810 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx
+++ b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx
@@ -9,7 +9,6 @@ import {
import { ConfirmInfoSection } from '../../../../../../../components/app/confirm/info/row/section';
import Tooltip from '../../../../../../../components/ui/tooltip';
import { useI18nContext } from '../../../../../../../hooks/useI18nContext';
-import { SPENDING_CAP_UNLIMITED_MSG } from '../../../../../constants';
import { useConfirmContext } from '../../../../../context/confirm';
import { useAssetDetails } from '../../../../../hooks/useAssetDetails';
import { Container } from '../../shared/transaction-data/transaction-data';
@@ -19,30 +18,25 @@ const SpendingCapGroup = ({
tokenSymbol,
decimals,
setIsOpenEditSpendingCapModal,
- customSpendingCap,
}: {
tokenSymbol: string;
decimals: string;
setIsOpenEditSpendingCapModal: (newValue: boolean) => void;
- customSpendingCap: string;
}) => {
const t = useI18nContext();
const { currentConfirmation: transactionMeta } =
useConfirmContext();
- const { spendingCap, formattedSpendingCap, value } =
+ const { spendingCap, isUnlimitedSpendingCap, formattedSpendingCap, value } =
useApproveTokenSimulation(transactionMeta, decimals);
- const spendingCapValue =
- customSpendingCap === '' ? formattedSpendingCap : customSpendingCap;
-
const SpendingCapElement = (
setIsOpenEditSpendingCapModal(true)}
editIconClassName="edit-spending-cap-btn"
@@ -63,8 +57,9 @@ const SpendingCapGroup = ({
tooltip={t('spendingCapTooltipDesc')}
data-testid="confirmation__approve-spending-cap-group"
>
- {spendingCap === SPENDING_CAP_UNLIMITED_MSG ? (
- {SpendingCapElement}
+ {Boolean(isUnlimitedSpendingCap) ||
+ spendingCap !== formattedSpendingCap ? (
+ {SpendingCapElement}
) : (
SpendingCapElement
)}
@@ -95,7 +90,7 @@ export const SpendingCap = ({
Number(decimals ?? '0'),
).toFixed();
- const { pending, spendingCap } = useApproveTokenSimulation(
+ const { pending } = useApproveTokenSimulation(
transactionMeta,
decimals || '0',
);
@@ -114,7 +109,6 @@ export const SpendingCap = ({
tokenSymbol={tokenSymbol || ''}
decimals={decimals || '0'}
setIsOpenEditSpendingCapModal={setIsOpenEditSpendingCapModal}
- customSpendingCap={spendingCap}
/>
);
diff --git a/ui/pages/confirmations/components/confirm/info/native-transfer/__snapshots__/native-transfer.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/native-transfer/__snapshots__/native-transfer.test.tsx.snap
index a17a5f37578a..7a488072fd42 100644
--- a/ui/pages/confirmations/components/confirm/info/native-transfer/__snapshots__/native-transfer.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/native-transfer/__snapshots__/native-transfer.test.tsx.snap
@@ -6,7 +6,7 @@ exports[`NativeTransferInfo renders correctly 1`] = `
class="mm-box mm-box--padding-4 mm-box--display-flex mm-box--flex-direction-column mm-box--justify-content-center mm-box--align-items-center"
>
G
diff --git a/ui/pages/confirmations/components/confirm/info/nft-token-transfer/__snapshots__/nft-token-transfer.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/nft-token-transfer/__snapshots__/nft-token-transfer.test.tsx.snap
index ca9af0539f6e..3ff774c6770b 100644
--- a/ui/pages/confirmations/components/confirm/info/nft-token-transfer/__snapshots__/nft-token-transfer.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/nft-token-transfer/__snapshots__/nft-token-transfer.test.tsx.snap
@@ -6,16 +6,43 @@ exports[`NFTTokenTransferInfo renders correctly 1`] = `
class="mm-box mm-box--padding-4 mm-box--display-flex mm-box--flex-direction-column mm-box--justify-content-center mm-box--align-items-center"
>
+ >
+ #undefined
+
{
const { currentConfirmation: transactionMeta } =
useConfirmContext
();
- const isWalletInitiated = transactionMeta.origin === 'metamask';
+ // const isWalletInitiated = transactionMeta.origin === 'metamask';
+ const isWalletInitiated = false;
return (
<>
diff --git a/ui/pages/confirmations/components/confirm/info/shared/native-send-heading/native-send-heading.tsx b/ui/pages/confirmations/components/confirm/info/shared/native-send-heading/native-send-heading.tsx
index 486ba863f92d..f3f1f292fa2e 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/native-send-heading/native-send-heading.tsx
+++ b/ui/pages/confirmations/components/confirm/info/shared/native-send-heading/native-send-heading.tsx
@@ -17,6 +17,7 @@ import Tooltip from '../../../../../../../components/ui/tooltip';
import { getIntlLocale } from '../../../../../../../ducks/locale/locale';
import {
AlignItems,
+ BackgroundColor,
Display,
FlexDirection,
JustifyContent,
@@ -81,6 +82,7 @@ const NativeSendHeading = () => {
}
name={multichainNetwork?.nickname}
size={AvatarTokenSize.Xl}
+ backgroundColor={BackgroundColor.backgroundDefault}
/>
);
diff --git a/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/__snapshots__/nft-send-heading.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/__snapshots__/nft-send-heading.test.tsx.snap
index 2e98c4e5ce13..5559f00fa01f 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/__snapshots__/nft-send-heading.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/__snapshots__/nft-send-heading.test.tsx.snap
@@ -6,16 +6,43 @@ exports[` renders component 1`] = `
class="mm-box mm-box--padding-4 mm-box--display-flex mm-box--flex-direction-column mm-box--justify-content-center mm-box--align-items-center"
>
+ >
+ #undefined
+
`;
diff --git a/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/nft-send-heading.tsx b/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/nft-send-heading.tsx
index 2f36d10ce42c..405236fe66da 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/nft-send-heading.tsx
+++ b/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/nft-send-heading.tsx
@@ -1,19 +1,23 @@
+import { Nft } from '@metamask/assets-controllers';
import { TransactionMeta } from '@metamask/transaction-controller';
import React from 'react';
-import {
- AvatarToken,
- AvatarTokenSize,
- Box,
- Text,
-} from '../../../../../../../components/component-library';
+import { useSelector } from 'react-redux';
+import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../../../../../shared/constants/network';
+import { isEqualCaseInsensitive } from '../../../../../../../../shared/modules/string-utils';
+import { Box, Text } from '../../../../../../../components/component-library';
+import { NftItem } from '../../../../../../../components/multichain/nft-item';
+import { getNFTsByChainId } from '../../../../../../../ducks/metamask/metamask';
import {
AlignItems,
Display,
FlexDirection,
JustifyContent,
+ TextAlign,
TextColor,
TextVariant,
} from '../../../../../../../helpers/constants/design-system';
+import { getNftImageAlt } from '../../../../../../../helpers/utils/nfts';
+import { getNetworkConfigurationsByChainId } from '../../../../../../../selectors';
import { useConfirmContext } from '../../../../../context/confirm';
import { useAssetDetails } from '../../../../../hooks/useAssetDetails';
@@ -25,21 +29,53 @@ const NFTSendHeading = () => {
const userAddress = transactionMeta.txParams.from;
const { data } = transactionMeta.txParams;
const { chainId } = transactionMeta;
+ const {
+ assetName,
+ tokenImage,
+ tokenId: assetTokenId,
+ } = useAssetDetails(tokenAddress, userAddress, data, chainId);
+ const nfts: Nft[] = useSelector((state) =>
+ getNFTsByChainId(state, chainId),
+ ) as Nft[];
+ const networkConfigurations = useSelector(getNetworkConfigurationsByChainId);
+ const nft: Nft | undefined =
+ assetTokenId &&
+ nfts.find(
+ ({ address, tokenId }: Nft) =>
+ isEqualCaseInsensitive(address, tokenAddress as string) &&
+ assetTokenId === tokenId.toString(),
+ );
+ const imageOriginal = (nft as Nft | undefined)?.imageOriginal;
+ const image = (nft as Nft | undefined)?.image;
+ const nftImageAlt = nft && getNftImageAlt(nft);
+ const nftSrcUrl = imageOriginal ?? (image || '');
+ const isIpfsURL = nftSrcUrl?.startsWith('ipfs:');
+ const currentChain = networkConfigurations[chainId];
- const { assetName, tokenImage, tokenId } = useAssetDetails(
- tokenAddress,
- userAddress,
- data,
- chainId,
+ const TokenImage = (
+
+
+
);
- const TokenImage = ;
-
const TokenName = (
{assetName}
@@ -47,7 +83,7 @@ const NFTSendHeading = () => {
const TokenID = (
- {tokenId}
+ {`#${assetTokenId}`}
);