Skip to content

refactor: parse signTypedData logic #14378

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
efb9889
style: rn sanitizeString to escapeSpecialUnicode
digiwand Mar 26, 2025
ce79681
style: reorder utils/signature.ts
digiwand Apr 1, 2025
cf9f745
style: refactor mv sig utils from string utils to sig utils
digiwand Mar 26, 2025
dfddbb2
style: rn sanitizeMessage to sanitizeParsedMessage to be more explicit
digiwand Mar 26, 2025
add4f6c
style: rn parseTypedSignDataMessage to parseSignTypedDataMessage
digiwand Mar 26, 2025
d831c0f
comment: add sanitizeParsedMessage strings multi lines
digiwand Mar 26, 2025
cf23d70
comment: be more explicity in sanitizeParsedMessage
digiwand Mar 26, 2025
6b05947
refactor: parseTypedDataMessage
digiwand Apr 1, 2025
d9888f0
cleanup
digiwand Apr 1, 2025
2ebea96
refactor: parseTypedDataMessageFromSignatureRequest update to return …
digiwand Apr 1, 2025
9025646
style: rn parseSignTypedDataMessage -> parseAndSanitizeSignTypedData
digiwand Apr 1, 2025
3461784
style: rn dataToParse -> messageParamsData
digiwand Apr 1, 2025
7f553b1
style: rn parseTypedDataMessage -> parseSignTypedData
digiwand Apr 1, 2025
a402cea
style: temp rn parseSanitizeTypedDataMessage -> parseAndSanitizeSignT…
digiwand Apr 2, 2025
dbbdd15
refactor: rm extra parseAndSanitizeSignTypedData
digiwand Apr 2, 2025
ada06b0
refactor: memoize parseAndSanitizeSignTypedData
digiwand Apr 2, 2025
47e6431
fix: restore error thrown from parseSignTypedData
digiwand Apr 2, 2025
8917e45
test: add stripArrayType, stripOneLayerofNesting, isArrayType, and is…
digiwand Apr 2, 2025
62788e2
style: mislabeled TS should accept unknown for stripMultipleNewlines
digiwand Apr 3, 2025
4c77a09
refactor: parsedMessage -> parsedData
digiwand Apr 3, 2025
258b212
Merge branch 'main' into refactor-parse-signTypedData-logic
digiwand Apr 9, 2025
c1d7f9e
Merge branch 'main' into refactor-parse-signTypedData-logic
digiwand Apr 14, 2025
78bf8e1
refactor: restore useMemo and undo memoize on parseAndSanitizeSignTyp…
digiwand Apr 16, 2025
29b738d
Merge branch 'main' into refactor-parse-signTypedData-logic
digiwand Apr 16, 2025
c02eb58
Merge branch 'main' into refactor-parse-signTypedData-logic
digiwand Apr 16, 2025
f705412
Merge branch 'main' into refactor-parse-signTypedData-logic
digiwand Apr 17, 2025
295a9ad
refactor: rn parse signTypedData methods
digiwand Apr 17, 2025
36c1972
fix: attempt to fix broken v3 and v4 test by reverting normalization …
digiwand Apr 17, 2025
86d0114
fix: utils parseAndSanitizeSignTypedData import
digiwand Apr 17, 2025
7ae1331
Merge branch 'main' into refactor-parse-signTypedData-logic
digiwand Apr 17, 2025
e9aae1c
Merge branch 'main' into refactor-parse-signTypedData-logic
digiwand Apr 22, 2025
fe179db
Merge branch 'main' into refactor-parse-signTypedData-logic
digiwand Apr 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Text from '../../../../../../component-library/components/Texts/Text';
import { Theme } from '../../../../../../util/theme/models';
import { fontStyles } from '../../../../../../styles/common';
import { useStyles } from '../../../../../../component-library/hooks';
import { sanitizeString } from '../../../../../../util/string';
import { escapeSpecialUnicode } from '../../../../../../util/string';
import { getSIWEDetails, SIWEMessage } from '../../../utils/signature';
import { useSignatureRequest } from '../../../hooks/signatures/useSignatureRequest';
import Address from '../../UI/info-row/info-value/address';
Expand Down Expand Up @@ -104,7 +104,7 @@ const Message = () => {
if (!signatureRequest?.messageParams?.data) {
return '';
}
return sanitizeString(
return escapeSpecialUnicode(
hexToText(signatureRequest?.messageParams?.data as string),
);
}, [signatureRequest?.messageParams?.data]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { InfoRowDivider } from '../../../UI/info-row/divider';
import InfoSection from '../../../UI/info-row/info-section';
import InfoRowAddress from '../../../UI/info-row/info-value/address';
import DisplayURL from '../../../UI/info-row/info-value/display-url';
import { isRecognizedPermit, parseTypedDataMessageFromSignatureRequest } from '../../../../utils/signature';
import {
isRecognizedPermit,
parseAndNormalizeSignTypedDataFromSignatureRequest,
} from '../../../../utils/signature';
import { useSignatureRequest } from '../../../../hooks/signatures/useSignatureRequest';
import useApprovalRequest from '../../../../hooks/useApprovalRequest';
import { View } from 'react-native';
Expand All @@ -26,9 +29,9 @@ export const InfoSectionOriginAndDetails = () => {
const signatureRequest = useSignatureRequest();
const isPermit = isRecognizedPermit(signatureRequest);

const parsedMessage = parseTypedDataMessageFromSignatureRequest(signatureRequest);
const spender = parsedMessage?.message?.spender;
const verifyingContract = parsedMessage?.domain?.verifyingContract;
const parsedData = parseAndNormalizeSignTypedDataFromSignatureRequest(signatureRequest);
const spender = parsedData.message?.spender;
const verifyingContract = parsedData.domain?.verifyingContract;

if (!signatureRequest) {
return null;
Expand Down Expand Up @@ -57,13 +60,10 @@ export const InfoSectionOriginAndDetails = () => {
<DisplayURL url={origin} />
</InfoRow>
{isValidAddress(verifyingContract) && (
<InfoRow label={strings('confirm.label.interacting_with')}>
<InfoRowAddress
address={verifyingContract}
chainId={chainId}
/>
</InfoRow>
)}
<InfoRow label={strings('confirm.label.interacting_with')}>
<InfoRowAddress address={verifyingContract} chainId={chainId} />
</InfoRow>
)}
</InfoSection>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useSignatureRequest } from '../../../hooks/signatures/useSignatureReque
import Text from '../../../../../../component-library/components/Texts/Text';
import { useStyles } from '../../../../../../component-library/hooks';
import { useTypedSignSimulationEnabled } from '../../../hooks/signatures/useTypedSignSimulationEnabled';
import { parseSanitizeTypedDataMessage } from '../../../utils/signature';
import { parseNormalizeAndSanitizeSignTypedData } from '../../../utils/signature';
import InfoRow from '../../UI/info-row';
import { useTokenDecimalsInTypedSignRequest } from '../../../hooks/signatures/useTokenDecimalsInTypedSignRequest';
import DataTree from '../../data-tree';
Expand Down Expand Up @@ -51,7 +51,7 @@ const Message = () => {
sanitizedMessage,
primaryType,
} = useMemo(
() => parseSanitizeTypedDataMessage(typedSignData),
() => parseNormalizeAndSanitizeSignTypedData(typedSignData),
[typedSignData],
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Engine from '../../../../../../../../core/Engine';
import { safeToChecksumAddress } from '../../../../../../../../util/address';
import { PrimaryType } from '../../../../../constants/signatures';
import { useSignatureRequest } from '../../../../../hooks/signatures/useSignatureRequest';
import { isPermitDaiRevoke, parseTypedDataMessage } from '../../../../../utils/signature';
import { isPermitDaiRevoke, parseAndNormalizeSignTypedData } from '../../../../../utils/signature';
import InfoRow from '../../../../UI/info-row';
import InfoSection from '../../../../UI/info-row/info-section';
import PermitSimulationValueDisplay from '../components/value-display';
Expand Down Expand Up @@ -74,7 +74,7 @@ const PermitSimulation = () => {
message,
message: { allowed, tokenId, value },
primaryType,
} = parseTypedDataMessage(msgData as string);
} = parseAndNormalizeSignTypedData(msgData as string);

const tokenDetails = extractTokenDetailsByPrimaryType(message, primaryType);

Expand Down
14 changes: 10 additions & 4 deletions app/components/Views/confirmations/components/title/title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import useApprovalRequest from '../../hooks/useApprovalRequest';
import { useSignatureRequest } from '../../hooks/signatures/useSignatureRequest';
import { useStandaloneConfirmation } from '../../hooks/ui/useStandaloneConfirmation';
import { useTransactionMetadataRequest } from '../../hooks/transactions/useTransactionMetadataRequest';
import { isPermitDaiRevoke, isRecognizedPermit, isSIWESignatureRequest, parseTypedDataMessageFromSignatureRequest } from '../../utils/signature';
import {
isPermitDaiRevoke,
isRecognizedPermit,
isSIWESignatureRequest,
parseAndNormalizeSignTypedDataFromSignatureRequest,
} from '../../utils/signature';
import { REDESIGNED_TRANSFER_TYPES } from '../../constants/confirmations';
import styleSheet from './title.styles';

Expand Down Expand Up @@ -40,9 +45,10 @@ const getTitleAndSubTitle = (
const isPermit = isRecognizedPermit(signatureRequest);

if (isPermit) {
const parsedMessage = parseTypedDataMessageFromSignatureRequest(signatureRequest) ?? {};
const { allowed, tokenId, value } = parsedMessage?.message ?? {};
const { verifyingContract } = parsedMessage?.domain ?? {};
const parsedData =
parseAndNormalizeSignTypedDataFromSignatureRequest(signatureRequest);
const { allowed, tokenId, value } = parsedData.message ?? {};
const { verifyingContract } = parsedData.domain ?? {};

const isERC721Permit = tokenId !== undefined;
if (isERC721Permit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { getSignatureDecodingEventProps } from '../../utils/signature-metrics';
import { useSignatureRequest } from './useSignatureRequest';
import { useSecurityAlertResponse } from '../alerts/useSecurityAlertResponse';
import { useTypedSignSimulationEnabled } from './useTypedSignSimulationEnabled';
import { parseTypedDataMessageFromSignatureRequest } from '../../utils/signature';
import { parseAndNormalizeSignTypedDataFromSignatureRequest } from '../../utils/signature';
import { useSelector } from 'react-redux';
import { selectConfirmationMetricsById } from '../../../../../core/redux/slices/confirmationMetrics';
import { RootState } from '../../../../../reducers';
Expand Down Expand Up @@ -66,7 +66,7 @@ export const useSignatureMetrics = () => {

const { chainId, decodingData, decodingLoading, messageParams, type, id } =
signatureRequest ?? {};
const { primaryType } = parseTypedDataMessageFromSignatureRequest(signatureRequest) ?? {};
const { primaryType } = parseAndNormalizeSignTypedDataFromSignatureRequest(signatureRequest);

const confirmationMetrics = useSelector((state: RootState) =>
selectConfirmationMetricsById(state, id ?? '')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { renderHook } from '@testing-library/react-hooks';

import { typedSignV4SignatureRequest } from '../../../../../util/test/confirm-data-helpers';
import { DataTreeInput } from '../../components/data-tree/data-tree';
import { parseSanitizeTypedDataMessage } from '../../utils/signature';
import { parseNormalizeAndSanitizeSignTypedData } from '../../utils/signature';
// eslint-disable-next-line import/no-namespace
import * as TokenDecimalHook from '../useGetTokenStandardAndDetails';
import { useTokenDecimalsInTypedSignRequest } from './useTokenDecimalsInTypedSignRequest';
Expand All @@ -12,7 +12,7 @@ describe('useTokenDecimalsInTypedSignRequest', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const typedSignData = signatureRequest?.messageParams?.data as any;
const { domain: { verifyingContract } = {}, sanitizedMessage } =
parseSanitizeTypedDataMessage(typedSignData);
parseNormalizeAndSanitizeSignTypedData(typedSignData);

it('returns correct decimal value for typed sign signature request', () => {
jest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
SignatureRequestType,
} from '@metamask/signature-controller';
import { selectUseTransactionSimulations } from '../../../../../selectors/preferencesController';
import { isRecognizedPermit, parseTypedDataMessage } from '../../utils/signature';
import { isRecognizedPermit, parseAndNormalizeSignTypedData } from '../../utils/signature';
import { useSignatureRequest } from './useSignatureRequest';

const NON_PERMIT_SUPPORTED_TYPES_SIGNS = [
Expand All @@ -32,7 +32,7 @@ const isNonPermitSupportedByDecodingAPI = (
const {
domain: { name, version },
primaryType,
} = parseTypedDataMessage(data);
} = parseAndNormalizeSignTypedData(data);

return NON_PERMIT_SUPPORTED_TYPES_SIGNS.some(
({ domainName, primaryTypeList, versionList }) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
isExternalHardwareAccount,
stripHexPrefix,
} from '../../../../../../util/address';
import { sanitizeString } from '../../../../../../util/string';
import { escapeSpecialUnicode } from '../../../../../../util/string';
import { useTheme } from '../../../../../../util/theme';
import { WALLET_CONNECT_ORIGIN } from '../../../../../../util/walletconnect';
import SignatureRequest from '../SignatureRequest';
Expand Down Expand Up @@ -210,7 +210,7 @@ const PersonalSign = ({
};

const renderMessageText = () => {
const textChild = sanitizeString(msgHexToText(messageParams.data))
const textChild = escapeSpecialUnicode(msgHexToText(messageParams.data))
.split('\n')
.map((line: string, i: number) => (
<Text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ import { MetaMetricsEvents } from '../../../../../../core/Analytics';
import { MetricsEventBuilder } from '../../../../../../core/Analytics/MetricsEventBuilder';
import { KEYSTONE_TX_CANCELED } from '../../../../../../constants/error';
import { ThemeContext, mockTheme } from '../../../../../../util/theme';
import {
parseTypedSignDataMessage,
sanitizeString,
} from '../../../../../../util/string';
import { escapeSpecialUnicode } from '../../../../../../util/string';
import { parseAndSanitizeSignTypedData } from '../../../../../../components/Views/confirmations/utils/signature';

import {
addSignatureErrorListener,
Expand Down Expand Up @@ -201,14 +199,14 @@ class TypedSign extends PureComponent {
{obj[key] && typeof obj[key] === 'object' ? (
<View>
<Text style={[styles.messageText, styles.msgKey]}>
{sanitizeString(key)}:
{escapeSpecialUnicode(key)}:
</Text>
<View>{this.renderTypedMessageV3(obj[key])}</View>
</View>
) : (
<Text style={styles.messageText}>
<Text style={styles.msgKey}>{sanitizeString(key)}:</Text>{' '}
{sanitizeString(`${obj[key]}`)}
<Text style={styles.msgKey}>{escapeSpecialUnicode(key)}:</Text>{' '}
{escapeSpecialUnicode(`${obj[key]}`)}
</Text>
)}
</View>
Expand All @@ -225,19 +223,19 @@ class TypedSign extends PureComponent {
{messageParams.data.map((obj, i) => (
<View key={`${obj.name}_${i}`}>
<Text style={[styles.messageText, styles.msgKey]}>
{sanitizeString(obj.name)}:
{escapeSpecialUnicode(obj.name)}:
</Text>
<Text style={styles.messageText} key={obj.name}>
{sanitizeString(` ${obj.value}`)}
{escapeSpecialUnicode(` ${obj.value}`)}
</Text>
</View>
))}
</View>
);
}
if (messageParams.version === 'V3' || messageParams.version === 'V4') {
const message = parseTypedSignDataMessage(messageParams.data);
return this.renderTypedMessageV3(message);
const { sanitizedMessage } = parseAndSanitizeSignTypedData(messageParams.data);
return this.renderTypedMessageV3(sanitizedMessage);
}
};

Expand Down
Loading
Loading