1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Fix a bug where non-address types would be rendered as addresses in EIP-712 (#17846)

* Fix EIP-712 rendering logic

* Fix tests

* Fix tests and story

* Fix lint

* Fix import

* Fix stories
This commit is contained in:
Frederik Bolding 2023-02-27 17:32:51 +01:00 committed by GitHub
parent 932282e638
commit 64bfe6f307
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 543 additions and 337 deletions

View File

@ -26,7 +26,7 @@ function SignatureRequestData({ data }) {
return (
<Box className="signature-request-data__node">
{Object.entries(data).map(([label, value], i) => (
{Object.entries(data).map(([label, { value, type }], i) => (
<Box
className="signature-request-data__node"
key={`${label}-${i}`}
@ -54,7 +54,8 @@ function SignatureRequestData({ data }) {
marginLeft={4}
className="signature-request-data__node__value"
>
{isValidHexAddress(value, {
{type === 'address' &&
isValidHexAddress(value, {
mixedCaseUseChecksum: true,
}) ? (
<Typography

View File

@ -1,4 +1,5 @@
import React from 'react';
import { sanitizeMessage } from '../../../../helpers/utils/util';
import SignatureRequestData from './signature-request-data';
export default {
@ -16,38 +17,58 @@ export const DefaultStory = (args) => {
DefaultStory.storyName = 'Default';
DefaultStory.args = {
data: JSON.parse(
JSON.stringify({
domain: {
name: 'happydapp.website',
},
message: {
string: 'haay wuurl',
number: 42,
},
primaryType: 'Mail',
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
Group: [
{ name: 'name', type: 'string' },
{ name: 'members', type: 'Person[]' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person[]' },
{ name: 'contents', type: 'string' },
],
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallets', type: 'address[]' },
const rawMessage = {
domain: {
chainId: 97,
name: 'Ether Mail',
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
version: '1',
},
message: {
contents: 'Hello, Bob!',
from: {
name: 'Cow',
wallets: [
'0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
'0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
'0x06195827297c7A80a443b6894d3BDB8824b43896',
],
},
to: [
{
name: 'Bob',
wallets: [
'0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
'0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
'0xB0B0b0b0b0b0B000000000000000000000000000',
],
},
}),
),
],
},
primaryType: 'Mail',
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person[]' },
{ name: 'contents', type: 'string' },
],
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallets', type: 'address[]' },
],
},
};
DefaultStory.args = {
data: sanitizeMessage(
rawMessage.message,
rawMessage.primaryType,
rawMessage.types,
).value,
};

View File

@ -1,6 +1,7 @@
import React from 'react';
import configureMockStore from 'redux-mock-store';
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
import { sanitizeMessage } from '../../../../helpers/utils/util';
import Identicon from '../../../ui/identicon';
import SignatureRequestData from './signature-request-data';
@ -59,124 +60,65 @@ describe('Signature Request Data', () => {
},
};
let messageData;
const store = configureMockStore()(mockStore);
beforeEach(() => {
messageData = {
domain: {
chainId: 97,
name: 'Ether Mail',
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
version: '1',
const rawMessage = {
domain: {
chainId: 97,
name: 'Ether Mail',
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
version: '1',
},
message: {
contents: 'Hello, Bob!',
from: {
name: 'Cow',
wallets: [
'0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
'0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
'0x06195827297c7A80a443b6894d3BDB8824b43896',
],
},
message: {
contents: 'Hello, Bob!',
from: {
name: 'Cow',
to: [
{
name: 'Bob',
wallets: [
'0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
'0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
'0x06195827297c7A80a443b6894d3BDB8824b43896',
'0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
'0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
'0xB0B0b0b0b0b0B000000000000000000000000000',
],
},
to: [
{
name: 'Bob',
wallets: [
'0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
'0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
'0xB0B0b0b0b0b0B000000000000000000000000000',
],
},
],
},
primaryType: 'Mail',
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person[]' },
{ name: 'contents', type: 'string' },
],
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallets', type: 'address[]' },
],
},
};
});
],
},
primaryType: 'Mail',
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person[]' },
{ name: 'contents', type: 'string' },
],
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallets', type: 'address[]' },
],
},
};
it('should render domain chainId', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
store,
);
expect(getByText('97')).toBeInTheDocument();
});
it('should render domain name', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
store,
);
expect(getByText('Ether Mail')).toBeInTheDocument();
});
it('should render Identicon for domain verifying contract', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const iconImage = (
<Identicon
diameter={32}
address={msgParams.data.domain.verifyingContract}
/>
);
expect(iconImage).toBeDefined();
});
it('should render domain verifying contract shorten address', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
store,
);
expect(getByText('0xCcC...cccC')).toBeInTheDocument();
});
const messageData = sanitizeMessage(
rawMessage.message,
rawMessage.primaryType,
rawMessage.types,
);
it('should render contents title', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -184,13 +126,8 @@ describe('Signature Request Data', () => {
});
it('should render contants text', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -198,13 +135,8 @@ describe('Signature Request Data', () => {
});
it('should render from title', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -212,13 +144,8 @@ describe('Signature Request Data', () => {
});
it('should render name title in "from" object', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams.data.message.from} />,
<SignatureRequestData data={messageData.value.from.value} />,
store,
);
@ -226,13 +153,8 @@ describe('Signature Request Data', () => {
});
it('should render name text in "from" object', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -240,13 +162,8 @@ describe('Signature Request Data', () => {
});
it('should render wallets title in "from" object', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams.data.message.from} />,
<SignatureRequestData data={messageData.value.from.value} />,
store,
);
@ -254,28 +171,18 @@ describe('Signature Request Data', () => {
});
it('should render Identicon for first wallet in "from" object', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const iconImage = (
<Identicon
diameter={32}
address={msgParams.data.message.from.wallets[0]}
address={messageData.value.from.value.wallets.value[0].value}
/>
);
expect(iconImage).toBeDefined();
});
it('should render first account name from wallets array if address exists in identities object', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -283,28 +190,18 @@ describe('Signature Request Data', () => {
});
it('should render Identicon for second wallet in "from" object', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const iconImage = (
<Identicon
diameter={32}
address={msgParams.data.message.from.wallets[1]}
address={messageData.value.from.value.wallets.value[1].value}
/>
);
expect(iconImage).toBeDefined();
});
it('should render second account name from wallets array if address exists in identities object', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -312,28 +209,18 @@ describe('Signature Request Data', () => {
});
it('should render Identicon for third wallet in "from" object', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const iconImage = (
<Identicon
diameter={32}
address={msgParams.data.message.from.wallets[2]}
address={messageData.value.from.value.wallets.value[2].value}
/>
);
expect(iconImage).toBeDefined();
});
it('should render third account name from wallets array if address exists in address book object', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -341,13 +228,8 @@ describe('Signature Request Data', () => {
});
it('should render name title in "to" array of objects', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams.data.message.to[0]} />,
<SignatureRequestData data={messageData.value.to.value[0].value} />,
store,
);
@ -355,13 +237,8 @@ describe('Signature Request Data', () => {
});
it('should render name text in "to" array of objects', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams.data.message.to[0]} />,
<SignatureRequestData data={messageData.value.to.value[0].value} />,
store,
);
@ -369,13 +246,8 @@ describe('Signature Request Data', () => {
});
it('should render wallets title in "to" array of objects', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams.data.message.to[0]} />,
<SignatureRequestData data={messageData.value.to.value[0].value} />,
store,
);
@ -383,28 +255,18 @@ describe('Signature Request Data', () => {
});
it('should render Identicon for first wallet in "to" array of objects', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const iconImage = (
<Identicon
diameter={32}
address={msgParams.data.message.to[0].wallets[0]}
address={messageData.value.to.value[0].value.wallets.value[0].value}
/>
);
expect(iconImage).toBeDefined();
});
it('should render first shorten address from wallets array if address does not exists in identities and address book objects', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -412,28 +274,18 @@ describe('Signature Request Data', () => {
});
it('should render Identicon for second wallet in "to" array of objects', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const iconImage = (
<Identicon
diameter={32}
address={msgParams.data.message.to[0].wallets[1]}
address={messageData.value.to.value[0].value.wallets.value[1].value}
/>
);
expect(iconImage).toBeDefined();
});
it('should render second shorten address from wallets array if address does not exists in identities and address book objects', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -441,28 +293,18 @@ describe('Signature Request Data', () => {
});
it('should render Identicon for third wallet in "to" array of objects', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const iconImage = (
<Identicon
diameter={32}
address={msgParams.data.message.to[0].wallets[2]}
address={messageData.value.to.value[0].value.wallets.value[2].value}
/>
);
expect(iconImage).toBeDefined();
});
it('should render third shorten address from wallets array if address does not exists in identities and address book objects', () => {
const msgParams = {
data: JSON.parse(JSON.stringify(messageData)),
version: 'V4',
origin: 'test',
};
const { getByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={messageData.value} />,
store,
);
@ -471,9 +313,9 @@ describe('Signature Request Data', () => {
it('should escape RTL character in label or value', () => {
const messageDataWithRTLCharacters = {
...messageData,
...rawMessage,
message: {
...messageData.message,
...rawMessage.message,
contents: 'Hello, \u202E Bob!',
from: {
'name\u202Ename': 'Cow \u202E Cow',
@ -495,20 +337,20 @@ describe('Signature Request Data', () => {
],
},
types: {
...messageData.message.types,
...rawMessage.types,
Person: [
{ name: 'name\u202Ename', type: 'string' },
{ name: 'wallets\u202Ewallets', type: 'address[]' },
],
},
};
const msgParams = {
data: JSON.parse(JSON.stringify(messageDataWithRTLCharacters)),
version: 'V4',
origin: 'test',
};
const data = sanitizeMessage(
messageDataWithRTLCharacters.message,
messageDataWithRTLCharacters.primaryType,
messageDataWithRTLCharacters.types,
);
const { getByText, getAllByText } = renderWithProvider(
<SignatureRequestData data={msgParams} />,
<SignatureRequestData data={data.value} />,
store,
);

View File

@ -87,7 +87,7 @@ export default function SignatureRequestMessage({
>
{primaryType}
</Typography>
<SignatureRequestData data={data} />
<SignatureRequestData data={data.value} />
</Box>
</Box>
);

View File

@ -1,4 +1,5 @@
import React from 'react';
import { sanitizeMessage } from '../../../../helpers/utils/util';
import SignatureRequestMessage from './signature-request-message';
export default {
@ -20,39 +21,59 @@ export const DefaultStory = (args) => {
DefaultStory.storyName = 'Default';
const rawMessage = {
domain: {
chainId: 97,
name: 'Ether Mail',
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
version: '1',
},
message: {
contents: 'Hello, Bob!',
from: {
name: 'Cow',
wallets: [
'0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
'0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
'0x06195827297c7A80a443b6894d3BDB8824b43896',
],
},
to: [
{
name: 'Bob',
wallets: [
'0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
'0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
'0xB0B0b0b0b0b0B000000000000000000000000000',
],
},
],
},
primaryType: 'Mail',
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person[]' },
{ name: 'contents', type: 'string' },
],
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallets', type: 'address[]' },
],
},
};
DefaultStory.args = {
data: JSON.parse(
JSON.stringify({
domain: {
name: 'happydapp.website',
},
message: {
string: 'haay wuurl',
number: 42,
},
primaryType: 'Mail',
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
Group: [
{ name: 'name', type: 'string' },
{ name: 'members', type: 'Person[]' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person[]' },
{ name: 'contents', type: 'string' },
],
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallets', type: 'address[]' },
],
},
}),
data: sanitizeMessage(
rawMessage.message,
rawMessage.primaryType,
rawMessage.types,
),
messageIsScrollable: true,
};

View File

@ -444,11 +444,14 @@ export const sanitizeMessage = (msg, primaryType, types) => {
// Primary type can be an array.
const isArray = primaryType && isArrayType(primaryType);
if (isArray) {
return msg.map((value) =>
sanitizeMessage(value, stripOneLayerofNesting(primaryType), types),
);
return {
value: msg.map((value) =>
sanitizeMessage(value, stripOneLayerofNesting(primaryType), types),
),
type: primaryType,
};
} else if (isSolidityType(primaryType)) {
return msg;
return { value: msg, type: primaryType };
}
// If not, assume to be struct
@ -459,7 +462,7 @@ export const sanitizeMessage = (msg, primaryType, types) => {
throw new Error(`Invalid primary type definition`);
}
const sanitizedMessage = {};
const sanitizedStruct = {};
const msgKeys = Object.keys(msg);
msgKeys.forEach((msgKey) => {
const definedType = Object.values(baseTypeDefinitions).find(
@ -470,13 +473,13 @@ export const sanitizeMessage = (msg, primaryType, types) => {
return;
}
sanitizedMessage[msgKey] = sanitizeMessage(
sanitizedStruct[msgKey] = sanitizeMessage(
msg[msgKey],
definedType.type,
types,
);
});
return sanitizedMessage;
return { value: sanitizedStruct, type: primaryType };
};
export function getAssetImageURL(image, ipfsGateway) {

View File

@ -478,12 +478,107 @@ describe('util', () => {
it('should return parsed message if types is defined', () => {
const result = util.sanitizeMessage(message, primaryType, types);
expect(result.contents).toStrictEqual('Hello, Bob!');
expect(result.from.name).toStrictEqual('Cow');
expect(result.from.wallets).toHaveLength(2);
expect(result.to).toHaveLength(1);
expect(result.to[0].name).toStrictEqual('Bob');
expect(result.to[0].wallets).toHaveLength(3);
expect(result).toStrictEqual({
type: 'Mail',
value: {
contents: {
type: 'string',
value: 'Hello, Bob!',
},
from: {
type: 'Person',
value: {
name: {
type: 'string',
value: 'Cow',
},
wallets: {
type: 'address[]',
value: [
{
type: 'address',
value: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
},
{
type: 'address',
value: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
},
],
},
},
},
nestArray: {
type: 'uint256[2][2]',
value: [
{
type: 'uint256[2]',
value: [
{
type: 'uint256',
value: 12,
},
{
type: 'uint256',
value: 34,
},
{
type: 'uint256',
value: 56,
},
],
},
{
type: 'uint256[2]',
value: [
{
type: 'uint256',
value: 56,
},
{
type: 'uint256',
value: 78,
},
{
type: 'uint256',
value: 89,
},
],
},
],
},
to: {
type: 'Person[]',
value: [
{
type: 'Person',
value: {
name: {
type: 'string',
value: 'Bob',
},
wallets: {
type: 'address[]',
value: [
{
type: 'address',
value: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
{
type: 'address',
value: '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
},
{
type: 'address',
value: '0xB0B0b0b0b0b0B000000000000000000000000000',
},
],
},
},
},
],
},
},
});
});
it('should return parsed nested array if defined', () => {
@ -497,10 +592,50 @@ describe('util', () => {
primaryType,
types,
);
expect(result.nestArray).toHaveLength(2);
expect(result.nestArray[0]).toHaveLength(3);
expect(result.nestArray[0][0]).toStrictEqual(12);
expect(result.nestArray[0][2]).toStrictEqual(56);
expect(result).toStrictEqual({
type: 'Mail',
value: {
nestArray: {
type: 'uint256[2][2]',
value: [
{
type: 'uint256[2]',
value: [
{
type: 'uint256',
value: 12,
},
{
type: 'uint256',
value: 34,
},
{
type: 'uint256',
value: 56,
},
],
},
{
type: 'uint256[2]',
value: [
{
type: 'uint256',
value: 56,
},
{
type: 'uint256',
value: 78,
},
{
type: 'uint256',
value: 89,
},
],
},
],
},
},
});
});
it('should return parsed nested array with struct if defined', () => {
@ -537,14 +672,104 @@ describe('util', () => {
],
};
const result = util.sanitizeMessage(msg, primaryType, types);
expect(result.nestedPeople).toHaveLength(2);
expect(result.nestedPeople[0]).toHaveLength(1);
expect(result.nestedPeople[0][0].name).toStrictEqual('Bob');
expect(result.nestedPeople[0][0].wallets).toHaveLength(3);
expect(result.nestedPeople[0][0].wallets[0]).toStrictEqual(
'0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
);
expect(result.nestedPeople[1][1].name).toStrictEqual('Brandon');
expect(result).toStrictEqual({
type: 'Mail',
value: {
nestedPeople: {
type: 'Person[][]',
value: [
{
type: 'Person[]',
value: [
{
type: 'Person',
value: {
name: {
type: 'string',
value: 'Bob',
},
wallets: {
type: 'address[]',
value: [
{
type: 'address',
value: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
{
type: 'address',
value: '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
},
{
type: 'address',
value: '0xB0B0b0b0b0b0B000000000000000000000000000',
},
],
},
},
},
],
},
{
type: 'Person[]',
value: [
{
type: 'Person',
value: {
name: {
type: 'string',
value: 'Ben',
},
wallets: {
type: 'address[]',
value: [
{
type: 'address',
value: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
{
type: 'address',
value: '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
},
{
type: 'address',
value: '0xB0B0b0b0b0b0B000000000000000000000000000',
},
],
},
},
},
{
type: 'Person',
value: {
name: {
type: 'string',
value: 'Brandon',
},
wallets: {
type: 'address[]',
value: [
{
type: 'address',
value: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
{
type: 'address',
value: '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
},
{
type: 'address',
value: '0xB0B0b0b0b0b0B000000000000000000000000000',
},
],
},
},
},
],
},
],
},
},
});
});
it('should return ignore message data with unknown types', () => {
@ -555,14 +780,107 @@ describe('util', () => {
// result will NOT contain the do_not_displays because type definition
const result = util.sanitizeMessage(message, primaryType, types);
expect(result.contents).toStrictEqual('Hello, Bob!');
expect(result.from.name).toStrictEqual('Cow');
expect(result.from.wallets).toHaveLength(2);
expect(result.to).toHaveLength(1);
expect(result.to[0].name).toStrictEqual('Bob');
expect(result.to[0].wallets).toHaveLength(3);
expect(result.do_not_display).toBeUndefined();
expect(result.do_not_display_2).toBeUndefined();
expect(result).toStrictEqual({
type: 'Mail',
value: {
contents: {
type: 'string',
value: 'Hello, Bob!',
},
from: {
type: 'Person',
value: {
name: {
type: 'string',
value: 'Cow',
},
wallets: {
type: 'address[]',
value: [
{
type: 'address',
value: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
},
{
type: 'address',
value: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
},
],
},
},
},
nestArray: {
type: 'uint256[2][2]',
value: [
{
type: 'uint256[2]',
value: [
{
type: 'uint256',
value: 12,
},
{
type: 'uint256',
value: 34,
},
{
type: 'uint256',
value: 56,
},
],
},
{
type: 'uint256[2]',
value: [
{
type: 'uint256',
value: 56,
},
{
type: 'uint256',
value: 78,
},
{
type: 'uint256',
value: 89,
},
],
},
],
},
to: {
type: 'Person[]',
value: [
{
type: 'Person',
value: {
name: {
type: 'string',
value: 'Bob',
},
wallets: {
type: 'address[]',
value: [
{
type: 'address',
value: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
{
type: 'address',
value: '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
},
{
type: 'address',
value: '0xB0B0b0b0b0b0B000000000000000000000000000',
},
],
},
},
},
],
},
},
});
});
});
});