diff --git a/docs/getting-started.md b/docs/getting-started.md
index d2527739..28e52c46 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -134,6 +134,10 @@ const verifiableURI = encodeDataSourceWithHash(
Try running the code snippets below within your browser using [StackBlitz](https://stackblitz.com/edit/erc725js-instantiation?devtoolsheight=66&file=index.js).
:::
+The _erc725.js_ contains multiple functionalities such as reading and decoding data. A full list is available under the [**Methods**](./methods.md) page.
+
+For fetching data, it is possible to query one data key (as a `string` name) or multiple data keys at once by passing an array parameter, as shown below.
+
```js
await erc725.getOwner();
// > '0x28D25E70819140daF65b724158D00c373D1a18ee'
diff --git a/docs/methods.md b/docs/methods.md
index 953f3062..7db0ba5e 100644
--- a/docs/methods.md
+++ b/docs/methods.md
@@ -3,7 +3,7 @@ sidebar_position: 1
title: 'Methods'
---
-import CodeSandbox from "../../../src/components/CodeSandbox";
+import CodeSandbox from "@site/src/components/CodeSandbox";
@@ -508,6 +508,64 @@ ERC725.encodeData(
+
+ Encode a tuple of CompactBytesArray
+
+```ts title="Encode a tuple of CompactBytesArray"
+import ERC725 from '@erc725/erc725.js';
+
+const schemas = [
+{
+ name: 'AddressPermissions:AllowedCalls:',
+ key: '0x4b80742de2bf393a64c70000',
+ keyType: 'MappingWithGrouping',
+ valueType: '(bytes4,address,bytes4,bytes4)[CompactBytesArray]',
+ valueContent: '(BitArray,Address,Bytes4,Bytes4)',
+ }
+];
+
+ERC725.encodeData(
+ [
+ {
+ keyName: 'AddressPermissions:AllowedCalls:',
+ dynamicKeyParts: "0xcafecafecafecafecafecafecafecafecafecafe"
+ value: [
+ '0x00000003', // CALL and TRANSFERVALUE
+ '0xCA41e4ea94c8fA99889c8EA2c8948768cBaf4bc0', // addresses are decoded as checksummed
+ '0x3e89ad98', // LSP0 interface ID
+ '0xffffffff', // any function
+ ],
+ [
+ '0x00000002', // CALL only
+ '0xF70Ce3b58f275A4c28d06C98615760dDe774DE57',
+ '0xffffffff', // any standard interface ID
+ '0x760d9bba', // function selector of `transfer(address,address,uint256,bool,bytes)`
+ ],
+ [
+ '0x00000001', // TRANSFERVALUE only
+ '0xd3236aa1B8A4dDe5eA375fd1F2Fb5c354e686c9f',
+ '0xffffffff', // any standard interface ID
+ '0xffffffff', // any function
+ ],
+ },
+ ],
+ schemas,
+);
+/**
+{
+ keys: [
+ '0x4b80742de2bf393a64c70000cafecafecafecafecafecafecafecafecafecafe', // -> data key for `AddressPermissions:AllowedCalls:0xcafecafecafecafecafecafecafecafecafecafe`
+ ],
+ values: [
+ '0x002000000003ca41e4ea94c8fa99889c8ea2c8948768cbaf4bc03e89ad98ffffffff002000000002f70ce3b58f275a4c28d06c98615760dde774de57ffffffff760d9bba002000000001d3236aa1b8a4dde5ea375fd1f2fb5c354e686c9fffffffffffffffff', // (bytes4,address,bytes4,bytes4)[CompactBytesArray]
+ ],
+}
+*/
+
+```
+
+
+
---
### encodeKeyName
@@ -965,6 +1023,61 @@ ERC725.decodeData(
*/
```
+#### Tuple of CompactBytesArray Example
+
+```ts title="Decode a tuple of CompactBytesArray"
+import ERC725 from '@erc725/erc725.js';
+
+const schemas = [
+ {
+ name: 'AddressPermissions:AllowedCalls:
',
+ key: '0x4b80742de2bf393a64c70000',
+ keyType: 'MappingWithGrouping',
+ valueType: '(bytes4,address,bytes4,bytes4)[CompactBytesArray]',
+ valueContent: '(BitArray,Address,Bytes4,Bytes4)',
+ }
+];
+
+ERC725.decodeData(
+ [
+ {
+ keyName: 'AddressPermissions:AllowedCalls:',
+ dynamicKeyParts: "0xcafecafecafecafecafecafecafecafecafecafe"
+ value: '0x002000000003ca41e4ea94c8fa99889c8ea2c8948768cbaf4bc03e89ad98ffffffff002000000002f70ce3b58f275a4c28d06c98615760dde774de57ffffffff760d9bba002000000001d3236aa1b8a4dde5ea375fd1f2fb5c354e686c9fffffffffffffffff'
+ },
+ ],
+ schemas,
+);
+
+/**
+{
+ key: '0x4b80742de2bf393a64c70000cafecafecafecafecafecafecafecafecafecafe',
+ name: 'AddressPermissions:AllowedCalls:cafecafecafecafecafecafecafecafecafecafe',
+ value: [
+ [
+ '0x00000003', // CALL and TRANSFERVALUE
+ '0xCA41e4ea94c8fA99889c8EA2c8948768cBaf4bc0', // addresses are decoded as checksummed
+ '0x3e89ad98', // LSP0 interface ID
+ '0xffffffff', // any function
+ ],
+ [
+ '0x00000002', // CALL only
+ '0xF70Ce3b58f275A4c28d06C98615760dDe774DE57',
+ '0xffffffff', // any standard interface ID
+ '0x760d9bba', // function selector of `transfer(address,address,uint256,bool,bytes)`
+ ],
+ [
+ '0x00000001', // TRANSFERVALUE only
+ '0xd3236aa1B8A4dDe5eA375fd1F2Fb5c354e686c9f',
+ '0xffffffff', // any standard interface ID
+ '0xffffffff', // any function
+ ]
+ ]
+}
+*/
+
+```
+
### decodeValueType
```js
diff --git a/docs/schemas.md b/docs/schemas.md
index 2f7f0b21..143f2f98 100644
--- a/docs/schemas.md
+++ b/docs/schemas.md
@@ -4,13 +4,17 @@ sidebar_position: 2
# Schemas
-The `@erc725/erc725.js` library contains a range of standard [LSP ERC725 JSON schemas](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md).
+:::info 📄 Schema Specification
-Schemas allow erc725.js to know how to decode and encode data written in an [ERC725Y](https://eips.ethereum.org/EIPS/eip-725) smart contract.
+For more details on schemas, see the [**official specification** of the LSP2 ERC725 JSON schemas](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-2-ERC725YJSONSchema.md) standard specification
-_A quick reference for keys used in schema definitions can be seen below_
+:::
+
+The ⚒️ [erc725.js](https://npmjs.com/package/@erc725/erc725.js) library works with [ERC725Y JSON schemas](../../standards/generic-standards/lsp2-json-schema). These schemas are JSON structures that tell developers and programs how to decode and encode 🗂️ [ERC725Y data keys](../../standards/lsp-background/erc725#erc725y-generic-data-keyvalue-store) from any [ERC725Y](https://eips.ethereum.org/EIPS/eip-725) smart contract.. You need to load the required schemas of the data keys you want to fetch when initializing the `ERC725` class.
-[Official Documentation](https://github.com/lukso-network/LIPs/blob/master/LSPs/LSP-2-ERC725YJSONSchema.md).
+The most common and standard schemas are [available](../../tools/erc725js/schemas.md) directly within the _erc725.js_ library. But you can also create and load your own ERC725Y JSON schemas if you want to use custom data keys.
+
+_A quick reference for keys used in schema definitions can be seen below_
- `name`: An arbitrary name
- `key`: The sha3 hash of the name
diff --git a/examples/package-lock.json b/examples/package-lock.json
index 129175bd..334ab741 100644
--- a/examples/package-lock.json
+++ b/examples/package-lock.json
@@ -3858,6 +3858,11 @@
"@scure/bip39": "1.2.2"
}
},
+ "../node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
+ },
"../node_modules/execa": {
"version": "5.1.1",
"dev": true,
@@ -9308,10 +9313,11 @@
}
},
"../node_modules/web3-errors": {
- "version": "1.1.4",
- "license": "LGPL-3.0",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.2.0.tgz",
+ "integrity": "sha512-58Kczou5zyjcm9LuSs5Hrm6VrG8t9p2J8X0yGArZrhKNPZL66gMGkOUpPx+EopE944Sk4yE+Q25hKv4H5BH+kA==",
"dependencies": {
- "web3-types": "^1.3.1"
+ "web3-types": "^1.6.0"
},
"engines": {
"node": ">=14",
@@ -9509,21 +9515,24 @@
}
},
"../node_modules/web3-types": {
- "version": "1.4.0",
- "license": "LGPL-3.0",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.7.0.tgz",
+ "integrity": "sha512-nhXxDJ7a5FesRw9UG5SZdP/C/3Q2EzHGnB39hkAV+YGXDMgwxBXFWebQLfEzZzuArfHnvC0sQqkIHNwSKcVjdA==",
"engines": {
"node": ">=14",
"npm": ">=6.12.0"
}
},
"../node_modules/web3-utils": {
- "version": "4.2.0",
- "license": "LGPL-3.0",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.0.tgz",
+ "integrity": "sha512-fGG2IZr0XB1vEoWZiyJzoy28HpsIfZgz4mgPeQA9aj5rIx8z0o80qUPtIyrCYX/Bo2gYALlV5SWIJWxJNUQn9Q==",
"dependencies": {
"ethereum-cryptography": "^2.0.0",
- "web3-errors": "^1.1.4",
- "web3-types": "^1.4.0",
- "web3-validator": "^2.0.4"
+ "eventemitter3": "^5.0.1",
+ "web3-errors": "^1.2.0",
+ "web3-types": "^1.6.0",
+ "web3-validator": "^2.0.6"
},
"engines": {
"node": ">=14",
@@ -9531,13 +9540,14 @@
}
},
"../node_modules/web3-validator": {
- "version": "2.0.4",
- "license": "LGPL-3.0",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.6.tgz",
+ "integrity": "sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==",
"dependencies": {
"ethereum-cryptography": "^2.0.0",
"util": "^0.12.5",
- "web3-errors": "^1.1.4",
- "web3-types": "^1.3.1",
+ "web3-errors": "^1.2.0",
+ "web3-types": "^1.6.0",
"zod": "^3.21.4"
},
"engines": {
@@ -9652,8 +9662,9 @@
}
},
"../node_modules/ws": {
- "version": "8.16.0",
- "license": "MIT",
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"engines": {
"node": ">=10.0.0"
},
@@ -10593,8 +10604,9 @@
}
},
"node_modules/ws": {
- "version": "8.16.0",
- "license": "MIT",
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"engines": {
"node": ">=10.0.0"
},
diff --git a/package-lock.json b/package-lock.json
index 9f29fb66..f76fb122 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8596,9 +8596,9 @@
"dev": true
},
"node_modules/path-to-regexp": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz",
- "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw=="
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
+ "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="
},
"node_modules/path-type": {
"version": "4.0.0",
diff --git a/src/lib/utils.test.ts b/src/lib/utils.test.ts
index 2fabaed1..380921ba 100644
--- a/src/lib/utils.test.ts
+++ b/src/lib/utils.test.ts
@@ -198,28 +198,31 @@ describe('utils', () => {
name: 'AddressPermissions:AllowedCalls:',
key: '0x4b80742de2bf393a64c70000',
keyType: 'MappingWithGrouping',
- valueType: '(bytes4,address,bytes4)[CompactBytesArray]',
- valueContent: '(Bytes4,Address,Bytes4)',
+ valueType: '(bytes4,address,bytes4,bytes4)[CompactBytesArray]',
+ valueContent: '(BitArray,Address,Bytes4,Bytes4)',
},
decodedValue: [
[
- '0xcafecafe',
- '0xDAFEA492D9c6733ae3d56b7Ed1ADB60692c98Bc5',
- '0xcafecafe',
+ '0x00000003', // CALL and TRANSFERVALUE
+ '0xCA41e4ea94c8fA99889c8EA2c8948768cBaf4bc0', // addresses are decoded as checksummed
+ '0x3e89ad98', // LSP0 interface ID
+ '0xffffffff', // any function
],
[
- '0xbeefbeef',
- '0xFE31320faF8Da1492Eadf8Deb79bd264D7cF2141',
- '0xbeefbeef',
+ '0x00000002', // CALL only
+ '0xF70Ce3b58f275A4c28d06C98615760dDe774DE57',
+ '0xffffffff', // any standard interface ID
+ '0x760d9bba', // function selector of `transfer(address,address,uint256,bool,bytes)`
],
[
- '0xf00df00d',
- '0xc527702b14BF2f79F70B32e09F62B6A74cADFd80',
- '0xf00df00d',
+ '0x00000001', // TRANSFERVALUE only
+ '0xd3236aa1B8A4dDe5eA375fd1F2Fb5c354e686c9f',
+ '0xffffffff', // any standard interface ID
+ '0xffffffff', // any function
],
],
encodedValue:
- '0x001ccafecafeDAFEA492D9c6733ae3d56b7Ed1ADB60692c98Bc5cafecafe001cbeefbeefFE31320faF8Da1492Eadf8Deb79bd264D7cF2141beefbeef001cf00df00dc527702b14BF2f79F70B32e09F62B6A74cADFd80f00df00d'.toLowerCase(),
+ '0x002000000003ca41e4ea94c8fa99889c8ea2c8948768cbaf4bc03e89ad98ffffffff002000000002f70ce3b58f275a4c28d06c98615760dde774de57ffffffff760d9bba002000000001d3236aa1b8a4dde5ea375fd1f2fb5c354e686c9fffffffffffffffff',
},
];
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 14fa11fc..d156d564 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -550,7 +550,7 @@ export function isDataAuthentic(
options: Verification,
capture?: string[],
): boolean {
- if (!options || !options.method) {
+ if (!options?.method || options?.method === '0x00000000') {
return true;
}
@@ -613,7 +613,9 @@ export function patchIPFSUrlsIfApplicable(
receivedData: URLDataWithHash,
ipfsGateway: string,
): URLDataWithHash {
- if (receivedData?.url?.indexOf('ipfs://') !== -1) {
+ // Only map URL if it's indeed an ipfs:// URL and ignore if it's a data:// URL with JSON
+ // possibly containing an IPFS URL inside of the JSON data.
+ if (receivedData?.url?.startsWith('ipfs://')) {
return {
...receivedData,
url: receivedData.url.replace('ipfs://', ipfsGateway),
diff --git a/src/types/decodeData.ts b/src/types/decodeData.ts
index 057b65c5..66539731 100644
--- a/src/types/decodeData.ts
+++ b/src/types/decodeData.ts
@@ -4,7 +4,7 @@ import { EncodeDataType, URLDataWithHash } from './encodeData/JSONURL';
export interface DataInput {
keyName: string; // can be the name or the hex/hash
value;
- dynamicKeyParts?: string | string[];
+ dynamicKeyParts?: string | string[] | number;
totalArrayLength?: number;
startingIndex?: number;
}