Skip to content

Commit

Permalink
fix: [cherrypick][V12.3.0] Redesign Signature Message date values (#2…
Browse files Browse the repository at this point in the history
…7305)

## **Description**

Cherry-pick #27249
for v12.3.0

Fix date values:
- Formerly, conversations were converting values as if they were
milliseconds. However, these values come from Solidity where these
timestamps are unix timestamps in seconds.
- Support -1 (no expiration) value
- Display "expiry" as a date instead of a unix timestamp

This PR fixes the conversion.

[![Open in GitHub

Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27249?quickstart=1)

Fixes: #27137

1. Go to test-dapp
2. Request Permit or another TypedSign request
3. Observe deadlines and dates

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

<img width="320"

src="https://github.com/user-attachments/assets/855fc4a5-5a1b-4575-bfda-40b5b6688fe3">

<img width="320"

src="https://github.com/user-attachments/assets/0bc90b15-daa7-4537-9cd1-8727000899b2">

<img width="320"

src="https://github.com/user-attachments/assets/e1beb4f9-2b41-4ef9-8190-8264d88c9ab0">

<img width="320"

src="https://github.com/user-attachments/assets/edb4d259-29a3-4558-8858-e5b619c0ce18">

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding

Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
digiwand authored Sep 23, 2024
1 parent 4c4b5c7 commit e5a2159
Show file tree
Hide file tree
Showing 15 changed files with 801 additions and 29 deletions.
3 changes: 3 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 25 additions & 2 deletions test/data/confirmations/typed_sign.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TransactionType } from '@metamask/transaction-controller';
import { SignatureRequestType } from '../../../ui/pages/confirmations/types/confirm';

export const unapprovedTypedSignMsgV1 = {
Expand Down Expand Up @@ -169,12 +170,13 @@ export const permitSignatureMsg = {
data: '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Permit":[{"name":"owner","type":"address"},{"name":"spender","type":"address"},{"name":"value","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"deadline","type":"uint256"}]},"primaryType":"Permit","domain":{"name":"MyToken","version":"1","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","chainId":1},"message":{"owner":"0x935e73edb9ff52e23bac7f7e043a1ecd06d05477","spender":"0x5B38Da6a701c568545dCfcB03FcB875f56beddC4","value":3000,"nonce":0,"deadline":50000000000}}',
from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
version: 'V4',
requestId: 14,
signatureMethod: 'eth_signTypedData_v4',
origin: 'https://metamask.github.io',
},
} as SignatureRequestType;

