From bb39806d87ca8004e1bdfda84df81d79b0764126 Mon Sep 17 00:00:00 2001
From: Jyoti Puri
Date: Tue, 2 Jul 2024 20:09:18 +0530
Subject: [PATCH] fix: decimal places displayed on token value on permit pages
(#25410)
---
.../confirmations/signatures/permit.spec.ts | 2 +-
.../__snapshots__/typed-sign.test.tsx.snap | 2 +-
.../permit-simulation.test.tsx.snap | 2 +-
.../permit-simulation.test.tsx | 5 +-
.../permit-simulation/permit-simulation.tsx | 10 +++-
.../info/typed-sign/typed-sign.test.tsx | 6 +++
.../confirm/info/typed-sign/typed-sign.tsx | 21 ++++++++-
.../components/confirm/row/dataTree.tsx | 24 +++++++++-
.../row/typed-sign-data/typedSignData.tsx | 11 +++--
.../components/confirm/utils.test.ts | 46 +++++++++++--------
.../confirmations/components/confirm/utils.ts | 11 +++++
11 files changed, 110 insertions(+), 30 deletions(-)
diff --git a/test/e2e/tests/confirmations/signatures/permit.spec.ts b/test/e2e/tests/confirmations/signatures/permit.spec.ts
index 8320fd748f63..03941dbecc3f 100644
--- a/test/e2e/tests/confirmations/signatures/permit.spec.ts
+++ b/test/e2e/tests/confirmations/signatures/permit.spec.ts
@@ -83,7 +83,7 @@ async function assertInfoValues(driver: Driver) {
css: '.name__value',
text: '0x5B38D...eddC4',
});
- const value = driver.findElement({ text: '3000' });
+ const value = driver.findElement({ text: '3,000' });
const nonce = driver.findElement({ text: '0' });
const deadline = driver.findElement({ text: '02 August 1971, 16:53' });
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 328fe4209390..c06db18f9268 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
@@ -401,7 +401,7 @@ exports[`TypedSignInfo correctly renders permit sign type 1`] = `
class="mm-box mm-text mm-text--body-md mm-box--color-inherit"
style="white-space: pre-wrap;"
>
- 3000
+ 3,000
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 111bc553477f..9b67671cbb06 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
@@ -70,7 +70,7 @@ exports[`PermitSimulation renders component correctly 1`] = `
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 ea0ffcc47bc1..daca28ece848 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
@@ -15,7 +15,10 @@ describe('PermitSimulation', () => {
},
};
const mockStore = configureMockStore([])(state);
- const { container } = renderWithProvider(
, mockStore);
+ const { container } = renderWithProvider(
+
,
+ mockStore,
+ );
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 04eaba8f9be4..f6a116b0842e 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
@@ -21,9 +21,12 @@ import {
import { SignatureRequestType } from '../../../../../types/confirm';
import useTokenExchangeRate from '../../../../../../../components/app/currency-input/hooks/useTokenExchangeRate';
import { IndividualFiatDisplay } from '../../../../simulation-details/fiat-display';
+import { formatNumber } from '../../../utils';
import { ConfirmInfoSection } from '../../../../../../../components/app/confirm/info/row/section';
-const PermitSimulation: React.FC = () => {
+const PermitSimulation: React.FC<{
+ tokenDecimals: number;
+}> = ({ tokenDecimals }) => {
const t = useI18nContext();
const currentConfirmation = useSelector(
currentConfirmationSelector,
@@ -61,7 +64,10 @@ const PermitSimulation: React.FC = () => {
paddingInline={2}
textAlign={TextAlign.Center}
>
- {value}
+ {formatNumber(
+ value / Math.pow(10, tokenDecimals),
+ tokenDecimals,
+ )}
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx
index 332b3f79a6ff..1ac473dd40f8 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx
@@ -10,6 +10,12 @@ import {
} from '../../../../../../../test/data/confirmations/typed_sign';
import TypedSignInfo from './typed-sign';
+jest.mock('../../../../../../store/actions', () => {
+ return {
+ getTokenStandardAndDetails: jest.fn().mockResolvedValue({ decimals: 2 }),
+ };
+});
+
describe('TypedSignInfo', () => {
it('renders origin for typed sign data request', () => {
const state = {
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx
index 019dd138f401..88ade5cc2a6f 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { isValidAddress } from 'ethereumjs-util';
@@ -11,6 +11,7 @@ import {
} from '../../../../../../components/app/confirm/info/row';
import { useI18nContext } from '../../../../../../hooks/useI18nContext';
import { currentConfirmationSelector } from '../../../../../../selectors';
+import { getTokenStandardAndDetails } from '../../../../../../store/actions';
import { SignatureRequestType } from '../../../../types/confirm';
import { isPermitSignatureRequest } from '../../../../utils';
import { selectUseTransactionSimulations } from '../../../../selectors/preferences';
@@ -26,6 +27,7 @@ const TypedSignInfo: React.FC = () => {
const useTransactionSimulations = useSelector(
selectUseTransactionSimulations,
);
+ const [decimals, setDecimals] = useState
(0);
if (!currentConfirmation?.msgParams) {
return null;
@@ -38,9 +40,23 @@ const TypedSignInfo: React.FC = () => {
const isPermit = isPermitSignatureRequest(currentConfirmation);
+ useEffect(() => {
+ (async () => {
+ if (!isPermit) {
+ return;
+ }
+ const { decimals: tokenDecimals } = await getTokenStandardAndDetails(
+ verifyingContract,
+ );
+ setDecimals(parseInt(tokenDecimals ?? '0', 10));
+ })();
+ }, [verifyingContract]);
+
return (
<>
- {isPermit && useTransactionSimulations && }
+ {isPermit && useTransactionSimulations && (
+
+ )}
{isPermit && (
<>
@@ -64,6 +80,7 @@ const TypedSignInfo: React.FC = () => {
diff --git a/ui/pages/confirmations/components/confirm/row/dataTree.tsx b/ui/pages/confirmations/components/confirm/row/dataTree.tsx
index 307b608488d9..9f5511e72446 100644
--- a/ui/pages/confirmations/components/confirm/row/dataTree.tsx
+++ b/ui/pages/confirmations/components/confirm/row/dataTree.tsx
@@ -11,6 +11,7 @@ import {
ConfirmInfoRowDate,
ConfirmInfoRowText,
} from '../../../../../components/app/confirm/info/row';
+import { formatNumber } from '../utils';
type ValueType = string | Record | TreeData[];
@@ -22,9 +23,11 @@ export type TreeData = {
export const DataTree = ({
data,
isPermit = false,
+ tokenDecimals = 0,
}: {
data: Record | TreeData[];
isPermit?: boolean;
+ tokenDecimals?: number;
}) => (
{Object.entries(data).map(([label, { value, type }], i) => (
@@ -42,6 +45,7 @@ export const DataTree = ({
isPermit={isPermit}
value={value}
type={type}
+ tokenDecimals={tokenDecimals}
/>
}
@@ -54,14 +58,32 @@ const DataField = ({
isPermit,
type,
value,
+ tokenDecimals,
}: {
label: string;
isPermit: boolean;
type: string;
value: ValueType;
+ tokenDecimals: number;
}) => {
if (typeof value === 'object' && value !== null) {
- return ;
+ return (
+
+ );
+ }
+ if (isPermit && label === 'value') {
+ return (
+
+ );
}
if (isPermit && label === 'deadline') {
return ;
diff --git a/ui/pages/confirmations/components/confirm/row/typed-sign-data/typedSignData.tsx b/ui/pages/confirmations/components/confirm/row/typed-sign-data/typedSignData.tsx
index 9b3934cef651..0b60f45b6a38 100644
--- a/ui/pages/confirmations/components/confirm/row/typed-sign-data/typedSignData.tsx
+++ b/ui/pages/confirmations/components/confirm/row/typed-sign-data/typedSignData.tsx
@@ -7,16 +7,17 @@ import {
ConfirmInfoRow,
ConfirmInfoRowText,
} from '../../../../../../components/app/confirm/info/row';
-
-import { DataTree } from '../dataTree';
import { parseSanitizeTypedDataMessage } from '../../../../utils';
+import { DataTree } from '../dataTree';
export const ConfirmInfoRowTypedSignData = ({
data,
isPermit,
+ tokenDecimals,
}: {
data: string;
isPermit?: boolean;
+ tokenDecimals?: number;
}) => {
const t = useI18nContext();
@@ -35,7 +36,11 @@ export const ConfirmInfoRowTypedSignData = ({
-
+
);
diff --git a/ui/pages/confirmations/components/confirm/utils.test.ts b/ui/pages/confirmations/components/confirm/utils.test.ts
index 87e6307de7be..b967a81e8f77 100644
--- a/ui/pages/confirmations/components/confirm/utils.test.ts
+++ b/ui/pages/confirmations/components/confirm/utils.test.ts
@@ -8,29 +8,39 @@ import {
unapprovedPersonalSignMsg,
} from '../../../../../test/data/confirmations/personal_sign';
import { SignatureRequestType } from '../../types/confirm';
-import { getConfirmationSender } from './utils';
+import { formatNumber, getConfirmationSender } from './utils';
-describe('getConfirmationSender()', () => {
- test("returns the sender address from a signature if it's passed", () => {
- const testCurrentConfirmation =
- genUnapprovedContractInteractionConfirmation() as TransactionMeta;
- const { from } = getConfirmationSender(testCurrentConfirmation);
+describe('confirm - utils', () => {
+ describe('getConfirmationSender()', () => {
+ test("returns the sender address from a signature if it's passed", () => {
+ const testCurrentConfirmation =
+ genUnapprovedContractInteractionConfirmation() as TransactionMeta;
+ const { from } = getConfirmationSender(testCurrentConfirmation);
- expect(from).toEqual(CONTRACT_INTERACTION_SENDER_ADDRESS);
- });
+ expect(from).toEqual(CONTRACT_INTERACTION_SENDER_ADDRESS);
+ });
- test("returns the sender address from a transaction if it's passed", () => {
- const { from } = getConfirmationSender(
- unapprovedPersonalSignMsg as SignatureRequestType,
- );
+ test("returns the sender address from a transaction if it's passed", () => {
+ const { from } = getConfirmationSender(
+ unapprovedPersonalSignMsg as SignatureRequestType,
+ );
- expect(from).toEqual(PERSONAL_SIGN_SENDER_ADDRESS);
- });
+ expect(from).toEqual(PERSONAL_SIGN_SENDER_ADDRESS);
+ });
- test('returns no sender address if no confirmation is passed', () => {
- const testCurrentConfirmation = undefined;
- const { from } = getConfirmationSender(testCurrentConfirmation);
+ test('returns no sender address if no confirmation is passed', () => {
+ const testCurrentConfirmation = undefined;
+ const { from } = getConfirmationSender(testCurrentConfirmation);
+
+ expect(from).toEqual(undefined);
+ });
+ });
- expect(from).toEqual(undefined);
+ describe('formatNumber()', () => {
+ test('formats number according to decimal places passed', () => {
+ expect(formatNumber(123456, 2)).toEqual('123,456.00');
+ expect(formatNumber(123456, 0)).toEqual('123,456');
+ expect(formatNumber(123456, 7)).toEqual('123,456.0000000');
+ });
});
});
diff --git a/ui/pages/confirmations/components/confirm/utils.ts b/ui/pages/confirmations/components/confirm/utils.ts
index 21b4aac78998..581bf1a5ccee 100644
--- a/ui/pages/confirmations/components/confirm/utils.ts
+++ b/ui/pages/confirmations/components/confirm/utils.ts
@@ -17,3 +17,14 @@ export const getConfirmationSender = (
return { from };
};
+
+export const formatNumber = (value: number, decimals: number) => {
+ if (value === undefined) {
+ return value;
+ }
+ const formatter = new Intl.NumberFormat('en-US', {
+ minimumFractionDigits: decimals,
+ maximumFractionDigits: decimals,
+ });
+ return formatter.format(value);
+};