diff --git a/biome.json b/biome.json index 996e03e6..d274c243 100644 --- a/biome.json +++ b/biome.json @@ -9,6 +9,9 @@ "style": { "useImportType": "off", "useNodejsImportProtocol": "off" + }, + "complexity": { + "noForEach": "off" } } }, @@ -23,6 +26,9 @@ "trailingComma": "all" } }, + "organizeImports": { + "enabled": false + }, "files": { "ignore": ["node_modules", "build", "coverage", ".vscode"] } diff --git a/examples/src/instantiation.js b/examples/src/instantiation.js index f3f37f16..bb1f3809 100644 --- a/examples/src/instantiation.js +++ b/examples/src/instantiation.js @@ -1,5 +1,5 @@ -import { ERC725 } from '@erc725/erc725.js'; import Web3 from 'web3'; +import { ERC725 } from '@erc725/erc725.js'; // this is needed because node does not support `fetch` out of the box // isomorphic-fetch is not needed in a browser environment diff --git a/package.json b/package.json index f9faf2ab..82fe37cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@erc725/erc725.js", - "version": "0.24.1-dev.4", + "version": "0.24.1-dev.5", "description": "Library to interact with ERC725 smart contracts", "main": "build/main/src/index.js", "typings": "build/main/src/index.d.ts", diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 036ceed5..f28a6852 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -12,11 +12,11 @@ along with @erc725/erc725.js. If not, see . */ -import { arrToBufArr, bufferToHex } from 'ethereumjs-util'; /* eslint-disable @typescript-eslint/ban-types */ -import { keccak256, numberToHex } from 'web3-utils'; +import { numberToHex, keccak256 } from 'web3-utils'; +import { arrToBufArr, bufferToHex } from 'ethereumjs-util'; -import { Encoding, Method, MethodData } from '../types/Method'; +import { MethodData, Encoding, Method } from '../types/Method'; // https://github.com/ERC725Alliance/ERC725/blob/develop/docs/ERC-725.md#specification export const ERC725Y_INTERFACE_IDS = { @@ -156,50 +156,31 @@ export const HASH_METHODS: { // TODO: These values can be imported from lsp-smartcontracts lib after release // prettier-ignore export const LSP6_DEFAULT_PERMISSIONS = { - CHANGEOWNER: - '0x0000000000000000000000000000000000000000000000000000000000000001', - ADDCONTROLLER: - '0x0000000000000000000000000000000000000000000000000000000000000002', - EDITPERMISSIONS: - '0x0000000000000000000000000000000000000000000000000000000000000004', - ADDEXTENSIONS: - '0x0000000000000000000000000000000000000000000000000000000000000008', - CHANGEEXTENSIONS: - '0x0000000000000000000000000000000000000000000000000000000000000010', - ADDUNIVERSALRECEIVERDELEGATE: - '0x0000000000000000000000000000000000000000000000000000000000000020', - CHANGEUNIVERSALRECEIVERDELEGATE: - '0x0000000000000000000000000000000000000000000000000000000000000040', - REENTRANCY: - '0x0000000000000000000000000000000000000000000000000000000000000080', - SUPER_TRANSFERVALUE: - '0x0000000000000000000000000000000000000000000000000000000000000100', - TRANSFERVALUE: - '0x0000000000000000000000000000000000000000000000000000000000000200', - SUPER_CALL: - '0x0000000000000000000000000000000000000000000000000000000000000400', - CALL: '0x0000000000000000000000000000000000000000000000000000000000000800', - SUPER_STATICCALL: - '0x0000000000000000000000000000000000000000000000000000000000001000', - STATICCALL: - '0x0000000000000000000000000000000000000000000000000000000000002000', - SUPER_DELEGATECALL: - '0x0000000000000000000000000000000000000000000000000000000000004000', - DELEGATECALL: - '0x0000000000000000000000000000000000000000000000000000000000008000', - DEPLOY: '0x0000000000000000000000000000000000000000000000000000000000010000', - SUPER_SETDATA: - '0x0000000000000000000000000000000000000000000000000000000000020000', - SETDATA: '0x0000000000000000000000000000000000000000000000000000000000040000', - ENCRYPT: '0x0000000000000000000000000000000000000000000000000000000000080000', - DECRYPT: '0x0000000000000000000000000000000000000000000000000000000000100000', - SIGN: '0x0000000000000000000000000000000000000000000000000000000000200000', - EXECUTE_RELAY_CALL: - '0x0000000000000000000000000000000000000000000000000000000000400000', - ERC4337_PERMISSION: - '0x0000000000000000000000000000000000000000000000000000000000800000', - ALL_PERMISSIONS: - '0x00000000000000000000000000000000000000000000000000000000007f3f7f', // lsp6 v0.14.0 + CHANGEOWNER : "0x0000000000000000000000000000000000000000000000000000000000000001", + ADDCONTROLLER : "0x0000000000000000000000000000000000000000000000000000000000000002", + EDITPERMISSIONS : "0x0000000000000000000000000000000000000000000000000000000000000004", + ADDEXTENSIONS : "0x0000000000000000000000000000000000000000000000000000000000000008", + CHANGEEXTENSIONS : "0x0000000000000000000000000000000000000000000000000000000000000010", + ADDUNIVERSALRECEIVERDELEGATE : "0x0000000000000000000000000000000000000000000000000000000000000020", + CHANGEUNIVERSALRECEIVERDELEGATE : "0x0000000000000000000000000000000000000000000000000000000000000040", + REENTRANCY : "0x0000000000000000000000000000000000000000000000000000000000000080", + SUPER_TRANSFERVALUE : "0x0000000000000000000000000000000000000000000000000000000000000100", + TRANSFERVALUE : "0x0000000000000000000000000000000000000000000000000000000000000200", + SUPER_CALL : "0x0000000000000000000000000000000000000000000000000000000000000400", + CALL : "0x0000000000000000000000000000000000000000000000000000000000000800", + SUPER_STATICCALL : "0x0000000000000000000000000000000000000000000000000000000000001000", + STATICCALL : "0x0000000000000000000000000000000000000000000000000000000000002000", + SUPER_DELEGATECALL : "0x0000000000000000000000000000000000000000000000000000000000004000", + DELEGATECALL : "0x0000000000000000000000000000000000000000000000000000000000008000", + DEPLOY : "0x0000000000000000000000000000000000000000000000000000000000010000", + SUPER_SETDATA : "0x0000000000000000000000000000000000000000000000000000000000020000", + SETDATA : "0x0000000000000000000000000000000000000000000000000000000000040000", + ENCRYPT : "0x0000000000000000000000000000000000000000000000000000000000080000", + DECRYPT : "0x0000000000000000000000000000000000000000000000000000000000100000", + SIGN : "0x0000000000000000000000000000000000000000000000000000000000200000", + EXECUTE_RELAY_CALL : "0x0000000000000000000000000000000000000000000000000000000000400000", + ERC4337_PERMISSION : "0x0000000000000000000000000000000000000000000000000000000000800000", + ALL_PERMISSIONS : "0x00000000000000000000000000000000000000000000000000000000007f3f7f" // lsp6 v0.14.0 }; export const LSP6_ALL_PERMISSIONS = diff --git a/src/index.test.ts b/src/index.test.ts index 5fc6614f..db4a4853 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -20,27 +20,21 @@ // Tests for the @erc725/erc725.js package import { assert } from 'chai'; -import * as sinon from 'sinon'; import Web3 from 'web3'; +import * as sinon from 'sinon'; import { hexToNumber, leftPad, numberToHex } from 'web3-utils'; // examples of schemas to load (for testing) -import { LSP1Schema, LSP3Schema, LSP6Schema, LSP12Schema } from './schemas'; +import { LSP1Schema, LSP12Schema, LSP3Schema, LSP6Schema } from './schemas'; import ERC725, { checkPermissions, + decodeMappingKey, decodePermissions, encodeKeyName, encodePermissions, supportsInterface, } from '.'; -import { EthereumProvider, HttpProvider } from '../test/mockProviders'; -import { mockSchema } from '../test/mockSchema'; -import { - generateAllData, - generateAllRawData, - generateAllResults, -} from '../test/testHelpers'; import { decodeKeyValue, encodeKey, @@ -48,6 +42,13 @@ import { hashData, } from './lib/utils'; import { ERC725JSONSchema } from './types/ERC725JSONSchema'; +import { EthereumProvider, HttpProvider } from '../test/mockProviders'; +import { mockSchema } from '../test/mockSchema'; +import { + generateAllData, + generateAllRawData, + generateAllResults, +} from '../test/testHelpers'; import 'isomorphic-fetch'; @@ -56,8 +57,8 @@ import { LSP6_DEFAULT_PERMISSIONS, SUPPORTED_VERIFICATION_METHOD_STRINGS, } from './constants/constants'; -import { INTERFACE_IDS_0_12_0 } from './constants/interfaces'; import { decodeKey } from './lib/decodeData'; +import { INTERFACE_IDS_0_12_0 } from './constants/interfaces'; const address = '0x0c03fba782b07bcf810deb3b7f0595024a444f4e'; @@ -615,13 +616,10 @@ describe('Running @erc725/erc725.js tests...', () => { }); }); - const contractVersions = [ + [ { name: 'legacy', interface: ERC725Y_INTERFACE_IDS.legacy }, { name: 'latest', interface: ERC725Y_INTERFACE_IDS['3.0'] }, - ]; - for (let i = 0; i < contractVersions.length; i++) { - const contractVersion = contractVersions[i]; - + ].forEach((contractVersion) => { describe(`Getting all data in schema by provider [ERC725Y ${contractVersion.name}][mock]`, () => { // Construct the full data and results const fullResults = generateAllResults(mockSchema); @@ -843,12 +841,10 @@ describe('Running @erc725/erc725.js tests...', () => { }); } }); - } + }); describe('Getting data by schema element by provider', () => { - for (let index = 0; index < mockSchema.length; index++) { - const schemaElement = mockSchema[index]; - + mockSchema.forEach((schemaElement) => { it(`${schemaElement.name} with web3.currentProvider`, async () => { const returnRawData = generateAllRawData([schemaElement], false); const provider = new HttpProvider({ returnData: returnRawData }, [ @@ -890,7 +886,7 @@ describe('Running @erc725/erc725.js tests...', () => { value: schemaElement.expectedResult, }); }); - } + }); }); describe('Testing utility encoding & decoding functions', () => { @@ -999,11 +995,10 @@ describe('Running @erc725/erc725.js tests...', () => { values: [], }; - for (let i = 0; i < keyValuePairs.length; i++) { - const { key, value } = keyValuePairs[i]; + keyValuePairs.forEach(({ key, value }) => { intendedResult.keys.push(key); intendedResult.values.push(value); - } + }); const erc725 = new ERC725([schemaElement]); @@ -1403,8 +1398,7 @@ describe('Running @erc725/erc725.js tests...', () => { const erc725Instance = new ERC725([]); describe('encodePermissions', () => { - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`Encodes ${testCase.hex} permission correctly`, () => { assert.deepStrictEqual( encodePermissions(testCase.permissions), @@ -1415,7 +1409,7 @@ describe('Running @erc725/erc725.js tests...', () => { testCase.hex, ); }); - } + }); it('Defaults permissions to false if not passed', () => { assert.deepStrictEqual( @@ -1438,13 +1432,11 @@ describe('Running @erc725/erc725.js tests...', () => { describe('Randomized Permissions Encoding', () => { function convertToPermissionBits(permissions: { [key: string]: string }) { const permissionBits = {}; - const entries = Object.entries(permissions); - for (let i = 0; i < entries.length; i++) { - const [key, hexValue] = entries[i]; + Object.entries(permissions).forEach(([key, hexValue]) => { // Convert hex to binary, then find the position of the '1' bit const bitPosition = BigInt(hexValue).toString(2).length - 1; permissionBits[key] = bitPosition; - } + }); return permissionBits; } @@ -1475,14 +1467,12 @@ describe('Running @erc725/erc725.js tests...', () => { // Function to calculate expected hex based on permissions const calculateExpectedHex = (permissions) => { let basePermissions = BigInt(0); - const entries = Object.entries(permissions); - for (let i = 0; i < entries.length; i++) { - const [key, value] = entries[i]; + Object.entries(permissions).forEach(([key, value]) => { if (value) { const bitPosition = permissionBits[key]; basePermissions |= BigInt(1) << BigInt(bitPosition); } - } + }); // Convert to hex string, properly padded return `0x${basePermissions.toString(16).padStart(64, '0')}`; }; @@ -1593,8 +1583,7 @@ describe('Running @erc725/erc725.js tests...', () => { }); describe('decodePermissions', () => { - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`Decodes ${testCase.hex} permission correctly`, () => { assert.deepStrictEqual( decodePermissions(testCase.hex), @@ -1606,7 +1595,7 @@ describe('Running @erc725/erc725.js tests...', () => { testCase.permissions, ); }); - } + }); it('Decodes 0xfff...fff admin permission correctly', () => { assert.deepStrictEqual( decodePermissions( @@ -1821,7 +1810,7 @@ describe('decodeMappingKey', () => { it('is available on instance and class', () => { assert.deepStrictEqual( - ERC725.decodeMappingKey( + decodeMappingKey( '0x35e6950bc8d21a1699e50000cafecafecafecafecafecafecafecafecafecafe', 'MyKeyName:
', ), diff --git a/src/index.ts b/src/index.ts index badd0a79..06a99e3d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,48 +20,48 @@ * @date 2020 */ -import HttpProvider from 'web3-providers-http'; import { isAddress } from 'web3-utils'; +import HttpProvider from 'web3-providers-http'; import { ProviderWrapper } from './provider/providerWrapper'; import { - convertIPFSGatewayUrl, - duplicateMultiTypeERC725SchemaEntry, encodeData, + convertIPFSGatewayUrl, generateSchemasFromDynamicKeys, + duplicateMultiTypeERC725SchemaEntry, } from './lib/utils'; -import { isValidSignature } from './lib/isValidSignature'; import { getSchema } from './lib/schemaParser'; +import { isValidSignature } from './lib/isValidSignature'; import { DEFAULT_GAS_VALUE } from './constants/constants'; import { encodeKeyName, isDynamicKeyName } from './lib/encodeKeyName'; -import { decodeData } from './lib/decodeData'; -import { decodeMappingKey } from './lib/decodeMappingKey'; -import { _supportsInterface, checkPermissions } from './lib/detector'; -import { decodeValueType, encodeValueType } from './lib/encoder'; -import { getData } from './lib/getData'; -import { getDataFromExternalSources } from './lib/getDataFromExternalSources'; -import { decodePermissions, encodePermissions } from './lib/permissions'; // Types import { ERC725Config, ERC725Options } from './types/Config'; +import { Permissions } from './types/Method'; import { ERC725JSONSchema, ERC725JSONSchemaKeyType, ERC725JSONSchemaValueContent, ERC725JSONSchemaValueType, } from './types/ERC725JSONSchema'; -import { GetDataDynamicKey, GetDataInput } from './types/GetData'; -import { Permissions } from './types/Method'; import { DecodeDataInput, DecodeDataOutput, EncodeDataInput, FetchDataOutput, } from './types/decodeData'; +import { GetDataDynamicKey, GetDataInput } from './types/GetData'; +import { decodeData } from './lib/decodeData'; +import { getDataFromExternalSources } from './lib/getDataFromExternalSources'; import { DynamicKeyPart, DynamicKeyParts } from './types/dynamicKeys'; +import { getData } from './lib/getData'; +import { decodeValueType, encodeValueType } from './lib/encoder'; +import { checkPermissions, internalSupportsInterface } from './lib/detector'; +import { decodeMappingKey } from './lib/decodeMappingKey'; +import { encodePermissions, decodePermissions } from './lib/permissions'; export { ERC725JSONSchema, @@ -121,7 +121,7 @@ export async function supportsInterface( throw new Error('Missing RPC URL'); } - return _supportsInterface(interfaceIdOrName, { + return internalSupportsInterface(interfaceIdOrName, { address: options.address, provider: options.provider || @@ -595,7 +595,7 @@ export class ERC725 { async supportsInterface(interfaceIdOrName: string): Promise { const { address, provider } = this.getAddressAndProvider(); - return _supportsInterface(interfaceIdOrName, { + return internalSupportsInterface(interfaceIdOrName, { address, provider, }); diff --git a/src/lib/decodeData.test.ts b/src/lib/decodeData.test.ts index c69dc41b..e979c70e 100644 --- a/src/lib/decodeData.test.ts +++ b/src/lib/decodeData.test.ts @@ -308,8 +308,7 @@ describe('tuple', () => { }, ]; // TODO: add more cases? Address, etc. - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it('decodes tuple values', () => { expect( decodeTupleKeyValue( @@ -319,7 +318,7 @@ describe('tuple', () => { ), ).to.eql(testCase.decodedValue); }); - } + }); }); describe('isValidTupleValueType', () => { @@ -387,8 +386,7 @@ describe('tuple', () => { }, ]; - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`detects valueType: ${testCase.valueType} valueContent: ${ testCase.valueContent } as ${testCase.isTuple ? 'tuple' : 'non tuple'}`, () => { @@ -403,6 +401,6 @@ describe('tuple', () => { isValidTuple(testCase.valueType, testCase.valueContent), ).to.equal(testCase.isTuple); }); - } + }); }); }); diff --git a/src/lib/decodeData.ts b/src/lib/decodeData.ts index 85819b56..8e9532ef 100644 --- a/src/lib/decodeData.ts +++ b/src/lib/decodeData.ts @@ -22,14 +22,14 @@ import { isHexStrict } from 'web3-utils'; import { COMPACT_BYTES_ARRAY_STRING } from '../constants/constants'; +import { DecodeDataInput, DecodeDataOutput } from '../types/decodeData'; import { ALL_VALUE_TYPES, ERC725JSONSchema, isValidValueType, } from '../types/ERC725JSONSchema'; -import { DecodeDataInput, DecodeDataOutput } from '../types/decodeData'; import { isDynamicKeyName } from './encodeKeyName'; -import { decodeValueType, valueContentEncodingMap } from './encoder'; +import { valueContentEncodingMap, decodeValueType } from './encoder'; import { getSchemaElement } from './getSchemaElement'; import { decodeKeyValue, encodeArrayKey } from './utils'; diff --git a/src/lib/decodeMappingKey.test.ts b/src/lib/decodeMappingKey.test.ts index 9a5f619d..3f804b90 100644 --- a/src/lib/decodeMappingKey.test.ts +++ b/src/lib/decodeMappingKey.test.ts @@ -145,8 +145,7 @@ describe('decodeDynamicKeyParts', () => { ]; it('decodes each dynamic key part', () => { - for (let i = 0; i < records.length; i++) { - const record = records[i]; + records.forEach((record) => { const decodedDynamicKeyParts = decodeMappingKey( record.key.encoded, record.key.name, @@ -158,7 +157,7 @@ describe('decodeDynamicKeyParts', () => { expect(keyPart.type).to.equal(decodedDynamicKeyParts[index].type); expect(keyPart.value).to.equal(decodedDynamicKeyParts[index].value); }); - } + }); }); it('decodes each dynamic key part when schema as a param', () => { diff --git a/src/lib/decodeMappingKey.ts b/src/lib/decodeMappingKey.ts index 0fd6d07c..5f2b6cd9 100644 --- a/src/lib/decodeMappingKey.ts +++ b/src/lib/decodeMappingKey.ts @@ -19,9 +19,9 @@ */ import { isHex, padLeft } from 'web3-utils'; +import { decodeValueType } from './encoder'; import { ERC725JSONSchema } from '../types/ERC725JSONSchema'; import { DynamicKeyPart } from '../types/dynamicKeys'; -import { decodeValueType } from './encoder'; function isDynamicKeyPart(keyPartName: string): boolean { return ( diff --git a/src/lib/detector.test.ts b/src/lib/detector.test.ts index ec418d25..d397feae 100644 --- a/src/lib/detector.test.ts +++ b/src/lib/detector.test.ts @@ -24,7 +24,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { INTERFACE_IDS_0_12_0 } from '../constants/interfaces'; -import { _supportsInterface, checkPermissions } from './detector'; +import { internalSupportsInterface, checkPermissions } from './detector'; describe('supportsInterface', () => { it('it should return true if the contract supports the interface with name', async () => { @@ -37,10 +37,13 @@ describe('supportsInterface', () => { .withArgs(contractAddress, INTERFACE_IDS_0_12_0[interfaceName]) .returns(Promise.resolve(true)); - const doesSupportInterface = await _supportsInterface(interfaceName, { - address: contractAddress, - provider: providerStub, - }); + const doesSupportInterface = await internalSupportsInterface( + interfaceName, + { + address: contractAddress, + provider: providerStub, + }, + ); expect(doesSupportInterface).to.be.true; }); @@ -55,7 +58,7 @@ describe('supportsInterface', () => { .withArgs(contractAddress, interfaceId) .returns(Promise.resolve(true)); - const doesSupportInterface = await _supportsInterface(interfaceId, { + const doesSupportInterface = await internalSupportsInterface(interfaceId, { address: contractAddress, provider: providerStub, }); diff --git a/src/lib/detector.ts b/src/lib/detector.ts index e6b407b2..1fae16a1 100644 --- a/src/lib/detector.ts +++ b/src/lib/detector.ts @@ -36,7 +36,7 @@ import { * @param options Object with address and RPC URL. * @returns {Promise} if interface is supported. */ -export const _supportsInterface = async ( +export const internalSupportsInterface = async ( interfaceIdOrName: string, options: AddressProviderOptions, ): Promise => { diff --git a/src/lib/encodeKeyName.test.ts b/src/lib/encodeKeyName.test.ts index acb5688e..31e44922 100644 --- a/src/lib/encodeKeyName.test.ts +++ b/src/lib/encodeKeyName.test.ts @@ -214,15 +214,14 @@ describe('encodeKeyName', () => { }, ]; - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`encodes ${testCase.keyName} key name correctly`, () => { assert.deepStrictEqual( encodeKeyName(testCase.keyName, testCase.dynamicKeyParts), testCase.expectedKey, ); }); - } + }); it('throws if trying to encode a dynamic key without any variable', () => { assert.throws(() => encodeKeyName('MyDynamicKey:
')); @@ -289,8 +288,7 @@ describe('isDynamicKeyName', () => { }, ]; - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`detects ${ testCase.isDynamicKeyName ? 'dynamic' : 'non-dynamic' } key name: ${testCase.keyName} correctly`, () => { @@ -299,7 +297,7 @@ describe('isDynamicKeyName', () => { testCase.isDynamicKeyName, ); }); - } + }); }); describe('encodeDynamicKeyPart', () => { @@ -385,15 +383,14 @@ describe('encodeDynamicKeyPart', () => { }, ]; - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`encodes: ${testCase.value} of type: ${testCase.type} correctly`, () => { assert.deepStrictEqual( encodeDynamicKeyPart(testCase.type, testCase.value, testCase.bytes), testCase.expectedEncoding, ); }); - } + }); it('throws if is called with non hex values', () => { assert.throws(() => @@ -438,15 +435,14 @@ describe('generateDynamicKeyName', () => { }, ]; - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`generates key name: ${testCase.keyName} correctly`, () => { assert.deepStrictEqual( generateDynamicKeyName(testCase.keyName, testCase.dynamicKeyParts), testCase.expectedKeyName, ); }); - } + }); it('throws if encoding with wrong number of dynamic values', () => { assert.throws(() => diff --git a/src/lib/encodeKeyName.ts b/src/lib/encodeKeyName.ts index 863e56d4..24328a64 100644 --- a/src/lib/encodeKeyName.ts +++ b/src/lib/encodeKeyName.ts @@ -26,8 +26,8 @@ import { padLeft, } from 'web3-utils'; -import { DynamicKeyParts } from '../types/dynamicKeys'; import { guessKeyTypeFromKeyName } from './utils'; +import { DynamicKeyParts } from '../types/dynamicKeys'; // https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md#mapping diff --git a/src/lib/encoder.test.ts b/src/lib/encoder.test.ts index 94bcdf3b..8ddf60d3 100644 --- a/src/lib/encoder.test.ts +++ b/src/lib/encoder.test.ts @@ -14,29 +14,29 @@ /* eslint-disable no-unused-expressions */ -import { assert, expect } from 'chai'; +import { expect, assert } from 'chai'; import { keccak256, - padLeft, + utf8ToHex, stripHexPrefix, toBN, toHex, - utf8ToHex, + padLeft, } from 'web3-utils'; +import { + valueContentEncodingMap, + encodeValueType, + decodeValueType, + encodeValueContent, + decodeValueContent, +} from './encoder'; import { NONE_VERIFICATION_METHOD, SUPPORTED_VERIFICATION_METHOD_HASHES, SUPPORTED_VERIFICATION_METHOD_STRINGS, } from '../constants/constants'; import { URLDataToEncode, URLDataWithHash } from '../types'; -import { - decodeValueContent, - decodeValueType, - encodeValueContent, - encodeValueType, - valueContentEncodingMap, -} from './encoder'; describe('encoder', () => { describe('valueType', () => { @@ -64,8 +64,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.decodedValue} as ${testCase.valueType}`, () => { const encodedValue = encodeValueType( testCase.valueType, @@ -78,7 +77,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); }); describe('`bytes4` type', () => { @@ -95,8 +94,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.decodedValue} as ${testCase.valueType}`, () => { const encodedValue = encodeValueType( testCase.valueType, @@ -109,7 +107,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); const errorEncodingTestCases = [ { @@ -130,14 +128,13 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < errorEncodingTestCases.length; i++) { - const testCase = errorEncodingTestCases[i]; + errorEncodingTestCases.forEach((testCase) => { it(`should throw when trying to encode ${testCase.input} as ${testCase.valueType}`, async () => { assert.throws(() => encodeValueType(testCase.valueType, testCase.input), ); }); - } + }); // these cases are not symetric. The input is converted + encoded. // When decoding, we do not get the same input back, but its bytes4 hex representation @@ -156,8 +153,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < oneWayEncodingTestCases.length; i++) { - const testCase = oneWayEncodingTestCases[i]; + oneWayEncodingTestCases.forEach((testCase) => { it(`encodes one way \`input\` = ${testCase.input} as ${testCase.valueType}, but does not decode back as the same input`, async () => { const encodedValue = encodeValueType( testCase.valueType, @@ -170,7 +166,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); // these cases are not symetric and right pad the value const rightPaddedTestCases = [ @@ -188,8 +184,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < rightPaddedTestCases.length; i++) { - const testCase = rightPaddedTestCases[i]; + rightPaddedTestCases.forEach((testCase) => { it(`encodes + right pad \`input\` = ${testCase.input} as ${testCase.valueType} padded on the right with \`00\`s`, async () => { const encodedValue = encodeValueType( testCase.valueType, @@ -202,7 +197,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); }); describe('`bytes32` type', () => { @@ -223,8 +218,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.decodedValue} as ${testCase.valueType}`, () => { const encodedValue = encodeValueType( testCase.valueType, @@ -237,7 +231,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); const errorEncodingTestCases = [ { @@ -262,14 +256,13 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < errorEncodingTestCases.length; i++) { - const testCase = errorEncodingTestCases[i]; + errorEncodingTestCases.forEach((testCase) => { it(`should throw when trying to encode ${testCase.input} as ${testCase.valueType}`, async () => { assert.throws(() => encodeValueType(testCase.valueType, testCase.input), ); }); - } + }); const oneWayEncodingTestCases = [ { @@ -290,8 +283,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < oneWayEncodingTestCases.length; i++) { - const testCase = oneWayEncodingTestCases[i]; + oneWayEncodingTestCases.forEach((testCase) => { it(`encodes one way \`input\` = ${testCase.input} as ${testCase.valueType}, but does not decode back as the same input`, async () => { const encodedValue = encodeValueType( testCase.valueType, @@ -304,7 +296,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); // these cases are not symetric and right pad the value const rightPaddedTestCases = [ @@ -326,8 +318,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < rightPaddedTestCases.length; i++) { - const testCase = rightPaddedTestCases[i]; + rightPaddedTestCases.forEach((testCase) => { it(`encodes + right pad \`input\` = ${testCase.input} as ${testCase.valueType} padded on the right with \`00\`s`, async () => { const encodedValue = encodeValueType( testCase.valueType, @@ -340,7 +331,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); }); describe('`uintN` type', () => { @@ -383,8 +374,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.decodedValue} as ${testCase.valueType}`, () => { const encodedValue = encodeValueType( testCase.valueType, @@ -397,7 +387,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); it('should throw an error when trying to encode/decode with an invalid `uintN` type', async () => { for (let ii = 1; ii <= 256; ii++) { @@ -436,8 +426,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.decodedValue} as ${testCase.valueType}`, () => { const encodedValue = encodeValueType( testCase.valueType, @@ -450,7 +439,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); it('should encode each letter in a number as a utf8 character, and decode it back as a string', () => { const testCase = { @@ -482,8 +471,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.decodedValue} as ${testCase.valueType}`, () => { const encodedValue = encodeValueType( testCase.valueType, @@ -496,7 +484,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); const errorEncodingTestCases = [ { @@ -509,14 +497,13 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < errorEncodingTestCases.length; i++) { - const testCase = errorEncodingTestCases[i]; + errorEncodingTestCases.forEach((testCase) => { it(`should throw when trying to encode ${testCase.input} as ${testCase.valueType}`, async () => { assert.throws(() => encodeValueType(testCase.valueType, testCase.input), ); }); - } + }); }); describe('`bytes` type', () => { @@ -540,8 +527,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.decodedValue} as ${testCase.valueType}`, () => { const encodedValue = encodeValueType( testCase.valueType, @@ -554,7 +540,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); }); describe('arrays `[]` of static types', () => { @@ -630,8 +616,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.decodedValue} as ${testCase.valueType}`, () => { const encodedValue = encodeValueType( testCase.valueType, @@ -644,7 +629,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); }); describe('when encoding a value that exceeds the maximal length of bytes than its type', () => { @@ -658,14 +643,13 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it('should throw', async () => { assert.throws(() => encodeValueType(testCase.valueType, testCase.decodedValue), ); }); - } + }); }); describe('when encoding/decoding a value that is not a number as a `uint128`', () => { @@ -743,8 +727,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < validTestCases.length; i++) { - const testCase = validTestCases[i]; + validTestCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.decodedValue} as ${testCase.valueType}`, () => { const encodedValue = encodeValueType( testCase.valueType, @@ -757,7 +740,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); describe('when encoding bytes[CompactBytesArray]', () => { it('should encode `0x` elements as `0x0000`', async () => { @@ -979,8 +962,7 @@ describe('encoder', () => { }, ]; - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`encodes/decodes: ${testCase.valueContent}`, () => { const encodedValue = encodeValueContent( testCase.valueContent, @@ -1000,7 +982,7 @@ describe('encoder', () => { testCase.decodedValue, ); }); - } + }); it('encodes/decodes: JSONURL', () => { const dataToEncode: URLDataToEncode = { diff --git a/src/lib/encoder.ts b/src/lib/encoder.ts index 94712faf..300852c4 100644 --- a/src/lib/encoder.ts +++ b/src/lib/encoder.ts @@ -28,8 +28,6 @@ import AbiCoder from 'web3-eth-abi'; import { - bytesToHex, - hexToBytes, hexToNumber, hexToUtf8, isAddress, @@ -37,28 +35,30 @@ import { keccak256, numberToHex, padLeft, - stripHexPrefix, - toBN, toChecksumAddress, - toHex, utf8ToHex, + stripHexPrefix, + hexToBytes, + bytesToHex, + toHex, + toBN, } from 'web3-utils'; import { URLDataToEncode, URLDataWithHash, Verification } from '../types'; import { AssetURLEncode } from '../types/encodeData'; import { - NONE_VERIFICATION_METHOD, SUPPORTED_VERIFICATION_METHOD_STRINGS, + NONE_VERIFICATION_METHOD, } from '../constants/constants'; -import { ERC725JSONSchemaValueType } from '../types/ERC725JSONSchema'; import { - countNumberOfBytes, - countSignificantBits, getVerificationMethod, hashData, + countNumberOfBytes, isValidUintSize, + countSignificantBits, } from './utils'; +import { ERC725JSONSchemaValueType } from '../types/ERC725JSONSchema'; const abiCoder = AbiCoder; diff --git a/src/lib/getDataFromExternalSources.test.ts b/src/lib/getDataFromExternalSources.test.ts index 6dcec1af..c8cd7659 100644 --- a/src/lib/getDataFromExternalSources.test.ts +++ b/src/lib/getDataFromExternalSources.test.ts @@ -18,8 +18,8 @@ import { expect } from 'chai'; import { ERC725JSONSchema } from '../types/ERC725JSONSchema'; -import { DecodeDataOutput } from '../types/decodeData'; import { getDataFromExternalSources } from './getDataFromExternalSources'; +import { DecodeDataOutput } from '../types/decodeData'; const IPFS_GATEWAY_MOCK = 'https://mock-ipfs.mock/ipfs/'; diff --git a/src/lib/getDataFromExternalSources.ts b/src/lib/getDataFromExternalSources.ts index 599dd881..dd6416ff 100644 --- a/src/lib/getDataFromExternalSources.ts +++ b/src/lib/getDataFromExternalSources.ts @@ -21,13 +21,13 @@ import { arrToBufArr } from 'ethereumjs-util'; -import { URLDataWithHash } from '../types'; -import { ERC725JSONSchema } from '../types/ERC725JSONSchema'; import { DecodeDataOutput, GetDataExternalSourcesOutput, } from '../types/decodeData'; +import { ERC725JSONSchema } from '../types/ERC725JSONSchema'; import { isDataAuthentic, patchIPFSUrlsIfApplicable } from './utils'; +import { URLDataWithHash } from '../types'; export const getDataFromExternalSources = ( schemas: ERC725JSONSchema[], diff --git a/src/lib/getSchemaElement.ts b/src/lib/getSchemaElement.ts index cbe8c3c7..139f70d1 100644 --- a/src/lib/getSchemaElement.ts +++ b/src/lib/getSchemaElement.ts @@ -18,8 +18,8 @@ */ import { isHex, isHexStrict } from 'web3-utils'; -import { ERC725JSONSchema } from '../types/ERC725JSONSchema'; import { DynamicKeyParts } from '../types/dynamicKeys'; +import { ERC725JSONSchema } from '../types/ERC725JSONSchema'; import { encodeKeyName, generateDynamicKeyName, diff --git a/src/lib/permissions.ts b/src/lib/permissions.ts index b6e405df..15647f5b 100644 --- a/src/lib/permissions.ts +++ b/src/lib/permissions.ts @@ -1,4 +1,4 @@ -import { hexToNumber, leftPad, toHex } from 'web3-utils'; +import { hexToNumber, leftPad, numberToHex } from 'web3-utils'; import { LSP6_DEFAULT_PERMISSIONS } from '../constants/constants'; import { Permissions } from '../types/Method'; @@ -26,7 +26,7 @@ export function encodePermissions(permissions: Permissions): string { } } // Convert the final BigInt permission value back to a hex string, properly padded - return leftPad(toHex(basePermissions.toString()), 64); + return leftPad(numberToHex(basePermissions.toString()), 64); } export function decodePermissions(permissionHex: string) { diff --git a/src/lib/utils.test.ts b/src/lib/utils.test.ts index 30000c3a..90212974 100644 --- a/src/lib/utils.test.ts +++ b/src/lib/utils.test.ts @@ -14,8 +14,8 @@ /* eslint-disable no-unused-expressions */ -import assert from 'assert'; import { expect } from 'chai'; +import assert from 'assert'; import { keccak256, utf8ToHex } from 'web3-utils'; import { @@ -26,22 +26,22 @@ import { import { GetDataDynamicKey } from '../types/GetData'; import { SUPPORTED_VERIFICATION_METHOD_STRINGS } from '../constants/constants'; -import { decodeKey } from './decodeData'; -import { isDynamicKeyName } from './encodeKeyName'; import { - convertIPFSGatewayUrl, - countSignificantBits, + guessKeyTypeFromKeyName, + isDataAuthentic, + encodeKeyValue, decodeKeyValue, - duplicateMultiTypeERC725SchemaEntry, - encodeData, encodeKey, - encodeKeyValue, - encodeTupleKeyValue, + encodeData, + convertIPFSGatewayUrl, generateSchemasFromDynamicKeys, - guessKeyTypeFromKeyName, - isDataAuthentic, + encodeTupleKeyValue, + duplicateMultiTypeERC725SchemaEntry, splitMultiDynamicKeyNamePart, + countSignificantBits, } from './utils'; +import { isDynamicKeyName } from './encodeKeyName'; +import { decodeKey } from './decodeData'; describe('utils', () => { describe('encodeKey/decodeKey', () => { @@ -223,8 +223,7 @@ describe('utils', () => { }, ]; - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`encodes/decodes keyType Array / tuples (valueContent: ${testCase.schema.valueContent}, valueType: ${testCase.schema.valueType}`, () => { assert.deepStrictEqual( encodeKey(testCase.schema as ERC725JSONSchema, testCase.decodedValue), @@ -236,7 +235,7 @@ describe('utils', () => { testCase.decodedValue, ); }); - } + }); it('should encode the array length only if passing a number', async () => { const schema: ERC725JSONSchema = { @@ -267,12 +266,11 @@ describe('utils', () => { { value: '0x1000', result: 13 }, { value: '0x000f', result: 4 }, ]; - for (let i = 0; i < testCases.length; i++) { - const { value, result } = testCases[i]; + testCases.forEach(({ value, result }) => { it(`should count the number of bits in ${value}`, () => { assert.equal(countSignificantBits(value), result); }); - } + }); }); describe('encodeKeyValue/decodeKeyValue', () => { @@ -384,8 +382,7 @@ describe('utils', () => { }, ]; - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`encodes correctly valueContent ${testCase.valueContent} to valueType: ${testCase.valueType}`, () => { assert.strictEqual( encodeKeyValue( @@ -406,7 +403,7 @@ describe('utils', () => { testCase.decodedValue, ); }); - } + }); }); describe('encodeTupleKeyValue', () => { @@ -419,8 +416,7 @@ describe('utils', () => { }, ]; // we may need to add more test cases! Address, etc. - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it('encodes tuple values', () => { expect( encodeTupleKeyValue( @@ -430,7 +426,7 @@ describe('utils', () => { ), ).to.eq(testCase.encodedValue); }); - } + }); }); describe('encodeArrayKey', () => { @@ -945,15 +941,14 @@ describe('utils', () => { }, ]; - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i]; + testCases.forEach((testCase) => { it(`guesses ${testCase.keyType}`, () => { assert.deepStrictEqual( guessKeyTypeFromKeyName(testCase.keyName), testCase.keyType, ); }); - } + }); }); describe('convertIPFSGatewayUrl', () => { @@ -1023,13 +1018,12 @@ describe('utils', () => { expect(generatedSchemas.length).to.equal(keys.length); - for (let i = 0; i < generatedSchemas.length; i++) { - const schema = generatedSchemas[i]; + generatedSchemas.forEach((schema) => { expect( isDynamicKeyName(schema.name), 'generated schema key should not be dynamic', ).to.be.false; - } + }); }); }); diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 6b3e8fcf..155c0b72 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -30,8 +30,8 @@ import { } from 'web3-utils'; import { - EncodeDataReturn, URLDataToEncode, + EncodeDataReturn, URLDataWithHash, Verification, } from '../types'; @@ -42,16 +42,11 @@ import { } from '../types/ERC725JSONSchema'; import { - COMPACT_BYTES_ARRAY_STRING, HASH_METHODS, SUPPORTED_VERIFICATION_METHODS, SUPPORTED_VERIFICATION_METHODS_LIST, + COMPACT_BYTES_ARRAY_STRING, } from '../constants/constants'; -import { GetDataDynamicKey } from '../types/GetData'; -import { EncodeDataInput } from '../types/decodeData'; -import { AssetURLEncode } from '../types/encodeData'; -import { isValidTuple } from './decodeData'; -import { isDynamicKeyName } from './encodeKeyName'; import { decodeValueContent, decodeValueType, @@ -59,7 +54,12 @@ import { encodeValueType, valueContentEncodingMap as valueContentMap, } from './encoder'; +import { AssetURLEncode } from '../types/encodeData'; +import { isDynamicKeyName } from './encodeKeyName'; import { getSchemaElement } from './getSchemaElement'; +import { EncodeDataInput } from '../types/decodeData'; +import { GetDataDynamicKey } from '../types/GetData'; +import { isValidTuple } from './decodeData'; /** * diff --git a/src/provider/providerWrapper.ts b/src/provider/providerWrapper.ts index fde376ec..9ec748e4 100644 --- a/src/provider/providerWrapper.ts +++ b/src/provider/providerWrapper.ts @@ -24,11 +24,11 @@ import AbiCoder from 'web3-eth-abi'; -import { ERC725Y_INTERFACE_IDS, ERC725_VERSION } from '../constants/constants'; -import { constructJSONRPC, decodeResult } from '../lib/provider-wrapper-utils'; import { JsonRpc } from '../types/JsonRpc'; import { Method } from '../types/Method'; +import { constructJSONRPC, decodeResult } from '../lib/provider-wrapper-utils'; import { ProviderTypes } from '../types/provider'; +import { ERC725_VERSION, ERC725Y_INTERFACE_IDS } from '../constants/constants'; const abiCoder = AbiCoder;