Skip to content

Commit

Permalink
feat: add dynamicPart in schema returned by getSchema
Browse files Browse the repository at this point in the history
  • Loading branch information
CJ42 committed Apr 28, 2024
1 parent a218ef3 commit 12d34d2
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 22 deletions.
24 changes: 16 additions & 8 deletions src/lib/schemaParser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/

import assert from 'assert';
import { ERC725JSONSchema } from '../types/ERC725JSONSchema';
import { DynamicNameSchema } from '../types/ERC725JSONSchema';

import { getSchema } from './schemaParser';

Expand Down Expand Up @@ -112,11 +112,13 @@ describe('schemaParser getSchema', () => {

it('finds Known Mapping:<address> ', () => {
const address = 'af3bf2ffb025098b79caddfbdd113b3681817744';
const name = `MyCoolAddress:${address}`;
const name = 'MyCoolAddress:<address>';
const dynamicName = `MyCoolAddress:${address}`;
const key = `0x22496f48a493035f00000000${address}`;

const extraSchema: ERC725JSONSchema = {
const extraSchema: DynamicNameSchema = {
name,
dynamicName,
key,
keyType: 'Mapping',
valueContent: 'Address',
Expand All @@ -131,11 +133,13 @@ describe('schemaParser getSchema', () => {
it('finds known SomeBytes32Mapping:<bytes32>', () => {
const bytes32Value =
'1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff';
const name = `SomeBytes32Mapping:${bytes32Value}`;
const name = `SomeBytes32Mapping:<bytes32>`;
const dynamicName = `SomeBytes32Mapping:${bytes32Value}`;
const key = `0x0cfc51aec37c55a4d0b10000${bytes32Value.slice(0, 42)}`;

const extraSchema: ERC725JSONSchema = {
const extraSchema: DynamicNameSchema = {
name,
dynamicName,
key,
keyType: 'Mapping',
valueContent: 'Address',
Expand All @@ -149,11 +153,13 @@ describe('schemaParser getSchema', () => {

it('finds known SomeSelectorMap:<bytes4>', () => {
const bytes4Value = 'beefbeef';
const name = `SomeSelectorMap:${bytes4Value}`;
const name = `SomeSelectorMap:<bytes4>`;
const dynamicName = `SomeSelectorMap:${bytes4Value}`;
const key = `0x0cfc51aec37c55a4d0b10000${bytes4Value}00000000000000000000000000000000`;

const extraSchema: ERC725JSONSchema = {
const extraSchema: DynamicNameSchema = {
name,
dynamicName,
key,
keyType: 'Mapping',
valueContent: '(Address,bool)',
Expand All @@ -169,12 +175,14 @@ describe('schemaParser getSchema', () => {
describe('MappingWithGrouping', () => {
it('finds MappingWithGrouping', () => {
const address = 'af3bf2ffb025098b79caddfbdd113b3681817744';
const name = `AddressPermissions:Permissions:${address}`;
const name = `AddressPermissions:Permissions:<address>`;
const dynamicName = `AddressPermissions:Permissions:${address}`;
const key = `0x4b80742de2bf82acb3630000${address}`;
const schema = getSchema(key);

assert.deepStrictEqual(schema, {
name,
dynamicName,
key,
keyType: 'MappingWithGrouping',
valueContent: 'BitArray',
Expand Down
30 changes: 16 additions & 14 deletions src/lib/schemaParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { keccak256 } from 'web3-utils';
import allSchemas from '../schemas';

import {
DynamicNameSchema,
ERC725JSONSchema,
ERC725JSONSchemaKeyType,
} from '../types/ERC725JSONSchema';
Expand Down Expand Up @@ -87,10 +88,9 @@ const findArraySchemaForKey = (
const findMappingSchemaForKey = (
key: string,
schemas: ERC725JSONSchema[],
): ERC725JSONSchema | null => {
): ERC725JSONSchema | DynamicNameSchema | null => {
const firstWordHex = key.substring(0, 26);
const secondWordHex = key.substring(26);

// Should detect:

// 1. Known/defined mapping
Expand All @@ -101,7 +101,7 @@ const findMappingSchemaForKey = (
}

// 2. "Semi defined mappings" i.e. "SupportedStandards:??????"
let dynamicPart = '??????'; // default for "unknown"
let dynamicPartName = '??????'; // default for "unknown"

keySchema =
schemas.find(
Expand All @@ -114,30 +114,32 @@ const findMappingSchemaForKey = (

const keyNameParts = keySchema.name.split(':');

const result = {
...keySchema,
name: `${keyNameParts[0]}:${dynamicPartName}`,
valueContent: '?',
key,
};

// replace dynamic placeholder in the map part (e.g: <address>, <bytes32>) with the hex value
if (isDynamicKeyName(keySchema.name)) {
dynamicPart = secondWordHex;
dynamicPartName = secondWordHex;
result['dynamicName'] = `${keyNameParts[0]}:${dynamicPartName}`;
}

// if first 20 bytes of the hash of second word in schema match,
// display the map part as plain word
if (keccak256(keyNameParts[1]).substring(0, 26) === secondWordHex) {
[, dynamicPart] = keyNameParts;
[, dynamicPartName] = keyNameParts;
}

// TODO: Handle the SupportedStandard Keys; we can get the valueContent from the Keys
return {
...keySchema,
valueContent: '?',
name: `${keyNameParts[0]}:${dynamicPart}`,
key,
};
return result;
};

const findMappingWithGroupingSchemaForKey = (
key: string,
schemas: ERC725JSONSchema[],
): ERC725JSONSchema | null => {
): ERC725JSONSchema | DynamicNameSchema | null => {
const keySchema =
schemas.find(
(schema) => schema.key.substring(0, 26) === key.substring(0, 26),
Expand All @@ -149,7 +151,7 @@ const findMappingWithGroupingSchemaForKey = (
return {
...keySchema,
key,
name: `${keySchema.name.substring(
dynamicName: `${keySchema.name.substring(
0,
keySchema.name.lastIndexOf(':'),
)}:${address}`,
Expand Down
6 changes: 6 additions & 0 deletions src/types/ERC725JSONSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,9 @@ export interface ERC725JSONSchema {
valueContent: ERC725JSONSchemaValueContent | string; // string holds '0x1345ABCD...' If the value content are specific bytes, than the returned value is expected to equal those bytes.
valueType: ERC725JSONSchemaValueType | string; // The type of the value. This is used to determine how the value should be encoded / decode (`string` for tuples and CompactBytesArray).
}

// The dynamic part placeholder in the `name` of ERC725JSONSchema is preserved to allow re-encoding after the schema
// of a hex data key got retrieved via `getSchema(...)`.
export interface DynamicNameSchema extends ERC725JSONSchema {
dynamicName: string; // Describes the name of the key where the dynamic part (<address>, <bytes32) is replaced by the actual mapped value.
}

0 comments on commit 12d34d2

Please sign in to comment.