diff --git a/test/data/confirmations/typed_sign.ts b/test/data/confirmations/typed_sign.ts
index 86067ef1f117..88985e1a52a7 100644
--- a/test/data/confirmations/typed_sign.ts
+++ b/test/data/confirmations/typed_sign.ts
@@ -176,3 +176,41 @@ export const permitSignatureMsg = {
origin: 'https://metamask.github.io',
},
} as SignatureRequestType;
+
+export const permitBatchSignatureMsg = {
+ id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659',
+ securityAlertResponse: {
+ reason: 'loading',
+ result_type: 'validation_in_progress',
+ securityAlertId: 'ab21395f-2190-472f-8cfa-3d224e7529d8',
+ },
+ status: 'unapproved',
+ time: 1716826404122,
+ type: 'eth_signTypedData',
+ msgParams: {
+ data: '{"types":{"PermitBatch":[{"name":"details","type":"PermitDetails[]"},{"name":"spender","type":"address"},{"name":"sigDeadline","type":"uint256"}],"PermitDetails":[{"name":"token","type":"address"},{"name":"amount","type":"uint160"},{"name":"expiration","type":"uint48"},{"name":"nonce","type":"uint48"}],"EIP712Domain":[{"name":"name","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}]},"domain":{"name":"Permit2","chainId":"1","verifyingContract":"0x000000000022d473030f116ddee9f6b43ac78ba3"},"primaryType":"PermitBatch","message":{"details":[{"token":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","amount":"1461501637330902918203684832716283019655932542975","expiration":"1722887542","nonce":"5"},{"token":"0xb0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","amount":"2461501637330902918203684832716283019655932542975","expiration":"1722887642","nonce":"6"}],"spender":"0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad","sigDeadline":"1720297342"}}',
+ from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
+ version: 'V4',
+ signatureMethod: 'eth_signTypedData_v4',
+ origin: 'https://metamask.github.io',
+ },
+} as SignatureRequestType;
+
+export const permitSingleSignatureMsg = {
+ id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659',
+ securityAlertResponse: {
+ reason: 'loading',
+ result_type: 'validation_in_progress',
+ securityAlertId: 'ab21395f-2190-472f-8cfa-3d224e7529d8',
+ },
+ status: 'unapproved',
+ time: 1716826404122,
+ type: 'eth_signTypedData',
+ msgParams: {
+ data: '{"types":{"PermitSingle":[{"name":"details","type":"PermitDetails"},{"name":"spender","type":"address"},{"name":"sigDeadline","type":"uint256"}],"PermitDetails":[{"name":"token","type":"address"},{"name":"amount","type":"uint160"},{"name":"expiration","type":"uint48"},{"name":"nonce","type":"uint48"}],"EIP712Domain":[{"name":"name","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}]},"domain":{"name":"Permit2","chainId":"1","verifyingContract":"0x000000000022d473030f116ddee9f6b43ac78ba3"},"primaryType":"PermitSingle","message":{"details":{"token":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","amount":"1461501637330902918203684832716283019655932542975","expiration":"1722887542","nonce":"5"},"spender":"0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad","sigDeadline":"1720297342"}}',
+ from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
+ version: 'V4',
+ signatureMethod: 'eth_signTypedData_v4',
+ origin: 'https://metamask.github.io',
+ },
+} as SignatureRequestType;
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/__snapshots__/typed-sign.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/typed-sign/__snapshots__/typed-sign.test.tsx.snap
index ebe7d746b36f..7b20ba3e9ddc 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/__snapshots__/typed-sign.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/__snapshots__/typed-sign.test.tsx.snap
@@ -65,51 +65,55 @@ exports[`TypedSignInfo correctly renders permit sign type 1`] = `
style="margin-left: auto; max-width: 100%;"
>
-
- 3,000
-
+
+ 3,000
+
+
-
-
-
-
-
+
- 0xCcCCc...ccccC
-
+
+
+ 0xCcCCc...ccccC
+
+
+
-
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap
index 7e101a53d2f5..792adfd2975f 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/__snapshots__/permit-simulation.test.tsx.snap
@@ -65,51 +65,55 @@ exports[`PermitSimulation renders component correctly 1`] = `
style="margin-left: auto; max-width: 100%;"
>
-
-
-
-
+
- 0xCcCCc...ccccC
-
+
+
+ 0xCcCCc...ccccC
+
+
+
-
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx
index bb86010ce07a..46c3212fb997 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx
@@ -1,19 +1,31 @@
import React from 'react';
import configureMockStore from 'redux-mock-store';
+import { act } from 'react-dom/test-utils';
import { getMockTypedSignConfirmStateForRequest } from '../../../../../../../../test/data/confirmations/helper';
import { renderWithConfirmContextProvider } from '../../../../../../../../test/lib/confirmations/render-helpers';
import { permitSignatureMsg } from '../../../../../../../../test/data/confirmations/typed_sign';
import PermitSimulation from './permit-simulation';
+jest.mock('../../../../../../../store/actions', () => {
+ return {
+ getTokenStandardAndDetails: jest.fn().mockResolvedValue({ decimals: 2 }),
+ };
+});
+
describe('PermitSimulation', () => {
- it('renders component correctly', () => {
+ it('renders component correctly', async () => {
const state = getMockTypedSignConfirmStateForRequest(permitSignatureMsg);
const mockStore = configureMockStore([])(state);
- const { container } = renderWithConfirmContextProvider(
- ,
- mockStore,
- );
- expect(container).toMatchSnapshot();
+
+ await act(async () => {
+ const { container, findByText } = renderWithConfirmContextProvider(
+ ,
+ mockStore,
+ );
+
+ expect(await findByText('30')).toBeInTheDocument();
+ expect(container).toMatchSnapshot();
+ });
});
});
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx
index b1551b2def14..98f41f72dda9 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx
@@ -1,65 +1,56 @@
-import { NameType } from '@metamask/name-controller';
-import React, { useMemo } from 'react';
+import React from 'react';
-import { calcTokenAmount } from '../../../../../../../../shared/lib/transactions-controller-utils';
+import { Box } from '../../../../../../../components/component-library';
+import { PrimaryType } from '../../../../../../../../shared/constants/signatures';
import { parseTypedDataMessage } from '../../../../../../../../shared/modules/transaction.utils';
-import useTokenExchangeRate from '../../../../../../../components/app/currency-input/hooks/useTokenExchangeRate';
-import Name from '../../../../../../../components/app/name/name';
-import { Box, Text } from '../../../../../../../components/component-library';
-import Tooltip from '../../../../../../../components/ui/tooltip';
import {
- BackgroundColor,
- BlockSize,
- BorderRadius,
Display,
- TextAlign,
+ FlexDirection,
} from '../../../../../../../helpers/constants/design-system';
-import { shortenString } from '../../../../../../../helpers/utils/util';
import { useI18nContext } from '../../../../../../../hooks/useI18nContext';
import { SignatureRequestType } from '../../../../../types/confirm';
import { useConfirmContext } from '../../../../../context/confirm';
-import { IndividualFiatDisplay } from '../../../../simulation-details/fiat-display';
-import {
- formatAmount,
- formatAmountMaxPrecision,
-} from '../../../../simulation-details/formatAmount';
import StaticSimulation from '../../shared/static-simulation/static-simulation';
+import PermitSimulationValueDisplay from './value-display/value-display';
+
+function extractTokenDetailsByPrimaryType(
+ message: Record,
+ primaryType: PrimaryType,
+): object[] | unknown {
+ let tokenDetails;
+
+ switch (primaryType) {
+ case PrimaryType.PermitBatch:
+ case PrimaryType.PermitSingle:
+ tokenDetails = message?.details;
+ break;
+ case PrimaryType.PermitBatchTransferFrom:
+ case PrimaryType.PermitTransferFrom:
+ tokenDetails = message?.permitted;
+ break;
+ default:
+ break;
+ }
+
+ const isNonArrayObject = tokenDetails && !Array.isArray(tokenDetails);
+
+ return isNonArrayObject ? [tokenDetails] : tokenDetails;
+}
-const PermitSimulation: React.FC<{
- tokenDecimals: number;
-}> = ({ tokenDecimals }) => {
+const PermitSimulation: React.FC