From c76a69f5b057b95519856afc8c3878854dd71a37 Mon Sep 17 00:00:00 2001 From: CJ42 Date: Mon, 13 May 2024 16:09:34 +0100 Subject: [PATCH] feat: export method `isDataAuthentic` as static, single method or member of class --- docs/examples.md | 21 --- .../methods/external-data-source-utilities.md | 132 ++++++++++++++-- docs/overview.md | 148 ------------------ src/index.ts | 22 ++- src/lib/getDataFromExternalSources.test.ts | 110 ++++++++++++- src/lib/getDataFromExternalSources.ts | 11 +- 6 files changed, 246 insertions(+), 198 deletions(-) delete mode 100644 docs/examples.md delete mode 100644 docs/overview.md diff --git a/docs/examples.md b/docs/examples.md deleted file mode 100644 index 2ad7e894..00000000 --- a/docs/examples.md +++ /dev/null @@ -1,21 +0,0 @@ -# Examples - -- Fetch data from smart contracts + decode in one go! - -- Create basic schemas - -- Encode / Decode Links to external sources (`VerifiableURI`) - -- Map infos to specific addresses or identifiers - - - Using Dynamic Keys - -- Create Lists with keyType Arrays - - - Adding - - Deleting - - Updating - -- Store multiple infos under one data key with tuples - -- Use `CompactBytesArray` for efficient storing + retrieval diff --git a/docs/methods/external-data-source-utilities.md b/docs/methods/external-data-source-utilities.md index 8850aec1..060e2d6f 100644 --- a/docs/methods/external-data-source-utilities.md +++ b/docs/methods/external-data-source-utilities.md @@ -267,19 +267,125 @@ export interface Verification { ### Example -```javascript title="isDataAuthentic example" -myErc725.myMethod(); -/* -Document an example of the output here -*/ +
+ JSON data to verify from data.json + +```json +[ + { + "name": "LSP3Profile", + "key": "0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5", + "value": { + "LSP3Profile": { + "name": "test", + "description": "", + "tags": ["profile"], + "links": [], + "profileImage": [ + { + "width": 1024, + "height": 709, + "verification": { + "method": "keccak256(bytes)", + "data": "0x6a0a28680d65b69f5696859be7e0fcebbbcf0df47f1f767926de35402c7d525c" + }, + "url": "ipfs://QmVUYyft3j2JVrG4RzDe1Qx7K5gNtJGFhrExHQFeiRXz1C" + }, + { + "width": 640, + "height": 443, + "verification": { + "method": "keccak256(bytes)", + "data": "0x7cd399f2a2552aa5cd21b1584a98db3efa39c701c311c38a60c680343cfa6d82" + }, + "url": "ipfs://QmeU8FUZC9F1qMYmcWyBhfGqaf7g3kLzGb4xBpoCfyVLZW" + }, + { + "width": 320, + "height": 221, + "verification": { + "method": "keccak256(bytes)", + "data": "0x272d2e57ae1710ac7c5e3d1c9f9d24f48954ad43d0e821f8bd041a4734e309a5" + }, + "url": "ipfs://QmdViKPWYhZv7u86z7HBTgAkTAwEkNSRi1VkYEU8K5yUsH" + }, + { + "width": 180, + "height": 124, + "verification": { + "method": "keccak256(bytes)", + "data": "0x1a464ff7e0eff05da98ed309a25195d8666b6211a5dfa2214865c3fd50ead810" + }, + "url": "ipfs://QmXZUCW6MqCNfYJEFsi54Vkj6PRrUoiPjzTuA2mWtas3RJ" + } + ], + "backgroundImage": [ + { + "width": 1800, + "height": 1012, + "verification": { + "method": "keccak256(bytes)", + "data": "0x3f6be73b35d348fb8f0b87a47d8c8b6b9db8858ee044cb13734cdfe5d28031d8" + }, + "url": "ipfs://QmfLCPmL31f31RRB4R7yoTg3Hsk5PjrWyS3ZaaYyhRPT4n" + }, + { + "width": 1024, + "height": 576, + "verification": { + "method": "keccak256(bytes)", + "data": "0xcb57ed802bcd7dc4964395a609b3a0f557c5f46a602b28b058b9587bb77bb54f" + }, + "url": "ipfs://QmPoPEaoGNVYhiMTwBWp6XzLPRXyuLjZWnuMobdCbfqsU9" + }, + { + "width": 640, + "height": 360, + "verification": { + "method": "keccak256(bytes)", + "data": "0x57e8039288c3e1a7f891c839e03805984ab36524b710656f072492c1c8ebd967" + }, + "url": "ipfs://QmU3pDA4eDNPMeARsJXxKaZsMC5MgFLgzGQccnydbU9WLV" + }, + { + "width": 320, + "height": 180, + "verification": { + "method": "keccak256(bytes)", + "data": "0x2bebf9baac33d719bbd3b481b1af468701409ad7578f84be04e8f7563d5a1509" + }, + "url": "ipfs://QmcKtenPsRvrqZJQ1gLCdUFkex4i9DGp7RFvucb9nbkzsz" + }, + { + "width": 180, + "height": 101, + "verification": { + "method": "keccak256(bytes)", + "data": "0xe32154c03c892d7c41c91220b8757ec5b7847eb2dd91413f7238b0c25f55b475" + }, + "url": "ipfs://QmU7ueJ467E9HRahaqQmSPhvkTkMhCLXRxV45P4kmMk6vm" + } + ] + } + } + } +] ``` -/\*\* +
+ +```typescript title="isDataAuthentic example" +import jsonData from './data.json'; -- Hashes the data received with the specified hashing function, -- and compares the result with the provided hash. - \*/ - export function isDataAuthentic( - data: string | Uint8Array, - options: Verification, - ): boolean { +isDataAuthentic(jsonData, { + data: '0xdb864ed42104cee179785036cb4ff1183ebc57e5532ae766ad8533fa48acfbb3', + method: 'keccak256(utf8)', +}); +// true + +isDataAuthentic(jsonData, { + data: '0xdeadbeef00000000000000000000000000000000000000000000000000000000', + method: 'keccak256(utf8)', +}); +// false +``` diff --git a/docs/overview.md b/docs/overview.md deleted file mode 100644 index 157590b3..00000000 --- a/docs/overview.md +++ /dev/null @@ -1,148 +0,0 @@ -# Overview - -## Types - -- ERC725JSONSchema, -- ERC725JSONSchemaKeyType, -- ERC725JSONSchemaValueContent, -- ERC725JSONSchemaValueType, -- Permissions, -- ERC725Config, -- KeyValuePair, -- ProviderTypes -- DynamicNameSchema -- DecodeDataInput, -- DecodeDataOutput, -- EncodeDataInput, -- FetchDataOutput, - -_there is even more..._ - -## Encoding utilities - -- encodeData -- encodeKey -> necessary? -- encodeKeyName -- encodeKeyValue -- encodeArrayKey -- encodeValueType, -- encodeValueContent, - -## Decoding utilities - -- decodeData -- decodeKey -- decodeKeyPart -- decodeKeyValue -- decodeMappingKey -- decodeValueType, -- decodeValueContent, - -## Permissions utilities - -- encodePermissions -- decodePermissions -- checkPermissions -- mapPermission -> Super useful! - -## Fetching data - -- getDataFromExternalSources -- ERC725.getData -- ERC725.fetchData -- ERC725.getOwner -- ERC725.isValidSignature - -**These to be discussed** - -- getArrayValues -- getDataMultiple -- getData - -## External Data Source utilities (`VerifiableURI` and `JSONURI`) - -- encodeDataSourceWithHash, -- decodeDataSourceWithHash, -- getVerificationMethod -- isDataAuthentic - -## Schema utilities - -- getSchema -- getSchemaElement -- getSchemaElementForDynamicKeyName -- validateSchemas -- generateSchemasFromDynamicKeys - -## Dynamic Keys utilities - -- encodeDynamicKeyPart -- encodeDynamicMapping -- encodeDynamicMappingWithGrouping -- encodeDynamicKeyName -- generateDynamicKeyName -- isDynamicKeyPart -- isDynamicKeyName -- splitMultiDynamicKeyNamePart - -## Helpers - -- convertIPFSGatewayUrl -- duplicateMultiTypeERC725SchemaEntry -- guessKeyTypeFromKeyName -- isValidUintSize -- isValidByteSize -- isValueContentLiteralHex -- isValid32ByteHexString - -## Tuple utilities - -- encodeTupleKeyValue -- decodeTupleKeyValue -- isValidTuple - ---- - -These functions are not exported (yet!) - -- validateSchemas -- duplicateMultiTypeERC725SchemaEntry -- convertIPFSGatewayUrl -- generateSchemasFromDynamicKeys -- encodeKeyValue -- guessKeyTypeFromKeyName -> can be renamed to `get`? -- encodeTupleKeyValue -- encodeKey -> necessary? -- isValidTuple -- decodeKeyValue -- isDataAuthentic -- splitMultiDynamicKeyNamePart -- isValidUintSize -- isValidByteSize -- isValueContentLiteralHex -- getSchemaElementForDynamicKeyName -- getSchemaElement -- getArrayValues -- getDataMultiple -- getData -- encodeDynamicKeyPart -- encodeDynamicMapping -- encodeDynamicMappingWithGrouping -- encodeDynamicKeyName -- generateDynamicKeyName -- isValid32ByteHexString -- mapPermission -> Super useful! -- isDynamicKeyPart -- decodeKeyPart -- isValidTuple -- decodeTupleKeyValue -> strange we don't have `encodeTupleKeyValue` -- decodeKey - -These types should be exported: - -- DynamicNameSchema -- DecodeDataInput, -- DecodeDataOutput, -- EncodeDataInput, -- FetchDataOutput, -- there is even more... diff --git a/src/index.ts b/src/index.ts index 4d3b990b..492ed072 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,6 +32,7 @@ import { generateSchemasFromDynamicKeys, duplicateMultiTypeERC725SchemaEntry, getVerificationMethod, + isDataAuthentic, } from './lib/utils'; import { getSchema } from './lib/schemaParser'; @@ -88,7 +89,12 @@ export { }; export { ERC725Config, KeyValuePair, ProviderTypes } from './types'; -export { encodeData, encodeArrayKey, getVerificationMethod } from './lib/utils'; +export { + encodeData, + encodeArrayKey, + getVerificationMethod, + isDataAuthentic, +} from './lib/utils'; export { decodeData } from './lib/decodeData'; export { encodeKeyName, isDynamicKeyName } from './lib/encodeKeyName'; export { decodeMappingKey } from './lib/decodeMappingKey'; @@ -777,6 +783,20 @@ export class ERC725 { | undefined { return getVerificationMethod(nameOrSig); } + + static isDataAuthentic( + data: string | Uint8Array, + verificationOptions: Verification, + ): boolean { + return isDataAuthentic(data, verificationOptions); + } + + isDataAuthentic( + data: string | Uint8Array, + verificationOptions: Verification, + ): boolean { + return isDataAuthentic(data, verificationOptions); + } } export default ERC725; diff --git a/src/lib/getDataFromExternalSources.test.ts b/src/lib/getDataFromExternalSources.test.ts index 0bd38310..2c3992e9 100644 --- a/src/lib/getDataFromExternalSources.test.ts +++ b/src/lib/getDataFromExternalSources.test.ts @@ -20,11 +20,10 @@ import { ERC725JSONSchema } from '../types/ERC725JSONSchema'; import { getDataFromExternalSources } from './getDataFromExternalSources'; import { DecodeDataOutput } from '../types/decodeData'; -import { URLDataWithHash } from '../types'; const IPFS_GATEWAY_MOCK = 'https://mock-ipfs.mock/ipfs/'; -describe.only('getDataFromExternalSources', () => { +describe('getDataFromExternalSources', () => { it('should not throw if the value of a JSONURL/ASSETURL is null', async () => { const schemas: ERC725JSONSchema[] = [ { @@ -69,19 +68,118 @@ describe.only('getDataFromExternalSources', () => { key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', value: { verification: { - data: '0x00006f357c6a0020db864ed42104cee179785036cb4ff1183ebc57e5532ae766ad8533fa48acfbb3697066733a2f2f516d644d4755787551736d3155395173386f4a536e3550665934423161704747373559425278515079627452566d', + data: '0xdb864ed42104cee179785036cb4ff1183ebc57e5532ae766ad8533fa48acfbb3', method: 'keccak256(utf8)', }, - } as URLDataWithHash, + url: 'ipfs://QmdMGUxuQsm1U9Qs8oJSn5PfY4B1apGG75YBRxQPybtRVm', + }, }, ]; const result = await getDataFromExternalSources( [schema], dataFromChain, - IPFS_GATEWAY_MOCK, + 'https://api.universalprofile.cloud/ipfs/', ); - console.log('result', result); + expect(result).to.deep.equal([ + { + name: 'LSP3Profile', + key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5', + value: { + LSP3Profile: { + name: 'test', + description: '', + tags: ['profile'], + links: [], + profileImage: [ + { + width: 1024, + height: 709, + verification: { + method: 'keccak256(bytes)', + data: '0x6a0a28680d65b69f5696859be7e0fcebbbcf0df47f1f767926de35402c7d525c', + }, + url: 'ipfs://QmVUYyft3j2JVrG4RzDe1Qx7K5gNtJGFhrExHQFeiRXz1C', + }, + { + width: 640, + height: 443, + verification: { + method: 'keccak256(bytes)', + data: '0x7cd399f2a2552aa5cd21b1584a98db3efa39c701c311c38a60c680343cfa6d82', + }, + url: 'ipfs://QmeU8FUZC9F1qMYmcWyBhfGqaf7g3kLzGb4xBpoCfyVLZW', + }, + { + width: 320, + height: 221, + verification: { + method: 'keccak256(bytes)', + data: '0x272d2e57ae1710ac7c5e3d1c9f9d24f48954ad43d0e821f8bd041a4734e309a5', + }, + url: 'ipfs://QmdViKPWYhZv7u86z7HBTgAkTAwEkNSRi1VkYEU8K5yUsH', + }, + { + width: 180, + height: 124, + verification: { + method: 'keccak256(bytes)', + data: '0x1a464ff7e0eff05da98ed309a25195d8666b6211a5dfa2214865c3fd50ead810', + }, + url: 'ipfs://QmXZUCW6MqCNfYJEFsi54Vkj6PRrUoiPjzTuA2mWtas3RJ', + }, + ], + backgroundImage: [ + { + width: 1800, + height: 1012, + verification: { + method: 'keccak256(bytes)', + data: '0x3f6be73b35d348fb8f0b87a47d8c8b6b9db8858ee044cb13734cdfe5d28031d8', + }, + url: 'ipfs://QmfLCPmL31f31RRB4R7yoTg3Hsk5PjrWyS3ZaaYyhRPT4n', + }, + { + width: 1024, + height: 576, + verification: { + method: 'keccak256(bytes)', + data: '0xcb57ed802bcd7dc4964395a609b3a0f557c5f46a602b28b058b9587bb77bb54f', + }, + url: 'ipfs://QmPoPEaoGNVYhiMTwBWp6XzLPRXyuLjZWnuMobdCbfqsU9', + }, + { + width: 640, + height: 360, + verification: { + method: 'keccak256(bytes)', + data: '0x57e8039288c3e1a7f891c839e03805984ab36524b710656f072492c1c8ebd967', + }, + url: 'ipfs://QmU3pDA4eDNPMeARsJXxKaZsMC5MgFLgzGQccnydbU9WLV', + }, + { + width: 320, + height: 180, + verification: { + method: 'keccak256(bytes)', + data: '0x2bebf9baac33d719bbd3b481b1af468701409ad7578f84be04e8f7563d5a1509', + }, + url: 'ipfs://QmcKtenPsRvrqZJQ1gLCdUFkex4i9DGp7RFvucb9nbkzsz', + }, + { + width: 180, + height: 101, + verification: { + method: 'keccak256(bytes)', + data: '0xe32154c03c892d7c41c91220b8757ec5b7847eb2dd91413f7238b0c25f55b475', + }, + url: 'ipfs://QmU7ueJ467E9HRahaqQmSPhvkTkMhCLXRxV45P4kmMk6vm', + }, + ], + }, + }, + }, + ]); }); }); diff --git a/src/lib/getDataFromExternalSources.ts b/src/lib/getDataFromExternalSources.ts index de35abde..f7bde427 100644 --- a/src/lib/getDataFromExternalSources.ts +++ b/src/lib/getDataFromExternalSources.ts @@ -129,21 +129,14 @@ export const getDataFromExternalSources = ( if (/^(\[.*\]|\{.*\})\s*$/s.test(key)) { const json = arrToBufArr(receivedData).toString(); const value = JSON.parse(json); + if (isDataAuthentic(value, urlDataWithHash.verification)) { return { ...dataEntry, value }; } - console.log('receivedData', receivedData); - console.log( - 'urlDataWithHash.verification', - urlDataWithHash.verification, - ); - console.log( - 'isDataAuthentic(receivedData, urlDataWithHash.verification)', - isDataAuthentic(receivedData, urlDataWithHash.verification), - ); if (isDataAuthentic(receivedData, urlDataWithHash.verification)) { return { ...dataEntry, value }; } + throw new Error('result did not correctly validate'); } } catch {