export const permitBatchSignatureMsg = {
export const permitSignatureMsgWithNoDeadline = {
id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659',
securityAlertResponse: {
reason: 'loading',
Expand All @@ -184,10 +186,30 @@ export const permitBatchSignatureMsg = {
status: 'unapproved',
time: 1716826404122,
type: 'eth_signTypedData',
msgParams: {
data: '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Permit":[{"name":"owner","type":"address"},{"name":"spender","type":"address"},{"name":"value","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"deadline","type":"uint256"}]},"primaryType":"Permit","domain":{"name":"MyToken","version":"1","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","chainId":1},"message":{"owner":"0x935e73edb9ff52e23bac7f7e043a1ecd06d05477","spender":"0x5B38Da6a701c568545dCfcB03FcB875f56beddC4","value":3000,"nonce":0,"deadline":-1}}',
from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
version: 'V4',
signatureMethod: 'eth_signTypedData_v4',
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: TransactionType.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',
requestId: 15,
signatureMethod: 'eth_signTypedData_v4',
origin: 'https://metamask.github.io',
},
Expand All @@ -202,11 +224,12 @@ export const permitSingleSignatureMsg = {
},
status: 'unapproved',
time: 1716826404122,
type: 'eth_signTypedData',
type: TransactionType.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',
requestId: 16,
signatureMethod: 'eth_signTypedData_v4',
origin: 'https://metamask.github.io',
},
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/tests/confirmations/signatures/permit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ async function assertInfoValues(driver: Driver) {
});
const value = driver.findElement({ text: '3,000' });
const nonce = driver.findElement({ text: '0' });
const deadline = driver.findElement({ text: '02 August 1971, 16:53' });
const deadline = driver.findElement({ text: '09 June 3554, 16:53' });

assert.ok(await origin, 'origin');
assert.ok(await contractPetName, 'contractPetName');
Expand Down
4 changes: 2 additions & 2 deletions ui/components/app/confirm/info/row/date.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ const ConfirmInfoRowDateStory = {
},
};

export const DefaultStory = ({ date }) => <ConfirmInfoRowDate date={date} />;
export const DefaultStory = ({ date }) => <ConfirmInfoRowDate unixTimestamp={date} />;
DefaultStory.args = {
date: 1633019124000,
date: 1633019124,
};

export default ConfirmInfoRowDateStory;
4 changes: 3 additions & 1 deletion ui/components/app/confirm/info/row/date.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { ConfirmInfoRowDate } from './date';

describe('ConfirmInfoRowDate', () => {
it('should match snapshot', () => {
const { getByText } = render(<ConfirmInfoRowDate date={1633019124000} />);
const { getByText } = render(
<ConfirmInfoRowDate unixTimestamp={1633019124} />,
);
expect(getByText('30 September 2021, 16:25')).toBeInTheDocument();
});
});
11 changes: 7 additions & 4 deletions ui/components/app/confirm/info/row/date.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ import {
FlexWrap,
TextColor,
} from '../../../../../helpers/constants/design-system';
import { formatUTCDate } from '../../../../../helpers/utils/util';
import { formatUTCDateFromUnixTimestamp } from '../../../../../helpers/utils/util';
import { Box, Text } from '../../../../component-library';

export type ConfirmInfoRowDateProps = {
date: number;
/** timestamp as seconds since unix epoch e.g. Solidity block.timestamp (type uint256) value */
unixTimestamp: number;
};

export const ConfirmInfoRowDate = ({ date }: ConfirmInfoRowDateProps) => (
export const ConfirmInfoRowDate = ({
unixTimestamp,
}: ConfirmInfoRowDateProps) => (
<Box
display={Display.Flex}
alignItems={AlignItems.center}
flexWrap={FlexWrap.Wrap}
gap={2}
>
<Text color={TextColor.inherit} style={{ whiteSpace: 'pre-wrap' }}>
{formatUTCDate(date)}
{formatUTCDateFromUnixTimestamp(unixTimestamp)}
</Text>
</Box>
);
14 changes: 9 additions & 5 deletions ui/helpers/utils/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,17 @@ export function formatDate(date, format = "M/d/y 'at' T") {
return DateTime.fromMillis(date).toFormat(format);
}

export const formatUTCDate = (dateInMillis) => {
if (!dateInMillis) {
return dateInMillis;
/**
* @param {number} unixTimestamp - timestamp as seconds since unix epoch
* @returns {string} formatted date string e.g. "14 July 2034, 22:22"
*/
export const formatUTCDateFromUnixTimestamp = (unixTimestamp) => {
if (!unixTimestamp) {
return unixTimestamp;
}

return DateTime.fromMillis(dateInMillis)
.setZone('utc')
return DateTime.fromSeconds(unixTimestamp)
.toUTC()
.toFormat('dd LLLL yyyy, HH:mm');
};

Expand Down
8 changes: 4 additions & 4 deletions ui/helpers/utils/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1044,15 +1044,15 @@ describe('util', () => {
});
});

describe('formatUTCDate', () => {
describe('formatUTCDateFromUnixTimestamp', () => {
it('formats passed date string', () => {
expect(util.formatUTCDate(1633019124000)).toStrictEqual(
'30 September 2021, 16:25',
expect(util.formatUTCDateFromUnixTimestamp(2036528542)).toStrictEqual(
'14 July 2034, 22:22',
);
});

it('returns empty string if empty string is passed', () => {
expect(util.formatUTCDate('')).toStrictEqual('');
expect(util.formatUTCDateFromUnixTimestamp('')).toStrictEqual('');
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ const SIWESignInfo: React.FC = () => {
</ConfirmInfoRow>
<ConfirmInfoRow label={t('siweIssued')}>
<ConfirmInfoRowDate
date={DateTime.fromISO(issuedAt).toJSDate().getTime()}
unixTimestamp={DateTime.fromISO(issuedAt, {
zone: 'utc',
}).toUnixInteger()}
/>
</ConfirmInfoRow>
{requestId && (
Expand Down
Loading

0 comments on commit e5a2159

Please sign in to comment.