diff --git a/README.md b/README.md index 52ded93bd..3a8cc46a3 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ DWN SDK includes a polyfilled distribution that can imported in a `module` scrip const dwn = await Dwn.create({ messageStore, dataStore, eventLog }); // Generate a did:key DID (Decentralized Identifier). - const didKey = await DidKeyResolver.generate(); + const didKey = await TestDataGenerator.generateDidKeyPersona(); // Create some data to be stored. const encoder = new TextEncoder(); @@ -199,7 +199,7 @@ const eventLog = new EventLogLevel(); const dwn = await Dwn.create({ messageStore, dataStore, eventLog }); // Generate a did:key DID (Decentralized Identifier). -const didKey = await DidKeyResolver.generate(); +const didKey = await TestDataGenerator.generateDidKeyPersona(); // Create some data to be stored. const encoder = new TextEncoder(); diff --git a/package-lock.json b/package-lock.json index a49da66f3..ff8dc3c26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@js-temporal/polyfill": "0.4.4", "@noble/ed25519": "2.0.0", "@noble/secp256k1": "2.0.0", + "@web5/dids": "^0.2.4", "abstract-level": "1.0.3", "ajv": "8.12.0", "blockstore-core": "4.2.0", @@ -36,6 +37,7 @@ "devDependencies": { "@types/chai": "4.3.0", "@types/chai-as-promised": "7.1.5", + "@types/dns-packet": "^5.6.4", "@types/flat": "^5.0.2", "@types/karma": "^6.3.3", "@types/lodash": "4.14.179", @@ -127,6 +129,65 @@ "node": ">=0.1.90" } }, + "node_modules/@decentralized-identity/ion-pow-sdk": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@decentralized-identity/ion-pow-sdk/-/ion-pow-sdk-1.0.17.tgz", + "integrity": "sha512-vk7DTDM8aKDbFyu1ad/qkoRrGL4q+KvNeL/FNZXhkWPaDhVExBN/qGEoRLf1YSfFe+myto3+4RYTPut+riiqnw==", + "dependencies": { + "buffer": "6.0.3", + "cross-fetch": "3.1.5", + "hash-wasm": "4.9.0" + } + }, + "node_modules/@decentralized-identity/ion-pow-sdk/node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/@decentralized-identity/ion-pow-sdk/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@decentralized-identity/ion-sdk": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@decentralized-identity/ion-sdk/-/ion-sdk-1.0.1.tgz", + "integrity": "sha512-+P+DXcRSFjsEsI5KIqUmVjpzgUT28B2lWpTO+IxiBcfibAN/1Sg20NebGTO/+serz2CnSZf95N2a1OZ6eXypGQ==", + "dependencies": { + "@noble/ed25519": "^2.0.0", + "@noble/secp256k1": "^2.0.0", + "canonicalize": "^2.0.0", + "multiformats": "^12.0.1", + "multihashes": "^4.0.3", + "uri-js": "^4.4.1" + } + }, + "node_modules/@decentralized-identity/ion-sdk/node_modules/multiformats": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.1.3.tgz", + "integrity": "sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@dependents/detective-less": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@dependents/detective-less/-/detective-less-3.0.2.tgz", @@ -362,6 +423,16 @@ "integrity": "sha512-e4psVV9Fe2eBfS9xK2rzQ9lE5xS4tARm7EJzDb6sVZy3F+EMyHJ67i0NdBVR9BRyQx7YhogMCbB6R1QwXuBxMg==", "dev": true }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "node_modules/@multiformats/base-x": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz", + "integrity": "sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw==" + }, "node_modules/@multiformats/murmur3": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@multiformats/murmur3/-/murmur3-2.1.5.tgz", @@ -620,6 +691,15 @@ "@types/node": "*" } }, + "node_modules/@types/dns-packet": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.6.4.tgz", + "integrity": "sha512-R0ORTvCCeujG+upKfV4JlvozKLdQWlpsducXGd1L6ezBChwpjSj9K84F+KoMDsZQ9RhOLTR1hnNrwJHWagY24g==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@types/flat/-/flat-5.0.2.tgz", @@ -945,6 +1025,95 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@web5/common": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@web5/common/-/common-0.2.2.tgz", + "integrity": "sha512-dRn6SmALExeTLMTK/W5ozGarfaddK+Lraf5OjuIGLAaLfcX1RWx3oDMoY5Hr9LjfxHJC8mGXB8DnKflbeYJRgA==", + "dependencies": { + "level": "8.0.0", + "multiformats": "11.0.2", + "readable-stream": "4.4.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@web5/crypto": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@web5/crypto/-/crypto-0.2.2.tgz", + "integrity": "sha512-vHFg0wXQSQXrwuBNQyDHnmSZchfTfO6/Sv+7rDsNkvofs+6lGTE8CZ02cwUYMeIwTRMLer12c+fMfzYrXokEUQ==", + "dependencies": { + "@noble/ciphers": "0.1.4", + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@web5/common": "0.2.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@web5/crypto/node_modules/@noble/ciphers": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.1.4.tgz", + "integrity": "sha512-d3ZR8vGSpy3v/nllS+bD/OMN5UZqusWiQqkyj7AwzTnhXFH72pF5oB4Ach6DQ50g5kXxC28LdaYBEpsyv9KOUQ==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@web5/crypto/node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "1.3.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@web5/crypto/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@web5/crypto/node_modules/@web5/common": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@web5/common/-/common-0.2.1.tgz", + "integrity": "sha512-Tt5P17HgQCx+Epw0IHnhRKqp5UU3E4xtsE8PkdghOBnvntBB0op5P6efvR1WqmJft5+VunDHt3yZAZstuqQkNg==", + "dependencies": { + "level": "8.0.0", + "multiformats": "11.0.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@web5/dids": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@web5/dids/-/dids-0.2.4.tgz", + "integrity": "sha512-e+m+xgpiM8ydTJgWcPdwmjILLMZYdl2kwahlO22mK0azSKVrg1klpGrUODzqkrWrQ5O0tnOyqEy39FcD5Sy11w==", + "dependencies": { + "@decentralized-identity/ion-pow-sdk": "1.0.17", + "@decentralized-identity/ion-sdk": "1.0.1", + "@web5/common": "0.2.2", + "@web5/crypto": "0.2.2", + "did-resolver": "4.1.0", + "dns-packet": "5.6.1", + "level": "8.0.0", + "ms": "2.1.3", + "pkarr": "1.1.1", + "z32": "1.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -1155,12 +1324,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/b4a": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1189,6 +1371,17 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/bencode": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-3.1.1.tgz", + "integrity": "sha512-btsxX9201yoWh45TdqYg6+OZ5O1xTYKTYSGvJndICDFtznE/9zXgow8yjMvvhOqKKuzuL7h+iiCMpfkG8+QuBA==", + "dependencies": { + "uint8-util": "^2.1.6" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1198,6 +1391,49 @@ "node": ">=8" } }, + "node_modules/bittorrent-dht": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/bittorrent-dht/-/bittorrent-dht-11.0.5.tgz", + "integrity": "sha512-R09D6uNaziRqsc+B/j5QzkjceTak+wH9vcNLnkmt8A52EWF9lQwBP0vvCKgSA3AJOYYl+41n3osA2KYYn/z5uQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bencode": "^4.0.0", + "debug": "^4.3.4", + "k-bucket": "^5.1.0", + "k-rpc": "^5.1.0", + "last-one-wins": "^1.0.4", + "lru": "^3.1.0", + "randombytes": "^2.1.0", + "record-cache": "^1.2.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/bittorrent-dht/node_modules/bencode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", + "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", + "dependencies": { + "uint8-util": "^2.2.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/bl": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", @@ -1221,6 +1457,24 @@ "node": ">= 6" } }, + "node_modules/blake2b": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/blake2b/-/blake2b-2.1.4.tgz", + "integrity": "sha512-AyBuuJNI64gIvwx13qiICz6H6hpmjvYS5DGkG6jbXMOT8Z3WUJ3V1X0FlhIoT1b/5JtHE3ki+xjtMvu1nn+t9A==", + "dependencies": { + "blake2b-wasm": "^2.4.0", + "nanoassert": "^2.0.0" + } + }, + "node_modules/blake2b-wasm": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/blake2b-wasm/-/blake2b-wasm-2.4.0.tgz", + "integrity": "sha512-S1kwmW2ZhZFFFOghcx73+ZajEfKBqhP82JMssxtLVMxlaPea1p9uoLiUZ5WYyHn0KddwbLc+0vh4wR0KBNoT5w==", + "dependencies": { + "b4a": "^1.0.1", + "nanoassert": "^2.0.0" + } + }, "node_modules/blockstore-core": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/blockstore-core/-/blockstore-core-4.2.0.tgz", @@ -1576,6 +1830,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/canonicalize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.0.0.tgz", + "integrity": "sha512-ulDEYPv7asdKvqahuAY35c1selLdzDwHqugK92hfkzvlDCwXRRelDkR+Er33md/PtnpqHemgkuDPanZ4fiYZ8w==" + }, "node_modules/catering": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", @@ -1592,6 +1851,14 @@ "cborg": "cli.js" } }, + "node_modules/chacha20-universal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chacha20-universal/-/chacha20-universal-1.0.4.tgz", + "integrity": "sha512-/IOxdWWNa7nRabfe7+oF+jVkGjlr2xUL4J8l/OvzZhj+c9RpMqoo3Dq+5nU1j/BflRV4BKnaQ4+4oH1yBpQG1Q==", + "dependencies": { + "nanoassert": "^2.0.0" + } + }, "node_modules/chai": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", @@ -1692,6 +1959,59 @@ "node": ">= 6" } }, + "node_modules/chrome-dgram": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/chrome-dgram/-/chrome-dgram-3.0.6.tgz", + "integrity": "sha512-bqBsUuaOiXiqxXt/zA/jukNJJ4oaOtc7ciwqJpZVEaaXwwxqgI2/ZdG02vXYWUhHGziDlvGMQWk0qObgJwVYKA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "inherits": "^2.0.4", + "run-series": "^1.1.9" + } + }, + "node_modules/chrome-dns": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chrome-dns/-/chrome-dns-1.0.1.tgz", + "integrity": "sha512-HqsYJgIc8ljJJOqOzLphjAs79EUuWSX3nzZi2LNkzlw3GIzAeZbaSektC8iT/tKvLqZq8yl1GJu5o6doA4TRbg==", + "dependencies": { + "chrome-net": "^3.3.2" + } + }, + "node_modules/chrome-net": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/chrome-net/-/chrome-net-3.3.4.tgz", + "integrity": "sha512-Jzy2EnzmE+ligqIZUsmWnck9RBXLuUy6CaKyuNMtowFG3ZvLt8d+WBJCTPEludV0DHpIKjAOlwjFmTaEdfdWCw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "inherits": "^2.0.1" + } + }, "node_modules/ci-info": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", @@ -2424,6 +2744,11 @@ "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", "dev": true }, + "node_modules/did-resolver": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/did-resolver/-/did-resolver-4.1.0.tgz", + "integrity": "sha512-S6fWHvCXkZg2IhS4RcVHxwuyVejPR7c+a4Go0xbQ9ps5kILa8viiYQgrM4gfTyeTjJ0ekgJH9gk/BawTpmkbZA==" + }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -2462,6 +2787,17 @@ "node": ">=8" } }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -3500,6 +3836,14 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "node_modules/graceful-goodbye": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/graceful-goodbye/-/graceful-goodbye-1.3.0.tgz", + "integrity": "sha512-hcZOs20emYlTM7MmUE0FpuZcjlk2GPsR+UYTHDeWxtGjXcbh2CawGi8vlzqsIvspqAbot7mRv3sC/uhgtKc4hQ==", + "dependencies": { + "safety-catch": "^1.0.2" + } + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -3639,6 +3983,11 @@ } ] }, + "node_modules/hash-wasm": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.9.0.tgz", + "integrity": "sha512-7SW7ejyfnRxuOc7ptQHSf4LDoZaWOivfzqw+5rpcQku0nHfmicPKE51ra9BiRLAmT8+gGLestr1XroUkqdjL6w==" + }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -4484,6 +4833,40 @@ "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, + "node_modules/k-bucket": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-5.1.0.tgz", + "integrity": "sha512-Fac7iINEovXIWU20GPnOMLUbjctiS+cnmyjC4zAUgvs3XPf1vo9akfCHkigftSic/jiKqKl+KA3a/vFcJbHyCg==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/k-rpc": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/k-rpc/-/k-rpc-5.1.0.tgz", + "integrity": "sha512-FGc+n70Hcjoa/X2JTwP+jMIOpBz+pkRffHnSl9yrYiwUxg3FIgD50+u1ePfJUOnRCnx6pbjmVk5aAeB1wIijuQ==", + "dependencies": { + "k-bucket": "^5.0.0", + "k-rpc-socket": "^1.7.2", + "randombytes": "^2.0.5" + } + }, + "node_modules/k-rpc-socket": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/k-rpc-socket/-/k-rpc-socket-1.11.1.tgz", + "integrity": "sha512-8xtA8oqbZ6v1Niryp2/g4GxW16EQh5MvrUylQoOG+zcrDff5CKttON2XUXvMwlIHq4/2zfPVFiinAccJ+WhxoA==", + "dependencies": { + "bencode": "^2.0.0", + "chrome-dgram": "^3.0.2", + "chrome-dns": "^1.0.0", + "chrome-net": "^3.3.2" + } + }, + "node_modules/k-rpc-socket/node_modules/bencode": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-2.0.3.tgz", + "integrity": "sha512-D/vrAD4dLVX23NalHwb8dSvsUsxeRPO8Y7ToKA015JQYq69MLDOMkC0uGZYA/MPpltLO8rt8eqFC2j8DxjTZ/w==" + }, "node_modules/karma": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.1.tgz", @@ -4736,6 +5119,11 @@ "json-buffer": "3.0.1" } }, + "node_modules/last-one-wins": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/last-one-wins/-/last-one-wins-1.0.4.tgz", + "integrity": "sha512-t+KLJFkHPQk8lfN6WBOiGkiUXoub+gnb2XTYI2P3aiISL+94xgZ1vgz1SXN/N4hthuOoLXarXfBZPUruyjQtfA==" + }, "node_modules/layerr": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/layerr/-/layerr-2.0.1.tgz", @@ -5013,6 +5401,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lru": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lru/-/lru-3.1.0.tgz", + "integrity": "sha512-5OUtoiVIGU4VXBOshidmtOsvBIvcQR6FD/RzWSvaeHyxCGB+PCUCu+52lqMfdc0h/2CLvHhZS4TwUmMQrrMbBQ==", + "dependencies": { + "inherits": "^2.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/lru-cache": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", @@ -5455,8 +5854,20 @@ "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/multibase": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", + "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", + "deprecated": "This module has been superseded by the multiformats module", + "dependencies": { + "@multiformats/base-x": "^4.0.1" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + } }, "node_modules/multiformats": { "version": "11.0.2", @@ -5467,6 +5878,38 @@ "npm": ">=7.0.0" } }, + "node_modules/multihashes": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", + "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", + "dependencies": { + "multibase": "^4.0.1", + "uint8arrays": "^3.0.0", + "varint": "^5.0.2" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/multihashes/node_modules/multiformats": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" + }, + "node_modules/multihashes/node_modules/uint8arrays": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", + "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/multihashes/node_modules/varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==" + }, "node_modules/murmurhash3js-revisited": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz", @@ -5475,6 +5918,11 @@ "node": ">=8.0.0" } }, + "node_modules/nanoassert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-2.0.0.tgz", + "integrity": "sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==" + }, "node_modules/nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", @@ -6122,6 +6570,34 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pkarr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkarr/-/pkarr-1.1.1.tgz", + "integrity": "sha512-X27LKqf83X3WuJd2Z9qdfVxkmfOu6HUbY0pm11LqeBbFmgmZRPgOxJG8bKiIsmmD6Vjc25j45KHYflF2lfodyQ==", + "dependencies": { + "bencode": "^3.0.3", + "bittorrent-dht": "^11.0.4", + "chalk": "^5.2.0", + "dns-packet": "^5.6.1", + "graceful-goodbye": "^1.3.0", + "sodium-universal": "^4.0.0", + "z32": "^1.0.0" + }, + "bin": { + "pkarr": "bin.js" + } + }, + "node_modules/pkarr/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/pkg-dir": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", @@ -6799,6 +7275,14 @@ "node": ">=8.10.0" } }, + "node_modules/record-cache": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/record-cache/-/record-cache-1.2.0.tgz", + "integrity": "sha512-kyy3HWCez2WrotaL3O4fTn0rsIdfRKOdQQcEJ9KpvmKmbffKVvwsloX063EgRUlpJIXHiDQFhJcTbZequ2uTZw==", + "dependencies": { + "b4a": "^1.3.1" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7003,6 +7487,25 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/run-series": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz", + "integrity": "sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -7014,6 +7517,11 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "node_modules/safety-catch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safety-catch/-/safety-catch-1.0.2.tgz", + "integrity": "sha512-C1UYVZ4dtbBxEtvOcpjBaaD27nP8MlvyAQEp2fOTOEe6pfUpk1cDUxij6BR1jZup6rSyUTaBBplK7LanskrULA==" + }, "node_modules/sass-lookup": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/sass-lookup/-/sass-lookup-3.0.0.tgz", @@ -7136,6 +7644,42 @@ "sha.js": "bin.js" } }, + "node_modules/sha256-universal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sha256-universal/-/sha256-universal-1.2.1.tgz", + "integrity": "sha512-ghn3muhdn1ailCQqqceNxRgkOeZSVfSE13RQWEg6njB+itsFzGVSJv+O//2hvNXZuxVIRyNzrgsZ37SPDdGJJw==", + "dependencies": { + "b4a": "^1.0.1", + "sha256-wasm": "^2.2.1" + } + }, + "node_modules/sha256-wasm": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/sha256-wasm/-/sha256-wasm-2.2.2.tgz", + "integrity": "sha512-qKSGARvao+JQlFiA+sjJZhJ/61gmW/3aNLblB2rsgIxDlDxsJPHo8a1seXj12oKtuHVgJSJJ7QEGBUYQN741lQ==", + "dependencies": { + "b4a": "^1.0.1", + "nanoassert": "^2.0.0" + } + }, + "node_modules/sha512-universal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sha512-universal/-/sha512-universal-1.2.1.tgz", + "integrity": "sha512-kehYuigMoRkIngCv7rhgruLJNNHDnitGTBdkcYbCbooL8Cidj/bS78MDxByIjcc69M915WxcQTgZetZ1JbeQTQ==", + "dependencies": { + "b4a": "^1.0.1", + "sha512-wasm": "^2.3.1" + } + }, + "node_modules/sha512-wasm": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/sha512-wasm/-/sha512-wasm-2.3.4.tgz", + "integrity": "sha512-akWoxJPGCB3aZCrZ+fm6VIFhJ/p8idBv7AWGFng/CZIrQo51oQNsvDbTSRXWAzIiZJvpy16oIDiCCPqTe21sKg==", + "dependencies": { + "b4a": "^1.0.1", + "nanoassert": "^2.0.0" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -7195,6 +7739,14 @@ "url": "https://opencollective.com/sinon" } }, + "node_modules/siphash24": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/siphash24/-/siphash24-1.3.1.tgz", + "integrity": "sha512-moemC3ZKiTzH29nbFo3Iw8fbemWWod4vNs/WgKbQ54oEs6mE6XVlguxvinYjB+UmaE0PThgyED9fUkWvirT8hA==", + "dependencies": { + "nanoassert": "^2.0.0" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7244,6 +7796,45 @@ "node": ">=10.0.0" } }, + "node_modules/sodium-javascript": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/sodium-javascript/-/sodium-javascript-0.8.0.tgz", + "integrity": "sha512-rEBzR5mPxPES+UjyMDvKPIXy9ImF17KOJ32nJNi9uIquWpS/nfj+h6m05J5yLJaGXjgM72LmQoUbWZVxh/rmGg==", + "dependencies": { + "blake2b": "^2.1.1", + "chacha20-universal": "^1.0.4", + "nanoassert": "^2.0.0", + "sha256-universal": "^1.1.0", + "sha512-universal": "^1.1.0", + "siphash24": "^1.0.1", + "xsalsa20": "^1.0.0" + } + }, + "node_modules/sodium-native": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.0.5.tgz", + "integrity": "sha512-YGimGhy7Ho6pTAAvuNdn3Tv9C2MD7HP89X1omReHat0Fd1mMnapGqwzb5YoHTAbIEh8tQmKP6+uLlwYCkf+EOA==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.6.0" + } + }, + "node_modules/sodium-universal": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/sodium-universal/-/sodium-universal-4.0.0.tgz", + "integrity": "sha512-iKHl8XnBV96k1c75gwwzANFdephw/MDWSjQAjPmBE+du0y3P23Q8uf7AcdcfFsYAMwLg7WVBfSAIBtV/JvRsjA==", + "dependencies": { + "blake2b": "^2.1.1", + "chacha20-universal": "^1.0.4", + "nanoassert": "^2.0.0", + "sha256-universal": "^1.1.0", + "sha512-universal": "^1.1.0", + "siphash24": "^1.0.1", + "sodium-javascript": "~0.8.0", + "sodium-native": "^4.0.0", + "xsalsa20": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7828,6 +8419,14 @@ "node": "*" } }, + "node_modules/uint8-util": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/uint8-util/-/uint8-util-2.2.4.tgz", + "integrity": "sha512-uEI5lLozmKQPYEevfEhP9LY3Je5ZmrQhaWXrzTVqrLNQl36xsRh8NiAxYwB9J+2BAt99TRbmCkROQB2ZKhx4UA==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/uint8arraylist": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.3.tgz", @@ -8120,6 +8719,11 @@ } } }, + "node_modules/xsalsa20": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/xsalsa20/-/xsalsa20-1.2.0.tgz", + "integrity": "sha512-FIr/DEeoHfj7ftfylnoFt3rAIRoWXpx2AoDfrT2qD2wtp7Dp+COajvs/Icb7uHqRW9m60f5iXZwdsJJO3kvb7w==" + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -8197,6 +8801,14 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/z32": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/z32/-/z32-1.0.1.tgz", + "integrity": "sha512-Uytfqf6VEVchHKZDw0NRdCViOARHP84uzvOw0CXCMLOwhgHZUL9XibpEPLLQN10mCVLxOlGCQWbkV7km7yNYcw==", + "dependencies": { + "b4a": "^1.5.3" + } } } } diff --git a/package.json b/package.json index cf91c82e6..197b2528b 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "@js-temporal/polyfill": "0.4.4", "@noble/ed25519": "2.0.0", "@noble/secp256k1": "2.0.0", + "@web5/dids": "^0.2.4", "abstract-level": "1.0.3", "ajv": "8.12.0", "blockstore-core": "4.2.0", @@ -88,6 +89,7 @@ "devDependencies": { "@types/chai": "4.3.0", "@types/chai-as-promised": "7.1.5", + "@types/dns-packet": "^5.6.4", "@types/flat": "^5.0.2", "@types/karma": "^6.3.3", "@types/lodash": "4.14.179", @@ -157,4 +159,4 @@ "license-check": "license-report --only=prod > license-report.json && node ./build/license-check.cjs", "publish:unstable": "./build/publish-unstable.sh" } -} \ No newline at end of file +} diff --git a/src/core/auth.ts b/src/core/auth.ts index 484c82913..d74a4c17b 100644 --- a/src/core/auth.ts +++ b/src/core/auth.ts @@ -1,4 +1,4 @@ -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { MessageInterface } from '../types/message-interface.js'; import type { AuthorizationModel, GenericMessage } from '../types/message-types.js'; diff --git a/src/did/did-ion-resolver.ts b/src/did/did-ion-resolver.ts deleted file mode 100644 index baeaa5a6b..000000000 --- a/src/did/did-ion-resolver.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { DidMethodResolver, DidResolutionResult } from '../types/did-types.js'; -import { DwnError, DwnErrorCode } from '../core/dwn-error.js'; - -import crossFetch from 'cross-fetch'; -// supports fetch in: node, browsers, and browser extensions. -// uses native fetch if available in environment or falls back to a ponyfill. -// 'cross-fetch' is a ponyfill that uses `XMLHTTPRequest` under the hood. -// `XMLHTTPRequest` cannot be used in browser extension background service workers. -// browser extensions get even more strict with `fetch` in that it cannot be referenced -// indirectly. -const fetch = globalThis.fetch ?? crossFetch; - -/** - * Resolver for ION DIDs. - */ -export class DidIonResolver implements DidMethodResolver { - /** - * @param resolutionEndpoint optional custom URL to send DID resolution request to - */ - constructor (private resolutionEndpoint: string = 'https://ion.tbd.engineering/identifiers/') { } - - method(): string { - return 'ion'; - } - - async resolve(did: string): Promise { - // using `URL` constructor to handle both existence and absence of trailing slash '/' in resolution endpoint - // appending './' to DID so 'did' in 'did:ion:abc' doesn't get interpreted as a URL scheme (e.g. like 'http') due to the colon - const resolutionUrl = new URL('./' + did, this.resolutionEndpoint).toString(); - const response = await fetch(resolutionUrl); - - if (response.status !== 200) { - throw new DwnError(DwnErrorCode.DidResolutionFailed, `unable to resolve ${did}, got http status ${response.status}`); - } - - const didResolutionResult = await response.json(); - return didResolutionResult; - } -} diff --git a/src/did/did-key-resolver.ts b/src/did/did-key-resolver.ts deleted file mode 100644 index 2b15349a7..000000000 --- a/src/did/did-key-resolver.ts +++ /dev/null @@ -1,148 +0,0 @@ -import type { Signer } from '../types/signer.js'; -import type { DidDocument, DidMethodResolver, DidResolutionResult } from '../types/did-types.js'; -import type { KeyMaterial, PublicJwk } from '../types/jose-types.js'; - -import varint from 'varint'; - -import { base58btc } from 'multiformats/bases/base58'; -import { Did } from './did.js'; -import { ed25519 } from '../../src/jose/algorithms/signing/ed25519.js'; -import { Encoder } from '../utils/encoder.js'; -import { PrivateKeySigner } from '../utils/private-key-signer.js'; -import { Secp256k1 } from '../utils/secp256k1.js'; - -/** - * did:key Resolver. - * * **NOTE**: Key support is limited to Ed25519 and SECP256k1. - * * **NOTE**: `verificationMethod` support is limited to `JsonWebKey2020` - * - * Helpful Resources: - * * [DID-Key Draft Spec](https://w3c-ccg.github.io/did-method-key/) - */ -export class DidKeyResolver implements DidMethodResolver { - method(): string { - return 'key'; - } - - /** - * Gets the number of bytes of the multicodec header in the `did:key` DID. - * @param did - A `did:key` DID - * @returns size of the multicodec head in number of bytes - */ - public static getMulticodecSize(did: Uint8Array): number { - let multicodecHeaderSize = 0; - - while (true) { - const currentByte = did[multicodecHeaderSize]; - multicodecHeaderSize++; - - // bitwise and with binary 1000 0000 - // as soon as the result byte does not lead with a leading 1, we've reached the end of the multicodec header - if ((currentByte & 0x80) !== 0x80) { - break; - } - } - - return multicodecHeaderSize; - } - - async resolve(did: string): Promise { - const [_scheme, _method, id] = did.split(':', 3); - - try { - const idBytes = base58btc.decode(id); - const multicodec = varint.decode(idBytes); - const multicodecSize = DidKeyResolver.getMulticodecSize(idBytes); - const publicKeyBytes = idBytes.slice(multicodecSize); - - // key specific values - const keySpecificContext: string[] = []; - let publicJwk: PublicJwk; - if (multicodec === 0xed) { - // ed25519-pub multicodec - keySpecificContext.push('https://w3id.org/security/suites/ed25519-2020/v1'); - publicJwk = await ed25519.publicKeyToJwk(publicKeyBytes); - } else if (multicodec === 0xe7) { - // secp256k1-pub multicodec - publicJwk = await Secp256k1.publicKeyToJwk(publicKeyBytes); - } else { - throw Error(`key type of multicodec ${multicodec} is not supported`); - } - - const keyId = `${did}#${id}`; - - const didDocument: DidDocument = { - '@context': [ - 'https://www.w3.org/ns/did/v1', - 'https://w3id.org/security/suites/jws-2020/v1', - ...keySpecificContext - ], - 'id' : did, - 'verificationMethod' : [{ - id : keyId, - type : 'JsonWebKey2020', - controller : did, - publicKeyJwk : publicJwk - }], - 'authentication' : [keyId], - 'assertionMethod' : [keyId], - 'capabilityDelegation' : [keyId], - 'capabilityInvocation' : [keyId] - }; - - return { - '@context' : 'https://w3id.org/did-resolution/v1', - didDocument, - didDocumentMetadata : {}, - didResolutionMetadata : {} - }; - } catch { - return { - didDocument : undefined, - didDocumentMetadata : {}, - didResolutionMetadata : { - error: 'invalidDid' - }, - }; - } - } - - /** - * Generates a new ed25519 public/private key pair. Creates a DID using the private key. - * @returns DID and its key material. - */ - public static async generate(): Promise<{ did: string, signer: Signer } & KeyMaterial> { - const { publicJwk, privateJwk } = await ed25519.generateKeyPair(); - - // multicodec code for Ed25519 public keys - const ed25519Multicodec = varint.encode(0xed); - const publicKeyBytes = Encoder.base64UrlToBytes(publicJwk.x); - const idBytes = new Uint8Array(ed25519Multicodec.length + publicKeyBytes.byteLength); - idBytes.set(ed25519Multicodec, 0); - idBytes.set(publicKeyBytes, ed25519Multicodec.length); - - const id = base58btc.encode(idBytes); - const did = `did:key:${id}`; - const keyId = DidKeyResolver.getKeyId(did); - - return { - did, - keyId, - keyPair : { publicJwk, privateJwk }, - signer : new PrivateKeySigner({ - privateJwk : privateJwk, - algorithm : privateJwk.alg, - keyId : `${did}#${keyId}`, - }) - }; - } - - /** - * Gets the fully qualified key ID of a `did:key` DID. ie. '#' - */ - public static getKeyId(did: string): string { - const methodSpecificId = Did.getMethodSpecificId(did); - const keyId = `${did}#${methodSpecificId}`; - return keyId; - }; -} \ No newline at end of file diff --git a/src/did/did-resolver.ts b/src/did/did-resolver.ts deleted file mode 100644 index a3012e167..000000000 --- a/src/did/did-resolver.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { Cache } from '../types/cache.js'; -import type { DidMethodResolver, DidResolutionResult } from '../types/did-types.js'; - -import { Did } from './did.js'; -import { DidIonResolver } from './did-ion-resolver.js'; -import { DidKeyResolver } from './did-key-resolver.js'; -import { MemoryCache } from '../utils/memory-cache.js'; -import { DwnError, DwnErrorCode } from '../core/dwn-error.js'; - -/** - * A DID resolver that by default supports `did:key` and `did:ion` DIDs. - */ -export class DidResolver { - private didResolvers: Map; - private cache: Cache; - - constructor(resolvers?: DidMethodResolver[], cache?:Cache) { - - this.cache = cache || new MemoryCache(600); - - // construct default DID method resolvers if none given - if (resolvers === undefined || resolvers.length === 0) { - resolvers = [ - new DidIonResolver(), - new DidKeyResolver() - ]; - } - - this.didResolvers = new Map(); - - for (const resolver of resolvers) { - this.didResolvers.set(resolver.method(), resolver); - } - } - - /** - * attempt to resolve the DID provided - * @throws {Error} if DID is invalid - * @throws {Error} if DID method is not supported - * @throws {Error} if resolving DID fails - * @param did - the DID to resolve - * @returns {DidResolutionResult} - */ - public async resolve(did: string): Promise { - // naively validate the given DID - Did.validate(did); - const splitDID = did.split(':', 3); - - const didMethod = splitDID[1]; - const didResolver = this.didResolvers.get(didMethod); - - if (!didResolver) { - throw new DwnError(DwnErrorCode.DidMethodNotSupported, `${didMethod} DID method not supported`); - } - - // use cached result if exists - const cachedResolutionResult = await this.cache.get(did); - const resolutionResult = cachedResolutionResult ?? await didResolver.resolve(did); - if (cachedResolutionResult === undefined){ - await this.cache.set(did, resolutionResult); - } - - const { didDocument, didResolutionMetadata } = resolutionResult; - - if (!didDocument || didResolutionMetadata?.error) { - const { error } = didResolutionMetadata; - let errMsg = `Failed to resolve DID ${did}.`; - errMsg += error ? ` Error: ${error}` : ''; - - throw new DwnError(DwnErrorCode.DidResolutionFailed, errMsg); - } - - return resolutionResult; - } -} diff --git a/src/dwn.ts b/src/dwn.ts index 79d1021fd..f133e9ad7 100644 --- a/src/dwn.ts +++ b/src/dwn.ts @@ -14,7 +14,6 @@ import type { ProtocolsConfigureMessage, ProtocolsQueryMessage, ProtocolsQueryRe import type { RecordsDeleteMessage, RecordsQueryMessage, RecordsQueryReply, RecordsReadMessage, RecordsReadReply, RecordsSubscribeMessage, RecordsSubscribeMessageOptions, RecordsSubscribeReply, RecordSubscriptionHandler, RecordsWriteMessage, RecordsWriteMessageOptions } from './types/records-types.js'; import { AllowAllTenantGate } from './core/tenant-gate.js'; -import { DidResolver } from './did/did-resolver.js'; import { EventsGetHandler } from './handlers/events-get.js'; import { EventsQueryHandler } from './handlers/events-query.js'; import { EventsSubscribeHandler } from './handlers/events-subscribe.js'; @@ -31,6 +30,7 @@ import { RecordsQueryHandler } from './handlers/records-query.js'; import { RecordsReadHandler } from './handlers/records-read.js'; import { RecordsSubscribeHandler } from './handlers/records-subscribe.js'; import { RecordsWriteHandler } from './handlers/records-write.js'; +import { DidDhtMethod, DidIonMethod, DidKeyMethod, DidResolver } from '@web5/dids'; import { DwnInterfaceName, DwnMethodName } from './enums/dwn-interface-method.js'; export class Dwn { @@ -134,7 +134,7 @@ export class Dwn { * Creates an instance of the DWN. */ public static async create(config: DwnConfig): Promise { - config.didResolver ??= new DidResolver(); + config.didResolver ??= new DidResolver({ didResolvers: [DidKeyMethod, DidIonMethod, DidDhtMethod] }); config.tenantGate ??= new AllowAllTenantGate(); const dwn = new Dwn(config); diff --git a/src/handlers/events-get.ts b/src/handlers/events-get.ts index 31f459061..03d3d2a98 100644 --- a/src/handlers/events-get.ts +++ b/src/handlers/events-get.ts @@ -1,4 +1,4 @@ -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { EventLog } from '../types/event-log.js'; import type { MethodHandler } from '../types/method-handler.js'; import type { EventsGetMessage, EventsGetReply } from '../types/events-types.js'; diff --git a/src/handlers/events-query.ts b/src/handlers/events-query.ts index 179e9ec35..09eb05782 100644 --- a/src/handlers/events-query.ts +++ b/src/handlers/events-query.ts @@ -1,4 +1,4 @@ -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { EventLog } from '../types/event-log.js'; import type { MethodHandler } from '../types/method-handler.js'; import type { EventsQueryMessage, EventsQueryReply } from '../types/events-types.js'; @@ -32,8 +32,8 @@ export class EventsQueryHandler implements MethodHandler { return messageReplyFromError(e, 401); } - const logFilters = Events.convertFilters(message.descriptor.filters); - const { events, cursor } = await this.eventLog.queryEvents(tenant, logFilters, message.descriptor.cursor); + const eventFilters = Events.convertFilters(message.descriptor.filters); + const { events, cursor } = await this.eventLog.queryEvents(tenant, eventFilters, message.descriptor.cursor); return { status : { code: 200, detail: 'OK' }, diff --git a/src/handlers/events-subscribe.ts b/src/handlers/events-subscribe.ts index bba6c481e..2c1aa44c5 100644 --- a/src/handlers/events-subscribe.ts +++ b/src/handlers/events-subscribe.ts @@ -1,4 +1,4 @@ -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { MessageSubscriptionHandler } from '../types/message-types.js'; import type { MethodHandler } from '../types/method-handler.js'; import type { EventListener, EventStream } from '../types/subscriptions.js'; diff --git a/src/handlers/messages-get.ts b/src/handlers/messages-get.ts index 18786b8ce..b91c2eff8 100644 --- a/src/handlers/messages-get.ts +++ b/src/handlers/messages-get.ts @@ -1,5 +1,5 @@ import type { DataStore } from '../types/data-store.js'; -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { MessageStore } from '../types/message-store.js'; import type { MethodHandler } from '../types/method-handler.js'; import type { RecordsQueryReplyEntry } from '../types/records-types.js'; diff --git a/src/handlers/permissions-grant.ts b/src/handlers/permissions-grant.ts index 97e40e9c9..584d16c05 100644 --- a/src/handlers/permissions-grant.ts +++ b/src/handlers/permissions-grant.ts @@ -1,4 +1,4 @@ -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { EventLog } from '../types//event-log.js'; import type { EventStream } from '../types/subscriptions.js'; import type { GenericMessageReply } from '../types/message-types.js'; diff --git a/src/handlers/permissions-request.ts b/src/handlers/permissions-request.ts index 8e2efba68..1c7951f9b 100644 --- a/src/handlers/permissions-request.ts +++ b/src/handlers/permissions-request.ts @@ -1,4 +1,4 @@ -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { EventLog } from '../types//event-log.js'; import type { EventStream } from '../types/subscriptions.js'; import type { GenericMessageReply } from '../types/message-types.js'; diff --git a/src/handlers/permissions-revoke.ts b/src/handlers/permissions-revoke.ts index 9edefbedc..4232067b9 100644 --- a/src/handlers/permissions-revoke.ts +++ b/src/handlers/permissions-revoke.ts @@ -1,4 +1,4 @@ -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { EventLog } from '../types/event-log.js'; import type { EventStream } from '../types/subscriptions.js'; import type { GenericMessageReply } from '../types/message-types.js'; diff --git a/src/handlers/protocols-configure.ts b/src/handlers/protocols-configure.ts index 38e95dff5..f9fe94ad4 100644 --- a/src/handlers/protocols-configure.ts +++ b/src/handlers/protocols-configure.ts @@ -1,4 +1,4 @@ -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { EventLog } from '../types/event-log.js'; import type { EventStream } from '../types/subscriptions.js'; import type { GenericMessageReply } from '../types/message-types.js'; diff --git a/src/handlers/protocols-query.ts b/src/handlers/protocols-query.ts index a9b07b5da..3e5d58a0b 100644 --- a/src/handlers/protocols-query.ts +++ b/src/handlers/protocols-query.ts @@ -1,5 +1,5 @@ import type { DataStore } from '../types/data-store.js'; -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { MessageStore } from '../types//message-store.js'; import type { MethodHandler } from '../types/method-handler.js'; import type { ProtocolsConfigureMessage, ProtocolsQueryMessage, ProtocolsQueryReply } from '../types/protocols-types.js'; diff --git a/src/handlers/records-delete.ts b/src/handlers/records-delete.ts index 442c716e9..4697f8b42 100644 --- a/src/handlers/records-delete.ts +++ b/src/handlers/records-delete.ts @@ -1,5 +1,5 @@ import type { DataStore } from '../types/data-store.js'; -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { EventLog } from '../types/event-log.js'; import type { EventStream } from '../types/subscriptions.js'; import type { GenericMessageReply } from '../types/message-types.js'; diff --git a/src/handlers/records-query.ts b/src/handlers/records-query.ts index 1771b76f8..48b8429f3 100644 --- a/src/handlers/records-query.ts +++ b/src/handlers/records-query.ts @@ -1,5 +1,5 @@ import type { DataStore } from '../types/data-store.js'; -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { MessageStore } from '../types//message-store.js'; import type { MethodHandler } from '../types/method-handler.js'; import type { Filter, PaginationCursor } from '../types/query-types.js'; @@ -251,7 +251,9 @@ export class RecordsQueryHandler implements MethodHandler { await recordsQuery.authorizeDelegate(messageStore); } - // Only run protocol authz if message deliberately invokes it + // NOTE: not all RecordsQuery messages require protocol authorization even if the filter includes protocol-related fields, + // this is because we dynamically filter out records that the caller is not authorized to see. + // Currently only run protocol authorization if message deliberately invokes a protocol role. if (Records.shouldProtocolAuthorize(recordsQuery.signaturePayload!)) { await ProtocolAuthorization.authorizeQueryOrSubscribe(tenant, recordsQuery, messageStore); } diff --git a/src/handlers/records-read.ts b/src/handlers/records-read.ts index c7eb02c30..680c42d01 100644 --- a/src/handlers/records-read.ts +++ b/src/handlers/records-read.ts @@ -1,5 +1,5 @@ import type { DataStore } from '../types/data-store.js'; -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { Filter } from '../types/query-types.js'; import type { MessageStore } from '../types//message-store.js'; import type { MethodHandler } from '../types/method-handler.js'; diff --git a/src/handlers/records-subscribe.ts b/src/handlers/records-subscribe.ts index d1d33bda1..76eb25e89 100644 --- a/src/handlers/records-subscribe.ts +++ b/src/handlers/records-subscribe.ts @@ -1,4 +1,4 @@ -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { Filter } from '../types/query-types.js'; import type { MessageStore } from '../types//message-store.js'; import type { MethodHandler } from '../types/method-handler.js'; @@ -207,7 +207,9 @@ export class RecordsSubscribeHandler implements MethodHandler { await recordsSubscribe.authorizeDelegate(messageStore); } - // Only run protocol authz if message deliberately invokes it + // NOTE: not all RecordsSubscribe messages require protocol authorization even if the filter includes protocol-related fields, + // this is because we dynamically filter out records that the caller is not authorized to see. + // Currently only run protocol authorization if message deliberately invokes a protocol role. if (Records.shouldProtocolAuthorize(recordsSubscribe.signaturePayload!)) { await ProtocolAuthorization.authorizeQueryOrSubscribe(tenant, recordsSubscribe, messageStore); } diff --git a/src/handlers/records-write.ts b/src/handlers/records-write.ts index 65313c875..35f6f6b28 100644 --- a/src/handlers/records-write.ts +++ b/src/handlers/records-write.ts @@ -1,5 +1,5 @@ import type { DataStore } from '../types/data-store.js'; -import type { DidResolver } from '../did/did-resolver.js'; +import type { DidResolver } from '@web5/dids'; import type { EventLog } from '../types/event-log.js'; import type { EventStream } from '../types/subscriptions.js'; import type { GenericMessageReply } from '../types/message-types.js'; diff --git a/src/index.ts b/src/index.ts index 253ac411f..5ba197ec9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,5 @@ // export everything that we want to be consumable export type { DwnConfig } from './dwn.js'; -export type { DidMethodResolver, DwnServiceEndpoint, ServiceEndpoint, DidDocument, DidResolutionResult, DidResolutionMetadata, DidDocumentMetadata, VerificationMethod } from './types/did-types.js'; export type { EventLog } from './types/event-log.js'; export type { EventsGetMessage, EventsGetReply, EventsQueryMessage, EventsQueryReply, EventsSubscribeDescriptor, EventsSubscribeMessage, EventsSubscribeReply } from './types/events-types.js'; export type { EventStream, SubscriptionReply } from './types/subscriptions.js'; @@ -19,9 +18,6 @@ export { DataStore, PutResult, GetResult, AssociateResult } from './types/data-s export { DataStream } from './utils/data-stream.js'; export { DateSort } from './types/records-types.js'; export { DerivedPrivateJwk, HdKey, KeyDerivationScheme } from './utils/hd-key.js'; -export { DidKeyResolver } from './did/did-key-resolver.js'; -export { DidIonResolver } from './did/did-ion-resolver.js'; -export { DidResolver } from './did/did-resolver.js'; export { Dwn } from './dwn.js'; export { DwnConstant } from './core/dwn-constant.js'; export { DwnError, DwnErrorCode } from './core/dwn-error.js'; diff --git a/src/jose/jws/general/verifier.ts b/src/jose/jws/general/verifier.ts index 2b1f21997..7e33d330a 100644 --- a/src/jose/jws/general/verifier.ts +++ b/src/jose/jws/general/verifier.ts @@ -1,8 +1,7 @@ import type { Cache } from '../../../types/cache.js'; -import type { DidResolver } from '../../../did/did-resolver.js'; import type { GeneralJws } from '../../../types/jws-types.js'; import type { PublicJwk } from '../../../types/jose-types.js'; -import type { VerificationMethod } from '../../../types/did-types.js'; +import type { DidResolver, VerificationMethod } from '@web5/dids'; import { Jws } from '../../../utils/jws.js'; import { MemoryCache } from '../../../utils/memory-cache.js'; diff --git a/src/types/did-types.ts b/src/types/did-types.ts deleted file mode 100644 index ffbcc58fa..000000000 --- a/src/types/did-types.ts +++ /dev/null @@ -1,95 +0,0 @@ -import type { PublicJwk } from './jose-types.js'; - -/** - * A generalized interface that can be implemented for individual - * DID methods - */ -export interface DidMethodResolver { - /** - * @returns the DID method supported by {@link DidMethodResolver.resolve} - */ - method(): string; - - /** - * attempts to resolve the DID provided into its respective DID Document. - * More info on resolving DIDs can be found - * {@link https://www.w3.org/TR/did-core/#resolution here} - * @param did - the DID to resolve - * @throws {Error} if unable to resolve the DID - */ - resolve(did: string): Promise; -} - - - -export type DidDocument = { - '@context'?: 'https://www.w3.org/ns/did/v1' | string | string[] - id: string - alsoKnownAs?: string[] - controller?: string | string[] - verificationMethod?: VerificationMethod[] - service?: ServiceEndpoint[] - authentication?: VerificationMethod[] | string[] - assertionMethod?: VerificationMethod[] | string[] - keyAgreement?: VerificationMethod[] | string[] - capabilityInvocation?: VerificationMethod[] | string[] - capabilityDelegation?: VerificationMethod[] | string[] -}; - -export type DwnServiceEndpoint = { - nodes: string[] -}; - -export type ServiceEndpoint = { - id: string - type: string - serviceEndpoint: string | DwnServiceEndpoint - description?: string -}; - -export type VerificationMethod = { - id: string - // one of the valid verification method types as per - // https://www.w3.org/TR/did-spec-registries/#verification-method-types - type: string - // DID of the key's controller - controller: string - // a JSON Web Key that conforms to https://datatracker.ietf.org/doc/html/rfc7517 - publicKeyJwk?: PublicJwk -}; - -export type DidResolutionResult = { - '@context'?: 'https://w3id.org/did-resolution/v1' | string | string[] - didResolutionMetadata: DidResolutionMetadata - didDocument?: DidDocument - didDocumentMetadata: DidDocumentMetadata -}; - -export type DidResolutionMetadata = { - contentType?: string - error?: 'invalidDid' | 'notFound' | 'representationNotSupported' | - 'unsupportedDidMethod' | string -}; - -export type DidDocumentMetadata = { - // indicates the timestamp of the Create operation. ISO8601 timestamp - created?: string - // indicates the timestamp of the last Update operation for the document version which was - // resolved. ISO8601 timestamp - updated?: string - // indicates whether the DID has been deactivated - deactivated?: boolean - // indicates the version of the last Update operation for the document version which - // was resolved - versionId?: string - // indicates the timestamp of the next Update operation if the resolved document version - // is not the latest version of the document. - nextUpdate?: string - // indicates the version of the next Update operation if the resolved document version - // is not the latest version of the document. - nextVersionId?: string - // @see https://www.w3.org/TR/did-core/#dfn-equivalentid - equivalentId?: string - // @see https://www.w3.org/TR/did-core/#dfn-canonicalid - canonicalId?: string -}; \ No newline at end of file diff --git a/src/utils/events.ts b/src/utils/events.ts index f66c56dc0..f80953d58 100644 --- a/src/utils/events.ts +++ b/src/utils/events.ts @@ -10,6 +10,9 @@ import { isEmptyObject, removeUndefinedProperties } from './object.js'; * Class containing Events related utility methods. */ export class Events { + /** + * Normalizes/fixes the formatting of the given filters (such as URLs) so that they provide a consistent search experience. + */ public static normalizeFilters(filters: EventsFilter[]): EventsFilter[] { const eventsQueryFilters: EventsFilter[] = []; @@ -60,6 +63,9 @@ export class Events { return eventsQueryFilters; } + /** + * Converts an external-facing filter model into an internal-facing filer model used by data store. + */ private static convertFilter(filter: EventsMessageFilter): Filter { const filterCopy = { ...filter } as Filter; diff --git a/tests/core/auth.spec.ts b/tests/core/auth.spec.ts index 9432ecc13..4544971dd 100644 --- a/tests/core/auth.spec.ts +++ b/tests/core/auth.spec.ts @@ -1,13 +1,13 @@ import { authenticate } from '../../src/core/auth.js'; -import { DidResolver } from '../../src/index.js'; import { DwnErrorCode } from '../../src/core/dwn-error.js'; import { expect } from 'chai'; +import { DidDhtMethod, DidResolver } from '@web5/dids'; describe('Auth', () => { describe('authenticate()', () => { it('should throw if given JWS is `undefined`', async () => { const jws = undefined; - await expect(authenticate(jws, new DidResolver)).to.be.rejectedWith(DwnErrorCode.AuthenticateJwsMissing); + await expect(authenticate(jws, new DidResolver({ didResolvers: [DidDhtMethod] }))).to.be.rejectedWith(DwnErrorCode.AuthenticateJwsMissing); }); }); }); \ No newline at end of file diff --git a/tests/did/did-ion-resolver.spec.ts b/tests/did/did-ion-resolver.spec.ts deleted file mode 100644 index 62c5a0ab9..000000000 --- a/tests/did/did-ion-resolver.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import chaiAsPromised from 'chai-as-promised'; -import chai, { expect } from 'chai'; - -import { DidIonResolver } from '../../src/did/did-ion-resolver.js'; - -// extends chai to test promises -chai.use(chaiAsPromised); - -describe('DidIonResolver', () => { - const defaultResolutionEndpoint = 'https://ion.tbd.engineering/identifiers/'; - - it('should set a default resolution endpoint when none is given in constructor', async () => { - const didIonResolver = new DidIonResolver(); - - expect(didIonResolver['resolutionEndpoint']).to.equal(defaultResolutionEndpoint); - }); - - it('should resolve an ION DID correctly', async () => { - const did = 'did:ion:EiClkZMDxPKqC9c-umQfTkR8vvZ9JPhl_xLDI9Nfk38w5w'; - const didIonResolver = new DidIonResolver(); - - const resolutionDocument = await didIonResolver.resolve(did); - expect(resolutionDocument.didDocument?.id).to.equal(did); - expect(resolutionDocument.didDocumentMetadata.canonicalId).to.equal(did); - }); - - it('should throw if ION DID cannot be resolved', async () => { - const did = 'did:ion:SomethingThatCannotBeResolved'; - const didIonResolver = new DidIonResolver(); - - const resolutionPromise = didIonResolver.resolve(did); - await expect(resolutionPromise).to.be.rejectedWith('unable to resolve'); - }); -}); diff --git a/tests/did/did-key-resolver.spec.ts b/tests/did/did-key-resolver.spec.ts deleted file mode 100644 index bdcc4db19..000000000 --- a/tests/did/did-key-resolver.spec.ts +++ /dev/null @@ -1,74 +0,0 @@ -import chaiAsPromised from 'chai-as-promised'; -import varint from 'varint'; -import chai, { expect } from 'chai'; - -import { base58btc } from 'multiformats/bases/base58'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; - -// extends chai to test promises -chai.use(chaiAsPromised); - -describe('DidKeyResolver', () => { - it('should resolve a ed25519 `did:key` DID correctly', async () => { - // test vector taken from https://w3c-ccg.github.io/did-method-key/#ed25519-x25519 - const did = 'did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp'; - const resolver = new DidKeyResolver(); - - const resolutionDocument = await resolver.resolve(did); - const didDocument = resolutionDocument.didDocument!; - expect(didDocument.id).to.equal(did); - expect(didDocument['@context']?.indexOf('https://w3id.org/security/suites/ed25519-2020/v1')).to.not.equal(-1); - - const verificationMethod = resolutionDocument.didDocument?.verificationMethod![0]!; - expect(verificationMethod.publicKeyJwk?.x).to.equal('O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik'); - }); - - it('should resolve a secp256k1 `did:key` DID correctly', async () => { - // test vector taken from: - // https://github.com/transmute-industries/did-key.js/blob/main/packages/did-key-test-vectors/src/secp256k1/did-key-secp256k1-case-0.json - const did = 'did:key:zQ3shjRPgHQQbTtXyofk1ygghRJ75RZpXmWBMY1BKnhyz7zKp'; - const resolver = new DidKeyResolver(); - - const resolutionDocument = await resolver.resolve(did); - expect(resolutionDocument.didDocument?.id!).to.equal(did); - expect(resolutionDocument['@context']?.indexOf('https://w3id.org/security/suites/ed25519-2020/v1')).to.equal(-1); - - const verificationMethod = resolutionDocument.didDocument?.verificationMethod![0]!; - expect(verificationMethod.publicKeyJwk?.x).to.equal('RwiZITTa2Dcmq-V1j-5tgPUshOLO31FbsnhVS-7lskc'); - expect(verificationMethod.publicKeyJwk?.y).to.equal('3o1-UCc3ABh757P58gDISSc4hOj9qyfSGl3SGGA7xdc'); - }); - - it('should resolve a `did:key` DID that the library generates', async () => { - const { did, keyPair } = await DidKeyResolver.generate(); - const resolver = new DidKeyResolver(); - - const resolutionDocument = await resolver.resolve(did); - expect(resolutionDocument.didDocument?.id).to.equal(did); - - const verificationMethod = resolutionDocument.didDocument?.verificationMethod![0]!; - expect(verificationMethod.publicKeyJwk?.x).to.equal(keyPair.publicJwk.x); - }); - - it('should throw if DID is using unsupported multicodec', async () => { - const unsupportedMulticodec = varint.encode(0x01); // any unsupported multicodec - const idBytes = new Uint8Array(unsupportedMulticodec.length); // just allocate for the multicodec for testing - idBytes.set(unsupportedMulticodec, 0); - const id = base58btc.encode(idBytes); - - const did = `did:key:${id}`; - const didKeyResolver = new DidKeyResolver(); - - const resolutionDocument = await didKeyResolver.resolve(did); - expect(resolutionDocument.didDocument).to.equal(undefined); - expect(resolutionDocument.didResolutionMetadata.error).to.equal('invalidDid'); - }); - - it('should throw if key is invalid', async () => { - const did = 'did:ion:SomethingThatCannotBeResolved'; - const didIonResolver = new DidKeyResolver(); - - const resolutionDocument = await didIonResolver.resolve(did); - expect(resolutionDocument.didDocument).to.equal(undefined); - expect(resolutionDocument.didResolutionMetadata.error).to.equal('invalidDid'); - }); -}); diff --git a/tests/did/did-resolver.spec.ts b/tests/did/did-resolver.spec.ts deleted file mode 100644 index e9cac319e..000000000 --- a/tests/did/did-resolver.spec.ts +++ /dev/null @@ -1,95 +0,0 @@ -import chaiAsPromised from 'chai-as-promised'; -import sinon from 'sinon'; -import chai, { expect } from 'chai'; - -import { DidIonResolver } from '../../src/did/did-ion-resolver.js'; -import { DidResolver } from '../../src/did/did-resolver.js'; -import { DwnErrorCode } from '../../src/core/dwn-error.js'; - -// extends chai to test promises -chai.use(chaiAsPromised); - -describe('DidResolver', () => { - it('should cache the resolution result and use the cached result when available', async () => { - const did = 'did:ion:unusedDid'; - const didIonResolver = new DidIonResolver('unusedResolutionEndpoint'); - const didResolver = new DidResolver([didIonResolver]); - - const mockResolution = { - didDocument : 'any' as any, - didDocumentMetadata : 'any' as any, - didResolutionMetadata : 'any' as any - }; - const ionDidResolveSpy = sinon.stub(didIonResolver, 'resolve').resolves(mockResolution); - - const cacheGetSpy = sinon.spy(didResolver['cache'], 'get'); - - // calling resolve twice - const resolutionResult1 = await didResolver.resolve(did); - expect(resolutionResult1).to.equal(mockResolution); - const resolutionResult2 = await didResolver.resolve(did); - expect(resolutionResult2).to.equal(mockResolution); - - sinon.assert.calledTwice(cacheGetSpy); // should try to fetch from cache both times - sinon.assert.calledOnce(ionDidResolveSpy); // should only resolve using ION resolver once (the first time) - }); - - it('should throw error when invalid DID is used', async () => { - const did = 'blah'; - const didIonResolver = new DidIonResolver(); - const didResolver = new DidResolver([didIonResolver]); - - await expect(didResolver.resolve(did)).to.eventually.be.rejected.and.has.property('code', DwnErrorCode.DidNotValid); - }); - - it('should throw error when unsupported DID method is used', async () => { - const did = 'did:foo:EiClkZMDxPKqC9c-umQfTkR8vvZ9JPhl_xLDI9Nfk38w5w'; - const didIonResolver = new DidIonResolver(); - const didResolver = new DidResolver([didIonResolver]); - - await expect(didResolver.resolve(did)).to.eventually.be.rejected.and.has.property('code', DwnErrorCode.DidMethodNotSupported); - }); - - it('should throw error when resolution fails due to error in didResolutionMetadata', async () => { - const did = 'did:ion:EiClkZMDxPKqC9c-umQfTkR8vvZ9JPhl_xLDI9Nfk38w5w'; - const didIonResolver = new DidIonResolver('unusedResolutionEndpoint'); - const didResolver = new DidResolver([didIonResolver]); - - const mockResolution = { - didDocument : 'any' as any, - didResolutionMetadata : { error: 'some error' }, - didDocumentMetadata : 'any' as any - }; - - const ionDidResolveSpy = sinon.stub(didIonResolver, 'resolve').resolves(mockResolution); - const cacheGetSpy = sinon.spy(didResolver['cache'], 'get'); - - await expect(didResolver.resolve(did)).to.eventually.be.rejected.and.has.property('code', DwnErrorCode.DidResolutionFailed); - - sinon.assert.calledOnce(cacheGetSpy); - sinon.assert.calledOnce(ionDidResolveSpy); - - }); - - it('should throw error when resolution fails due to undefined didDocument', async () => { - const did = 'did:ion:EiClkZMDxPKqC9c-umQfTkR8vvZ9JPhl_xLDI9Nfk38w5w'; - const didIonResolver = new DidIonResolver('unusedResolutionEndpoint'); - const didResolver = new DidResolver([didIonResolver]); - - const mockResolution = { - didDocument : undefined, - didResolutionMetadata : 'any' as any, - didDocumentMetadata : 'any' as any - }; - - const ionDidResolveSpy = sinon.stub(didIonResolver, 'resolve').resolves(mockResolution); - const cacheGetSpy = sinon.spy(didResolver['cache'], 'get'); - - await expect(didResolver.resolve(did)).to.eventually.be.rejected.and.has.property('code', DwnErrorCode.DidResolutionFailed); - - sinon.assert.calledOnce(cacheGetSpy); - sinon.assert.calledOnce(ionDidResolveSpy); - - }); - -}); diff --git a/tests/dwn.spec.ts b/tests/dwn.spec.ts index fef8e8e35..650cc5a64 100644 --- a/tests/dwn.spec.ts +++ b/tests/dwn.spec.ts @@ -6,7 +6,6 @@ import chaiAsPromised from 'chai-as-promised'; import sinon from 'sinon'; import chai, { expect } from 'chai'; -import { DidKeyResolver } from '../src/did/did-key-resolver.js'; import { Dwn } from '../src/dwn.js'; import { Message } from '../src/core/message.js'; import { stubInterface } from 'ts-sinon'; @@ -50,7 +49,7 @@ export function testDwnClass(): void { describe('processMessage()', () => { it('should process RecordsWrite message signed by a `did:key` DID', async () => { // generate a `did:key` DID - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, @@ -62,7 +61,7 @@ export function testDwnClass(): void { }); it('should process RecordsQuery message', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { author, message } = await TestDataGenerator.generateRecordsQuery({ author: alice }); const tenant = author!.did; @@ -73,7 +72,7 @@ export function testDwnClass(): void { }); it('should process an EventsGet message', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateEventsGet({ author: alice }); const reply: EventsGetReply = await dwn.processMessage(alice.did, message); @@ -95,7 +94,7 @@ export function testDwnClass(): void { const validateJsonSchemaSpy = sinon.spy(Message, 'validateJsonSchema'); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const reply = await dwn.processMessage(alice.did, invalidMessage); sinon.assert.calledOnce(validateJsonSchemaSpy); @@ -105,7 +104,7 @@ export function testDwnClass(): void { }); it('should throw 400 if given no interface or method found in message', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const reply1 = await dwn.processMessage(alice.did, undefined ); // missing message entirely, thus missing both `interface` and `method` expect(reply1.status.code).to.equal(400); expect(reply1.status.detail).to.contain('Both interface and method must be present'); @@ -140,7 +139,7 @@ export function testDwnClass(): void { eventStream : eventStreamStub }); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { author, message } = await TestDataGenerator.generateRecordsQuery({ author: alice }); const tenant = author!.did; @@ -172,7 +171,7 @@ export function testDwnClass(): void { eventStream : eventStreamStub }); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { author, message } = await TestDataGenerator.generateRecordsQuery({ author: alice }); const tenant = author!.did; diff --git a/tests/event-log/event-log.spec.ts b/tests/event-log/event-log.spec.ts index dcb28a2fa..327939258 100644 --- a/tests/event-log/event-log.spec.ts +++ b/tests/event-log/event-log.spec.ts @@ -1,6 +1,5 @@ import type { EventLog } from '../../src/types/event-log.js'; -import { DidKeyResolver } from '../../src/index.js'; import { Message } from '../../src/core/message.js'; import { normalizeSchemaUrl } from '../../src/utils/url.js'; import { TestDataGenerator } from '../utils/test-data-generator.js'; @@ -103,7 +102,7 @@ export function testEventLog(): void { }); it('gets all events that occurred after the cursor provided', async () => { - const author = await DidKeyResolver.generate(); + const author = await TestDataGenerator.generateDidKeyPersona(); // create an initial record to and, issue a getEvents and grab the cursor const { message, recordsWrite } = await TestDataGenerator.generateRecordsWrite({ author }); @@ -233,7 +232,7 @@ export function testEventLog(): void { }); it('returns filtered events after cursor', async () => { - const author = await DidKeyResolver.generate(); + const author = await TestDataGenerator.generateDidKeyPersona(); // message 1 schema1 const { message, recordsWrite } = await TestDataGenerator.generateRecordsWrite({ author, schema: 'schema1' }); diff --git a/tests/handlers/events-get.spec.ts b/tests/handlers/events-get.spec.ts index eef10ce8b..14ac3ff64 100644 --- a/tests/handlers/events-get.spec.ts +++ b/tests/handlers/events-get.spec.ts @@ -6,18 +6,15 @@ import type { MessageStore } from '../../src/index.js'; +import { Dwn } from '../../src/index.js'; import { EventsGetHandler } from '../../src/handlers/events-get.js'; import { expect } from 'chai'; import { TestDataGenerator } from '../utils/test-data-generator.js'; -import { - DidKeyResolver, - DidResolver, - Dwn, -} from '../../src/index.js'; import { Message } from '../../src/core/message.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; export function testEventsGetHandler(): void { describe('EventsGetHandler.handle()', () => { @@ -31,7 +28,7 @@ export function testEventsGetHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -54,8 +51,8 @@ export function testEventsGetHandler(): void { }); it('returns a 401 if tenant is not author', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateEventsGet({ author: alice }); const eventsGetHandler = new EventsGetHandler(didResolver, eventLog); @@ -66,7 +63,7 @@ export function testEventsGetHandler(): void { }); it('returns a 400 if message is invalid', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateEventsGet({ author: alice }); (message['descriptor'] as any)['troll'] = 'hehe'; @@ -78,7 +75,7 @@ export function testEventsGetHandler(): void { }); it('returns all events for a tenant if cursor is not provided', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const expectedCids: string[] = []; for (let i = 0; i < 5; i += 1) { @@ -104,7 +101,7 @@ export function testEventsGetHandler(): void { }); it('returns all events after cursor if provided', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); for (let i = 0; i < 5; i += 1) { const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice }); diff --git a/tests/handlers/events-query.spec.ts b/tests/handlers/events-query.spec.ts index e1a967d3e..7aaab4298 100644 --- a/tests/handlers/events-query.spec.ts +++ b/tests/handlers/events-query.spec.ts @@ -5,16 +5,13 @@ import type { MessageStore } from '../../src/index.js'; +import { Dwn } from '../../src/index.js'; import { EventsQueryHandler } from '../../src/handlers/events-query.js'; import { expect } from 'chai'; import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; -import { - DidKeyResolver, - DidResolver, - Dwn, -} from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; export function testEventsQueryHandler(): void { @@ -29,7 +26,7 @@ export function testEventsQueryHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -52,8 +49,8 @@ export function testEventsQueryHandler(): void { }); it('returns a 401 if tenant is not author', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateEventsQuery({ author : alice, @@ -67,7 +64,7 @@ export function testEventsQueryHandler(): void { }); it('returns a 400 if message is invalid', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateEventsQuery({ author : alice, @@ -83,7 +80,7 @@ export function testEventsQueryHandler(): void { }); it('returns 400 if no filters are provided', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateEventsQuery({ author : alice, @@ -98,7 +95,7 @@ export function testEventsQueryHandler(): void { }); it('returns 400 if an empty filter without properties is provided', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateEventsQuery({ author : alice, diff --git a/tests/handlers/events-subscribe.spec.ts b/tests/handlers/events-subscribe.spec.ts index 96e6c4ae8..2e7094d40 100644 --- a/tests/handlers/events-subscribe.spec.ts +++ b/tests/handlers/events-subscribe.spec.ts @@ -1,8 +1,6 @@ import type { EventStream } from '../../src/types/subscriptions.js'; import type { DataStore, EventLog, GenericMessage, MessageStore } from '../../src/index.js'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; -import { DidResolver } from '../../src/did/did-resolver.js'; import { Dwn } from '../../src/dwn.js'; import { DwnErrorCode } from '../../src/core/dwn-error.js'; import { EventsSubscribe } from '../../src/interfaces/events-subscribe.js'; @@ -11,6 +9,7 @@ import { Message } from '../../src/core/message.js'; import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; import sinon from 'sinon'; import chai, { expect } from 'chai'; @@ -32,7 +31,7 @@ export function testEventsSubscribeHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -66,7 +65,7 @@ export function testEventsSubscribeHandler(): void { await dwn.close(); // close the original dwn instance dwn = await Dwn.create({ didResolver, messageStore, dataStore, eventLog }); // leave out eventStream - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // attempt to subscribe const { message } = await EventsSubscribe.create({ signer: Jws.createSigner(alice) }); const subscriptionMessageReply = await dwn.processMessage(alice.did, message, { subscriptionHandler: (_) => {} }); @@ -86,7 +85,7 @@ export function testEventsSubscribeHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -118,7 +117,7 @@ export function testEventsSubscribeHandler(): void { }); it('returns a 400 if message is invalid', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateEventsSubscribe({ author: alice }); // add an invalid property to the descriptor @@ -132,7 +131,7 @@ export function testEventsSubscribeHandler(): void { it('should allow tenant to subscribe their own event stream', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // set up a promise to read later that captures the emitted messageCid let handler; @@ -166,8 +165,8 @@ export function testEventsSubscribeHandler(): void { }); it('should not allow non-tenant to subscribe to an event stream they are not authorized for', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // test anonymous request const anonymousSubscription = await TestDataGenerator.generateEventsSubscribe(); diff --git a/tests/handlers/messages-get.spec.ts b/tests/handlers/messages-get.spec.ts index 7c98ea1a3..1be053c7d 100644 --- a/tests/handlers/messages-get.spec.ts +++ b/tests/handlers/messages-get.spec.ts @@ -13,7 +13,8 @@ import { stubInterface } from 'ts-sinon'; import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; -import { DidKeyResolver, DidResolver, Dwn, DwnConstant } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; +import { Dwn, DwnConstant } from '../../src/index.js'; import sinon from 'sinon'; @@ -29,7 +30,7 @@ export function testMessagesGetHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -54,8 +55,8 @@ export function testMessagesGetHandler(): void { }); it('returns a 401 if tenant is not author', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { recordsWrite } = await TestDataGenerator.generateRecordsWrite({ author: alice }); const { message } = await TestDataGenerator.generateMessagesGet({ @@ -69,7 +70,7 @@ export function testMessagesGetHandler(): void { }); it('returns a 400 if message is invalid', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { recordsWrite } = await TestDataGenerator.generateRecordsWrite({ author: alice }); const { message } = await TestDataGenerator.generateMessagesGet({ @@ -85,7 +86,7 @@ export function testMessagesGetHandler(): void { }); it('returns a 400 if message contains an invalid message cid', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { recordsWrite } = await TestDataGenerator.generateRecordsWrite({ author: alice }); const { message } = await TestDataGenerator.generateMessagesGet({ @@ -103,7 +104,7 @@ export function testMessagesGetHandler(): void { }); it('returns all requested messages', async () => { - const did = await DidKeyResolver.generate(); + const did = await TestDataGenerator.generateDidKeyPersona(); const alice = await TestDataGenerator.generatePersona(did); const messageCids: string[] = []; @@ -158,7 +159,7 @@ export function testMessagesGetHandler(): void { }); it('returns message as undefined in reply entry when a messageCid is not found', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { recordsWrite } = await TestDataGenerator.generateRecordsWrite({ author: alice }); const recordsWriteMessageCid = await Message.getCid(recordsWrite.message); @@ -187,7 +188,7 @@ export function testMessagesGetHandler(): void { const messagesGetHandler = new MessagesGetHandler(didResolver, messageStore, dataStore); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { recordsWrite } = await TestDataGenerator.generateRecordsWrite({ author: alice }); const recordsWriteMessageCid = await Message.getCid(recordsWrite.message); @@ -208,7 +209,7 @@ export function testMessagesGetHandler(): void { }); it('includes encodedData in reply entry if the data is available and dataSize < threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({ author : alice, @@ -238,8 +239,8 @@ export function testMessagesGetHandler(): void { }); it('does not return messages that belong to other tenants', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice diff --git a/tests/handlers/permissions-grant.spec.ts b/tests/handlers/permissions-grant.spec.ts index b2c9c7328..4a62c2cf4 100644 --- a/tests/handlers/permissions-grant.spec.ts +++ b/tests/handlers/permissions-grant.spec.ts @@ -7,8 +7,6 @@ import type { import sinon from 'sinon'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; -import { DidResolver } from '../../src/did/did-resolver.js'; import { Dwn } from '../../src/dwn.js'; import { DwnErrorCode } from '../../src/core/dwn-error.js'; import { expect } from 'chai'; @@ -20,6 +18,7 @@ import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; import { Time } from '../../src/utils/time.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; import { DwnInterfaceName, DwnMethodName } from '../../src/enums/dwn-interface-method.js'; export function testPermissionsGrantHandler(): void { @@ -36,7 +35,7 @@ export function testPermissionsGrantHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -61,7 +60,7 @@ export function testPermissionsGrantHandler(): void { }); it('should accept a PermissionsGrant with permissionsRequestId omitted', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsGrant({ author : alice, @@ -74,7 +73,7 @@ export function testPermissionsGrantHandler(): void { }); it('should accept a PermissionsGrant with associated PermissionsRequest', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { permissionsRequest } = await TestDataGenerator.generatePermissionsRequest({ author: alice, @@ -94,20 +93,23 @@ export function testPermissionsGrantHandler(): void { }); it('should return 401 if authentication fails', async () => { - const alice = await DidKeyResolver.generate(); - alice.keyId = 'wrongValue'; // to fail authentication + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsGrant({ author: alice, }); + // use a bad signature to fail authentication + const badSignature = await TestDataGenerator.randomSignatureString(); + message.authorization.signature.signatures[0].signature = badSignature; + const reply = await dwn.processMessage(alice.did, message); expect(reply.status.code).to.equal(401); - expect(reply.status.detail).to.contain('not a valid DID'); + expect(reply.status.detail).to.contain(DwnErrorCode.GeneralJwsVerifierInvalidSignature); }); it('should reject if author does not match grantedBy', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsGrant({ author : alice, @@ -120,8 +122,8 @@ export function testPermissionsGrantHandler(): void { }); it('should reject if grantedBy is not a delegate and does not match grantedFor', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsGrant({ author : alice, @@ -135,7 +137,7 @@ export function testPermissionsGrantHandler(): void { }); it('should return 400 if failure parsing the message', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsGrant(); const permissionsRequestHandler = new PermissionsGrantHandler(didResolver, messageStore, eventLog, eventStream); @@ -149,7 +151,7 @@ export function testPermissionsGrantHandler(): void { describe('scope validation', () => { it('ensures that `schema` and protocol related fields `protocol`, `contextId` or `protocolPath` are not both present', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // Options to create a grant with `schema` in its `scope` const permissionsGrantBaseOptions = { @@ -220,7 +222,7 @@ export function testPermissionsGrantHandler(): void { }); it('ensures that `contextId` and `protocolPath` are not both present in grant scope', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const contextIdAndProtocolPathGrant = await TestDataGenerator.generatePermissionsGrant({ author : alice, @@ -254,7 +256,7 @@ export function testPermissionsGrantHandler(): void { describe('event log', () => { it('should add event for PermissionsGrant', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsGrant({ author : alice, grantedBy : alice.did, @@ -271,7 +273,7 @@ export function testPermissionsGrantHandler(): void { }); it('should not add a new event if we have already stored this PermissionsRequest', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsGrant({ author : alice, grantedBy : alice.did, diff --git a/tests/handlers/permissions-request.spec.ts b/tests/handlers/permissions-request.spec.ts index 4dbf59ba2..8dc1934df 100644 --- a/tests/handlers/permissions-request.spec.ts +++ b/tests/handlers/permissions-request.spec.ts @@ -8,8 +8,6 @@ import type { import { expect } from 'chai'; import sinon from 'sinon'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; -import { DidResolver } from '../../src/did/did-resolver.js'; import { Dwn } from '../../src/dwn.js'; import { Message } from '../../src/core/message.js'; import { PermissionsRequest } from '../../src/interfaces/permissions-request.js'; @@ -17,7 +15,8 @@ import { PermissionsRequestHandler } from '../../src/handlers/permissions-reques import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; -import { DwnInterfaceName, DwnMethodName } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; +import { DwnErrorCode, DwnInterfaceName, DwnMethodName } from '../../src/index.js'; export function testPermissionsRequestHandler(): void { describe('PermissionsRequestHandler.handle()', () => { @@ -33,7 +32,7 @@ export function testPermissionsRequestHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -59,8 +58,8 @@ export function testPermissionsRequestHandler(): void { it('should accept a PermissionsRequest with conditions omitted', async () => { // scenario: Bob sends a PermissionsRequest to Alice's DWN - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsRequest({ author : bob, @@ -79,8 +78,7 @@ export function testPermissionsRequestHandler(): void { }); it('should return 401 if auth fails', async () => { - const alice = await DidKeyResolver.generate(); - alice.keyId = 'wrongValue'; // to fail authentication + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsRequest({ author : alice, scope : { @@ -89,13 +87,17 @@ export function testPermissionsRequestHandler(): void { } }); + // use a bad signature to fail authentication + const badSignature = await TestDataGenerator.randomSignatureString(); + message.authorization.signature.signatures[0].signature = badSignature; + const reply = await dwn.processMessage(alice.did, message); expect(reply.status.code).to.equal(401); - expect(reply.status.detail).to.contain('not a valid DID'); + expect(reply.status.detail).to.contain(DwnErrorCode.GeneralJwsVerifierInvalidSignature); }); it('should return 400 if failure parsing the message', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsRequest(); const permissionsRequestHandler = new PermissionsRequestHandler(didResolver, messageStore, eventLog, eventStream); @@ -109,7 +111,7 @@ export function testPermissionsRequestHandler(): void { describe('event log', () => { it('should add event for PermissionsRequest', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsRequest({ author : alice, scope : { @@ -129,7 +131,7 @@ export function testPermissionsRequestHandler(): void { }); it('should not add a new event if we have already stored this PermissionsRequest', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsRequest({ author : alice, scope : { diff --git a/tests/handlers/permissions-revoke.spec.ts b/tests/handlers/permissions-revoke.spec.ts index 73be4efe1..ee9a4664a 100644 --- a/tests/handlers/permissions-revoke.spec.ts +++ b/tests/handlers/permissions-revoke.spec.ts @@ -3,8 +3,6 @@ import sinon from 'sinon'; import type { DataStore, EventLog, EventStream, MessageStore } from '../../src/index.js'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; -import { DidResolver } from '../../src/did/did-resolver.js'; import { Dwn } from '../../src/dwn.js'; import { DwnErrorCode } from '../../src/core/dwn-error.js'; import { Message } from '../../src/core/message.js'; @@ -13,6 +11,7 @@ import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; import { Time } from '../../src/utils/time.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; describe('PermissionsRevokeHandler.handle()', () => { let didResolver: DidResolver; @@ -24,7 +23,7 @@ describe('PermissionsRevokeHandler.handle()', () => { describe('functional tests', () => { before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); // important to follow this pattern to initialize and clean the message and data store in tests // so that different suites can reuse the same block store and index location for testing @@ -53,8 +52,8 @@ describe('PermissionsRevokeHandler.handle()', () => { it('should accept a PermissionsRevoke that revokes an existing grant', async () => { // scenario: Alice issues a grant to Bob, then she revokes the grant. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice issues a grant @@ -77,19 +76,22 @@ describe('PermissionsRevokeHandler.handle()', () => { }); it('should return 401 if authentication fails', async () => { - const alice = await DidKeyResolver.generate(); - alice.keyId = 'wrongValue'; // to fail authentication + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsRevoke({ author: alice, }); + // use a bad signature to fail authentication + const badSignature = await TestDataGenerator.randomSignatureString(); + message.authorization.signature.signatures[0].signature = badSignature; + const reply = await dwn.processMessage(alice.did, message); expect(reply.status.code).to.equal(401); - expect(reply.status.detail).to.contain('not a valid DID'); + expect(reply.status.detail).to.contain(DwnErrorCode.GeneralJwsVerifierInvalidSignature); }); it('should reject with 400 if failure parsing the message', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsRevoke(); // stub the `parse()` function to throw an error @@ -100,7 +102,7 @@ describe('PermissionsRevokeHandler.handle()', () => { }); it('should reject with 400 if the associated grant cannot be found', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { permissionsRevoke } = await TestDataGenerator.generatePermissionsRevoke({ author : alice, @@ -112,7 +114,7 @@ describe('PermissionsRevokeHandler.handle()', () => { }); it('should reject with 400 if the associated grant was issued after the revoke was created', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const preGrantTimeStamp = Time.getCurrentTimestamp(); await Time.sleep(10); @@ -139,8 +141,8 @@ describe('PermissionsRevokeHandler.handle()', () => { it('should reject with 401 if the revoke was not authored by the DID in the `grantedFor` of the grant', async () => { // scenario: Alice issues a grant. Bob tries and failes to revoke the grant. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { permissionsGrant } = await TestDataGenerator.generatePermissionsGrant({ author : alice, @@ -160,7 +162,7 @@ describe('PermissionsRevokeHandler.handle()', () => { }); it('should reject with 409 if older PermissionsRevoke messages exist for the same grant', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // Create a grant const { permissionsGrant } = await TestDataGenerator.generatePermissionsGrant({ @@ -189,7 +191,7 @@ describe('PermissionsRevokeHandler.handle()', () => { }); it('should reject with 409 if a PermissionsRevoke message exists for same grant, same revocation time, and lower lexicographic CID', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // Create a grant const { permissionsGrant } = await TestDataGenerator.generatePermissionsGrant({ @@ -234,7 +236,7 @@ describe('PermissionsRevokeHandler.handle()', () => { }); it('should accept revokes that are older than the oldest existing revoke', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // Create a grant const { permissionsGrant } = await TestDataGenerator.generatePermissionsGrant({ @@ -268,7 +270,7 @@ describe('PermissionsRevokeHandler.handle()', () => { describe('event log', () => { it('should add event for PermissionsRevoke', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // Create a grant, adding one event const { permissionsGrant } = await TestDataGenerator.generatePermissionsGrant({ @@ -300,7 +302,7 @@ describe('PermissionsRevokeHandler.handle()', () => { it('should remove events for existing PermissionsRevoke messages with timestamp after the incoming message', async () => { // scenario: A grant is issued, adding one event. Then the grant is revoked, adding another event. // Then, a slightly earlier revoke is processed, causing the existing revoke to be purged. - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // Create a grant, adding one event const { permissionsGrant } = await TestDataGenerator.generatePermissionsGrant({ diff --git a/tests/handlers/protocols-configure.spec.ts b/tests/handlers/protocols-configure.spec.ts index 2dd03c51a..d820465e3 100644 --- a/tests/handlers/protocols-configure.spec.ts +++ b/tests/handlers/protocols-configure.spec.ts @@ -14,7 +14,6 @@ import chai, { expect } from 'chai'; import dexProtocolDefinition from '../vectors/protocol-definitions/dex.json' assert { type: 'json' }; import minimalProtocolDefinition from '../vectors/protocol-definitions/minimal.json' assert { type: 'json' }; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; import { GeneralJwsBuilder } from '../../src/jose/jws/general/builder.js'; import { lexicographicalCompare } from '../../src/utils/string.js'; import { Message } from '../../src/core/message.js'; @@ -24,7 +23,8 @@ import { TestStores } from '../test-stores.js'; import { TestStubGenerator } from '../utils/test-stub-generator.js'; import { Time } from '../../src/utils/time.js'; -import { DidResolver, Dwn, DwnErrorCode, Encoder, Jws } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; +import { Dwn, DwnErrorCode, Encoder, Jws } from '../../src/index.js'; chai.use(chaiAsPromised); @@ -42,7 +42,7 @@ export function testProtocolsConfigureHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -67,7 +67,7 @@ export function testProtocolsConfigureHandler(): void { }); it('should allow a protocol definition with schema or dataFormat omitted', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({ @@ -102,17 +102,20 @@ export function testProtocolsConfigureHandler(): void { }); it('should return 401 if auth fails', async () => { - const alice = await DidKeyResolver.generate(); - alice.keyId = 'wrongValue'; // to fail authentication + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateProtocolsConfigure({ author: alice }); + // use a bad signature to fail authentication + const badSignature = await TestDataGenerator.randomSignatureString(); + message.authorization.signature.signatures[0].signature = badSignature; + const reply = await dwn.processMessage(alice.did, message); expect(reply.status.code).to.equal(401); - expect(reply.status.detail).to.contain('not a valid DID'); + expect(reply.status.detail).to.contain(DwnErrorCode.GeneralJwsVerifierInvalidSignature); }); it('should be able to overwrite existing protocol if timestamp is newer', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -154,7 +157,7 @@ export function testProtocolsConfigureHandler(): void { }); it('should only be able to overwrite existing protocol if new protocol is lexicographically larger and timestamps are identical', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // Alter each protocol slightly to create lexicographic difference between them const protocolDefinition1 = { @@ -224,7 +227,7 @@ export function testProtocolsConfigureHandler(): void { }); it('should return 400 if protocol is not normalized', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // query for non-normalized protocol const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({ @@ -248,7 +251,7 @@ export function testProtocolsConfigureHandler(): void { }); it('should return 400 if schema is not normalized', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = dexProtocolDefinition; const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({ @@ -273,8 +276,8 @@ export function testProtocolsConfigureHandler(): void { it('rejects non-tenant non-granted ProtocolsConfigures with 401', async () => { // Bob tries to ProtocolsConfigure to Alice's DWN without a PermissionsGrant - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = dexProtocolDefinition; const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({ @@ -288,7 +291,7 @@ export function testProtocolsConfigureHandler(): void { describe('event log', () => { it('should add event for ProtocolsConfigure', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateProtocolsConfigure({ author: alice }); const reply = await dwn.processMessage(alice.did, message); @@ -302,7 +305,7 @@ export function testProtocolsConfigureHandler(): void { }); it('should delete older ProtocolsConfigure events when one is overwritten', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const oldestWrite = await TestDataGenerator.generateProtocolsConfigure({ author: alice, protocolDefinition: minimalProtocolDefinition }); await Time.minimalSleep(); const newestWrite = await TestDataGenerator.generateProtocolsConfigure({ author: alice, protocolDefinition: minimalProtocolDefinition }); diff --git a/tests/handlers/protocols-query.spec.ts b/tests/handlers/protocols-query.spec.ts index f654fa441..7eda7be4a 100644 --- a/tests/handlers/protocols-query.spec.ts +++ b/tests/handlers/protocols-query.spec.ts @@ -10,7 +10,6 @@ import chaiAsPromised from 'chai-as-promised'; import sinon from 'sinon'; import chai, { expect } from 'chai'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; import { GeneralJwsBuilder } from '../../src/jose/jws/general/builder.js'; import { Message } from '../../src/core/message.js'; import { TestDataGenerator } from '../utils/test-data-generator.js'; @@ -18,7 +17,8 @@ import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; import { TestStubGenerator } from '../utils/test-stub-generator.js'; import { Time } from '../../src/utils/time.js'; -import { DidResolver, Dwn, DwnErrorCode, DwnInterfaceName, DwnMethodName, Encoder, Jws, ProtocolsQuery } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; +import { Dwn, DwnErrorCode, DwnInterfaceName, DwnMethodName, Encoder, Jws, ProtocolsQuery } from '../../src/index.js'; chai.use(chaiAsPromised); @@ -36,7 +36,7 @@ export function testProtocolsQueryHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -166,7 +166,7 @@ export function testProtocolsQueryHandler(): void { }); it('should return 400 if protocol is not normalized', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // query for non-normalized protocol const protocolsQuery = await TestDataGenerator.generateProtocolsQuery({ @@ -209,21 +209,23 @@ export function testProtocolsQueryHandler(): void { }); it('should return 401 if auth fails', async () => { - const alice = await DidKeyResolver.generate(); - alice.keyId = 'wrongValue'; // to fail authentication + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateProtocolsQuery({ author: alice }); - const reply = await dwn.processMessage(alice.did, message); + // use a bad signature to fail authentication + const badSignature = await TestDataGenerator.randomSignatureString(); + message.authorization!.signature.signatures[0].signature = badSignature; + const reply = await dwn.processMessage(alice.did, message); expect(reply.status.code).to.equal(401); - expect(reply.status.detail).to.contain('not a valid DID'); + expect(reply.status.detail).to.contain(DwnErrorCode.GeneralJwsVerifierInvalidSignature); }); describe('Grant authorization', () => { it('allows an external party to ProtocolsConfigure if they have an active grant', async () => { // scenario: Alice grants Bob the access to ProtocolsConfigure on her DWN, then Bob does a ProtocolsConfigure - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice gives Bob a PermissionsGrant with scope ProtocolsConfigure const permissionsGrant = await TestDataGenerator.generatePermissionsGrant({ @@ -250,8 +252,8 @@ export function testProtocolsQueryHandler(): void { it('rejects with 401 an external party attempt to ProtocolsConfigure if they present an expired grant', async () => { // scenario: Alice grants Bob access to ProtocolsConfigure, but when Bob invokes the grant it has expired - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice gives Bob a PermissionsGrant with scope ProtocolsConfigure and an expiry time const dateGranted = Time.getCurrentTimestamp(); @@ -284,8 +286,8 @@ export function testProtocolsQueryHandler(): void { it('rejects with 401 an external partys attempt to ProtocolsQuery if the grant is not yet active', async () => { // scenario: Alice grants Bob access to ProtocolsConfigure, but Bob's message has a timestamp just before the grant is active - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Set up timestamps const protocolsQueryTimestamp = Time.getCurrentTimestamp(); @@ -321,8 +323,8 @@ export function testProtocolsQueryHandler(): void { it('rejects with 401 an external partys attempt to ProtocolsQuery if the grant has been revoked', async () => { // Alice grants and revokes Bob access to ProtocolsConfigure. Bob tries to invoke the revoked grant - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice gives Bob a PermissionsGrant with scope ProtocolsConfigure const permissionsGrant = await TestDataGenerator.generatePermissionsGrant({ @@ -360,8 +362,8 @@ export function testProtocolsQueryHandler(): void { it('rejects with 401 an external party attempts to ProtocolsQuery if grant has different DWN interface scope', async () => { // scenario: Alice grants Bob access to RecordsRead, then Bob tries to invoke the grant with ProtocolsConfigure - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice gives Bob a PermissionsGrant with scope RecordsRead const permissionsGrant = await TestDataGenerator.generatePermissionsGrant({ @@ -390,8 +392,8 @@ export function testProtocolsQueryHandler(): void { it('rejects with 401 if the PermissionsGrant cannot be found', async () => { // scenario: Bob uses a permissionsGrantId to ProtocolsConfigure, but no PermissionsGrant can be found. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Bob tries to ProtocolsConfigure const protocolsQuery = await TestDataGenerator.generateProtocolsQuery({ @@ -405,9 +407,9 @@ export function testProtocolsQueryHandler(): void { it('rejects with 401 if the PermissionsGrant has not been grantedTo the author', async () => { // Alice gives a PermissionsGrant to Bob, then Carol tries to invoke it to ProtocolsConfigure on Alice's DWN - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // Alice gives Bob a PermissionsGrant with scope ProtocolsConfigure const permissionsGrant = await TestDataGenerator.generatePermissionsGrant({ @@ -436,9 +438,9 @@ export function testProtocolsQueryHandler(): void { it('rejects with 401 if the PermissionsGrant has not been grantedFor the tenant', async () => { // Alice gives a PermissionsGrant to Carol, which Bob stores on his DWN. // Then Carol tries to invoke it to ProtocolsConfigure on Bob's DWN. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // Alice gives Bob a PermissionsGrant with scope ProtocolsConfigure const permissionsGrant = await TestDataGenerator.generatePermissionsGrant({ diff --git a/tests/handlers/records-delete.spec.ts b/tests/handlers/records-delete.spec.ts index d5d192310..b41cde81a 100644 --- a/tests/handlers/records-delete.spec.ts +++ b/tests/handlers/records-delete.spec.ts @@ -17,7 +17,6 @@ import recipientCanProtocolDefinition from '../vectors/protocol-definitions/reci import threadRoleProtocolDefinition from '../vectors/protocol-definitions/thread-role.json' assert { type: 'json' }; import { ArrayUtility } from '../../src/utils/array.js'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; import { DwnErrorCode } from '../../src/core/dwn-error.js'; import { DwnMethodName } from '../../src/enums/dwn-interface-method.js'; import { Message } from '../../src/core/message.js'; @@ -29,7 +28,8 @@ import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; import { TestStubGenerator } from '../utils/test-stub-generator.js'; import { Time } from '../../src/utils/time.js'; -import { DataStream, DidResolver, Dwn, Encoder, Jws, RecordsDelete, RecordsRead, RecordsWrite } from '../../src/index.js'; +import { DataStream, Dwn, Encoder, Jws, RecordsDelete, RecordsRead, RecordsWrite } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; chai.use(chaiAsPromised); @@ -47,7 +47,7 @@ export function testRecordsDeleteHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -72,7 +72,7 @@ export function testRecordsDeleteHandler(): void { }); it('should handle RecordsDelete successfully and return 404 if deleting a deleted record', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // insert data const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice }); @@ -114,8 +114,8 @@ export function testRecordsDeleteHandler(): void { }); it('should not affect other records or tenants with the same data', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const data = Encoder.stringToBytes('test'); // alice writes a records with data @@ -188,7 +188,7 @@ export function testRecordsDeleteHandler(): void { }); it('should return 404 if deleting a non-existent record', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // testing deleting a non-existent record const recordsDelete = await RecordsDelete.create({ @@ -201,7 +201,7 @@ export function testRecordsDeleteHandler(): void { }); it('should be disallowed if there is a newer RecordsWrite already in the DWN ', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // initial write const initialWriteData = await TestDataGenerator.generateRecordsWrite({ author: alice }); @@ -241,7 +241,7 @@ export function testRecordsDeleteHandler(): void { }); it('should be able to delete then rewrite the same data', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const data = Encoder.stringToBytes('test'); const encodedData = Encoder.bytesToBase64Url(data); @@ -509,9 +509,9 @@ export function testRecordsDeleteHandler(): void { // Bob invokes his admin role to delete the 'thread/chat'. Carol is unable to delete // the 'thread/chat'. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -579,9 +579,9 @@ export function testRecordsDeleteHandler(): void { // scenario: Alice adds Bob as an 'admin' $globalRole. She writes a 'chat'. // Bob invokes his admin role to delete the 'chat'. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -637,8 +637,8 @@ export function testRecordsDeleteHandler(): void { it('should return 401 if message is not authorized', async () => { // scenario: Alice creates a record and Bob is unable to delete it. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const recordsWrite = await TestDataGenerator.generateRecordsWrite({ author: alice, @@ -656,7 +656,7 @@ export function testRecordsDeleteHandler(): void { }); it('should index additional properties from the RecordsWrite being deleted', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // initial write const initialWriteData = await TestDataGenerator.generateRecordsWrite({ author: alice, schema: 'testSchema' }); @@ -687,7 +687,7 @@ export function testRecordsDeleteHandler(): void { describe('event log', () => { it('should include RecordsDelete event and keep initial RecordsWrite event', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice }); const writeReply = await dwn.processMessage(alice.did, message, { dataStream }); diff --git a/tests/handlers/records-query.spec.ts b/tests/handlers/records-query.spec.ts index ae660895d..f5e52a69c 100644 --- a/tests/handlers/records-query.spec.ts +++ b/tests/handlers/records-query.spec.ts @@ -13,7 +13,6 @@ import threadRoleProtocolDefinition from '../vectors/protocol-definitions/thread import { ArrayUtility } from '../../src/utils/array.js'; import { DateSort } from '../../src/types/records-types.js'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; import { DwnConstant } from '../../src/core/dwn-constant.js'; import { DwnErrorCode } from '../../src/core/dwn-error.js'; import { Encoder } from '../../src/utils/encoder.js'; @@ -27,7 +26,8 @@ import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; import { TestStubGenerator } from '../utils/test-stub-generator.js'; -import { DidResolver, Dwn, RecordsWrite, Time } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; +import { Dwn, RecordsWrite, Time } from '../../src/index.js'; chai.use(chaiAsPromised); @@ -44,7 +44,7 @@ export function testRecordsQueryHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -157,7 +157,7 @@ export function testRecordsQueryHandler(): void { it('should return `encodedData` if data size is within the spec threshold', async () => { const data = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded); // within/on threshold - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write= await TestDataGenerator.generateRecordsWrite({ author: alice, data }); const writeReply = await dwn.processMessage(alice.did, write.message, { dataStream: write.dataStream }); @@ -173,7 +173,7 @@ export function testRecordsQueryHandler(): void { it('should not return `encodedData` if data size is greater then spec threshold', async () => { const data = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1); // exceeding threshold - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write= await TestDataGenerator.generateRecordsWrite({ author: alice, data }); const writeReply = await dwn.processMessage(alice.did, write.message, { dataStream: write.dataStream }); @@ -188,7 +188,7 @@ export function testRecordsQueryHandler(): void { }); it('should include `initialWrite` property if RecordsWrite is not initial write', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write = await TestDataGenerator.generateRecordsWrite({ author: alice, published: false }); const writeReply = await dwn.processMessage(alice.did, write.message, { dataStream: write.dataStream }); @@ -212,8 +212,8 @@ export function testRecordsQueryHandler(): void { it('should be able to query by attester', async () => { // scenario: 2 records authored by alice, 1st attested by alice, 2nd attested by bob - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const recordsWrite1 = await TestDataGenerator.generateRecordsWrite({ author: alice, attesters: [alice] }); const recordsWrite2 = await TestDataGenerator.generateRecordsWrite({ author: alice, attesters: [bob] }); @@ -241,7 +241,7 @@ export function testRecordsQueryHandler(): void { expect(reply2Attester).to.equal(bob.did); // testing attester filter that yields no results - const carol = await DidKeyResolver.generate(); + const carol = await TestDataGenerator.generateDidKeyPersona(); const recordsQuery3 = await TestDataGenerator.generateRecordsQuery({ author: alice, filter: { attester: carol.did } }); const reply3 = await dwn.processMessage(alice.did, recordsQuery3.message); expect(reply3.entries?.length).to.equal(0); @@ -250,8 +250,8 @@ export function testRecordsQueryHandler(): void { it('should be able to query by author', async () => { // scenario alice and bob both author records into alice's DWN. // alice is able to filter for records authored by bob. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = freeForAll; @@ -314,8 +314,8 @@ export function testRecordsQueryHandler(): void { }); it('should be able to query for published records', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // create a published record const publishedWrite = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true, schema: 'post' }); @@ -382,7 +382,7 @@ export function testRecordsQueryHandler(): void { }); it('should be able to query for unpublished records', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // create a published record const publishedWrite = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true, schema: 'post' }); @@ -417,8 +417,8 @@ export function testRecordsQueryHandler(): void { }); it('should not be able to query for unpublished records if unauthorized', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // create a published record const publishedWrite = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true, schema: 'post' }); @@ -464,7 +464,7 @@ export function testRecordsQueryHandler(): void { }); it('should be able to query for a record by a dataCid', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // create a record const writeRecord = await TestDataGenerator.generateRecordsWrite({ author: alice }); @@ -481,7 +481,7 @@ export function testRecordsQueryHandler(): void { }); it('should be able to query with `dataSize` filter (half-open range)', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write1 = await TestDataGenerator.generateRecordsWrite({ author: alice, data: TestDataGenerator.randomBytes(10) }); const write2 = await TestDataGenerator.generateRecordsWrite({ author: alice, data: TestDataGenerator.randomBytes(50) }); const write3 = await TestDataGenerator.generateRecordsWrite({ author: alice, data: TestDataGenerator.randomBytes(100) }); @@ -555,7 +555,7 @@ export function testRecordsQueryHandler(): void { }); it('should be able to range query with `dataSize` filter (open & closed range)', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write1 = await TestDataGenerator.generateRecordsWrite({ author: alice, data: TestDataGenerator.randomBytes(10) }); const write2 = await TestDataGenerator.generateRecordsWrite({ author: alice, data: TestDataGenerator.randomBytes(50) }); const write3 = await TestDataGenerator.generateRecordsWrite({ author: alice, data: TestDataGenerator.randomBytes(100) }); @@ -613,7 +613,7 @@ export function testRecordsQueryHandler(): void { const firstDayOf2021 = Time.createTimestamp({ year: 2021, month: 1, day: 1 }); const firstDayOf2022 = Time.createTimestamp({ year: 2022, month: 1, day: 1 }); const firstDayOf2023 = Time.createTimestamp({ year: 2023, month: 1, day: 1 }); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write1 = await TestDataGenerator.generateRecordsWrite({ author: alice, dateCreated: firstDayOf2021, messageTimestamp: firstDayOf2021 }); const write2 = await TestDataGenerator.generateRecordsWrite({ author: alice, dateCreated: firstDayOf2022, messageTimestamp: firstDayOf2022 }); const write3 = await TestDataGenerator.generateRecordsWrite({ author: alice, dateCreated: firstDayOf2023, messageTimestamp: firstDayOf2023 }); @@ -680,7 +680,7 @@ export function testRecordsQueryHandler(): void { const firstDayOf2021 = Time.createTimestamp({ year: 2021, month: 1, day: 1 }); const firstDayOf2022 = Time.createTimestamp({ year: 2022, month: 1, day: 1 }); const firstDayOf2023 = Time.createTimestamp({ year: 2023, month: 1, day: 1 }); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write1 = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true, dateCreated: firstDayOf2020, datePublished: firstDayOf2021, messageTimestamp: firstDayOf2020 }); @@ -798,7 +798,7 @@ export function testRecordsQueryHandler(): void { const firstDayOf2021 = Time.createTimestamp({ year: 2021, month: 1, day: 1 }); const firstDayOf2022 = Time.createTimestamp({ year: 2022, month: 1, day: 1 }); const firstDayOf2023 = Time.createTimestamp({ year: 2023, month: 1, day: 1 }); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write1 = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true, dateCreated: firstDayOf2020, datePublished: firstDayOf2021, messageTimestamp: firstDayOf2020 }); @@ -875,7 +875,7 @@ export function testRecordsQueryHandler(): void { expect(anonymousReplyIds).to.have.members([ write2.message.recordId, write3.message.recordId ]); // check for non owner range query - const bob = await DidKeyResolver.generate(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const nonOwnerRange = await TestDataGenerator.generateRecordsQuery({ author : bob, filter : { datePublished: { from: lastDayOf2021 } }, @@ -898,7 +898,7 @@ export function testRecordsQueryHandler(): void { const firstDayOf2021 = Time.createTimestamp({ year: 2021, month: 1, day: 1 }); const firstDayOf2022 = Time.createTimestamp({ year: 2022, month: 1, day: 1 }); const firstDayOf2023 = Time.createTimestamp({ year: 2023, month: 1, day: 1 }); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write1 = await TestDataGenerator.generateRecordsWrite({ author: alice, dateCreated: firstDayOf2020, messageTimestamp: firstDayOf2020 @@ -1001,7 +1001,7 @@ export function testRecordsQueryHandler(): void { const firstDayOf2021 = Time.createTimestamp({ year: 2021, month: 1, day: 1 }); const firstDayOf2022 = Time.createTimestamp({ year: 2022, month: 1, day: 1 }); const firstDayOf2023 = Time.createTimestamp({ year: 2023, month: 1, day: 1 }); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const schema = '2021And2022Schema'; const write1 = await TestDataGenerator.generateRecordsWrite({ author: alice, dateCreated: firstDayOf2021, messageTimestamp: firstDayOf2021, schema @@ -1062,7 +1062,7 @@ export function testRecordsQueryHandler(): void { it('should include `attestation` in returned records', async () => { // scenario: alice and bob attest to a message alice authored - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, attesters: [alice] }); const writeReply = await dwn.processMessage(alice.did, message, { dataStream }); @@ -1285,7 +1285,7 @@ export function testRecordsQueryHandler(): void { // setup: 3 messages with the same `dateCreated` value const dateCreated = Time.getCurrentTimestamp(); const messageTimestamp = dateCreated; - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const schema = 'aSchema'; const published = true; const write1Data = await TestDataGenerator.generateRecordsWrite({ messageTimestamp, dateCreated, author: alice, schema, published }); @@ -1333,7 +1333,7 @@ export function testRecordsQueryHandler(): void { }); it('should paginate all records in ascending order', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(12).fill({}).map(_ => TestDataGenerator.generateRecordsWrite({ author : alice, @@ -1374,7 +1374,7 @@ export function testRecordsQueryHandler(): void { }); it('should paginate all records in descending order', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(12).fill({}).map(_ => TestDataGenerator.generateRecordsWrite({ author : alice, @@ -1418,7 +1418,7 @@ export function testRecordsQueryHandler(): void { // write 2 records into Alice's DB: // 1st is unpublished // 2nd is published - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const record1Data = await TestDataGenerator.generateRecordsWrite( { author: alice, schema: 'https://schema1', published: false } ); @@ -1469,9 +1469,9 @@ export function testRecordsQueryHandler(): void { // 4th is published // 5th is published, authored by Alice and is meant for Carol as recipient; - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); const schema = 'schema1'; const record1Data = await TestDataGenerator.generateRecordsWrite( @@ -1579,8 +1579,8 @@ export function testRecordsQueryHandler(): void { }); it('should paginate correctly for fetchRecordsAsNonOwner()', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const schema = 'schema1'; // published messages bob @@ -1719,8 +1719,8 @@ export function testRecordsQueryHandler(): void { // https://github.com/TBD54566975/dwn-sdk-js/issues/170 it('#170 - should treat records with `published` explicitly set to `false` as unpublished', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const schema = 'schema1'; const unpublishedRecordsWrite = await TestDataGenerator.generateRecordsWrite( { author: alice, schema, data: Encoder.stringToBytes('1'), published: false } // explicitly setting `published` to `false` @@ -1749,8 +1749,8 @@ export function testRecordsQueryHandler(): void { }); it('should allow DWN owner to use `recipient` as a filter in queries', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const bobQueryMessageData = await TestDataGenerator.generateRecordsQuery({ author : alice, @@ -1764,8 +1764,8 @@ export function testRecordsQueryHandler(): void { it('should not fetch entries across tenants', async () => { // insert three messages into DB, two with matching schema - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const schema = 'myAwesomeSchema'; const recordsWriteMessage1Data = await TestDataGenerator.generateRecordsWrite({ author: alice, schema }); const recordsWriteMessage2Data = await TestDataGenerator.generateRecordsWrite({ author: bob, schema }); @@ -1786,7 +1786,7 @@ export function testRecordsQueryHandler(): void { }); it('should return 400 if protocol is not normalized', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // query for non-normalized protocol const recordsQuery = await TestDataGenerator.generateRecordsQuery({ @@ -1810,7 +1810,7 @@ export function testRecordsQueryHandler(): void { }); it('should return 400 if schema is not normalized', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // query for non-normalized schema const recordsQuery = await TestDataGenerator.generateRecordsQuery({ @@ -1835,7 +1835,7 @@ export function testRecordsQueryHandler(): void { it('should return 400 if published is set to false and a datePublished range is provided', async () => { const fromDatePublished = Time.getCurrentTimestamp(); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // set to true so create does not fail const recordQuery = await TestDataGenerator.generateRecordsQuery({ author : alice, @@ -1850,7 +1850,7 @@ export function testRecordsQueryHandler(): void { }); it('should return 401 for anonymous queries that filter explicitly for unpublished records', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // create an unpublished record const draftWrite = await TestDataGenerator.generateRecordsWrite({ author: alice, schema: 'post' }); @@ -1877,8 +1877,8 @@ export function testRecordsQueryHandler(): void { // only one chat message to Bob. Bob queries by protocol URI without invoking a protocolRole, // and he is able to receive the message addressed to him. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -1959,8 +1959,8 @@ export function testRecordsQueryHandler(): void { // scenario: Alice creates a thread and writes some chat messages writes a chat message. Bob invokes his // thread member role in order to query the chat messages. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -2031,8 +2031,8 @@ export function testRecordsQueryHandler(): void { it('allows $contextRole authorized queries', async () => { // scenario: Alice writes some chat messages. Bob invokes his friend role in order to query the chat messages. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -2104,8 +2104,8 @@ export function testRecordsQueryHandler(): void { // scenario: Alice writes some chat messages. Bob invokes his $globalRole to query those messages, // but his query filter does not include protocolPath. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -2160,8 +2160,8 @@ export function testRecordsQueryHandler(): void { it('does not execute $contextRole authorized queries where contextId is missing from the filter', async () => { // scenario: Alice writes some chat messages and gives Bob a role allowing him to access them. But Bob's filter // does not contain a contextId so the query fails. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -2232,8 +2232,8 @@ export function testRecordsQueryHandler(): void { // scenario: Alice creates a thread and writes some chat messages writes a chat message. Bob invokes a // $globalRole but fails because he does not actually have a role. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -2276,8 +2276,8 @@ export function testRecordsQueryHandler(): void { it('rejects $contextRole authorized queries where the query author does not have a matching $contextRole', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; diff --git a/tests/handlers/records-read.spec.ts b/tests/handlers/records-read.spec.ts index e0807e56c..a64da3e76 100644 --- a/tests/handlers/records-read.spec.ts +++ b/tests/handlers/records-read.spec.ts @@ -20,7 +20,6 @@ import chai, { expect } from 'chai'; import { ArrayUtility } from '../../src/utils/array.js'; import { authenticate } from '../../src/core/auth.js'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; import { DwnErrorCode } from '../../src/core/dwn-error.js'; import { Encryption } from '../../src/utils/encryption.js'; import { HdKey } from '../../src/utils/hd-key.js'; @@ -32,7 +31,8 @@ import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; import { TestStubGenerator } from '../utils/test-stub-generator.js'; -import { DataStream, DidResolver, Dwn, Jws, Protocols, ProtocolsConfigure, ProtocolsQuery, Records, RecordsDelete, RecordsRead , RecordsWrite, Secp256k1 } from '../../src/index.js'; +import { DataStream, Dwn, Jws, Protocols, ProtocolsConfigure, ProtocolsQuery, Records, RecordsDelete, RecordsRead , RecordsWrite, Secp256k1 } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; chai.use(chaiAsPromised); @@ -51,7 +51,7 @@ export function testRecordsReadHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -76,7 +76,7 @@ export function testRecordsReadHandler(): void { }); it('should allow tenant to RecordsRead their own record', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // insert data const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ author: alice }); @@ -102,7 +102,7 @@ export function testRecordsReadHandler(): void { }); it('should not allow non-tenant to RecordsRead their a record data', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // insert data const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice }); @@ -110,7 +110,7 @@ export function testRecordsReadHandler(): void { expect(writeReply.status.code).to.equal(202); // testing RecordsRead - const bob = await DidKeyResolver.generate(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const recordsRead = await RecordsRead.create({ filter: { @@ -124,7 +124,7 @@ export function testRecordsReadHandler(): void { }); it('should allow reading of data that is published without `authorization`', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // insert public data const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true }); @@ -147,7 +147,7 @@ export function testRecordsReadHandler(): void { }); it('should allow an authenticated user to RecordRead data that is published', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // insert public data const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true }); @@ -155,7 +155,7 @@ export function testRecordsReadHandler(): void { expect(writeReply.status.code).to.equal(202); // testing public RecordsRead - const bob = await DidKeyResolver.generate(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const recordsRead = await RecordsRead.create({ filter: { @@ -172,8 +172,8 @@ export function testRecordsReadHandler(): void { }); it('should allow a non-tenant to read RecordsRead data they have received', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice inserts data with Bob as recipient const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ @@ -201,7 +201,7 @@ export function testRecordsReadHandler(): void { }); it('should include `initialWrite` property if RecordsWrite is not initial write', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write = await TestDataGenerator.generateRecordsWrite({ author: alice, published: false }); const writeReply = await dwn.processMessage(alice.did, write.message, { dataStream: write.dataStream }); @@ -226,8 +226,8 @@ export function testRecordsReadHandler(): void { it('should allow read with allow-anyone rule', async () => { // scenario: Alice writes an image to her DWN, then Bob reads the image because he is "anyone". - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = socialMediaProtocolDefinition; @@ -309,9 +309,9 @@ export function testRecordsReadHandler(): void { // scenario: Alice sends an email to Bob, then Bob reads the email. // ImposterBob tries and fails to read the email. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const imposterBob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const imposterBob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = emailProtocolDefinition as ProtocolDefinition; @@ -364,9 +364,9 @@ export function testRecordsReadHandler(): void { it('should allow read with ancestor author rule', async () => { // scenario: Bob sends an email to Alice, then Bob reads the email. // ImposterBob tries and fails to read the email. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const imposterBob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const imposterBob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = emailProtocolDefinition as ProtocolDefinition; @@ -417,7 +417,7 @@ export function testRecordsReadHandler(): void { describe('filter based reads', () => { it('should return a filter based read if there is only a single result', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = { ...nestedProtocol }; const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({ @@ -453,7 +453,7 @@ export function testRecordsReadHandler(): void { }); it('should throw if requested filter has more than a single result', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = { ...nestedProtocol }; const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({ @@ -506,8 +506,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice writes a chat message writes a chat message. Bob invokes his // friend role in order to read the chat message. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -557,8 +557,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice writes a chat message writes a chat message. Bob tries to invoke the 'chat' role, // but 'chat' is not a role. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -597,8 +597,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice writes a chat message writes a chat message. Bob tries to invoke a role, // but he has not been given one. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -637,8 +637,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. Alice writes a chat message. // Bob invokes the record to read in the chat message. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -723,8 +723,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice creates a thread and adds Bob as a participant. ALice creates another thread. Bob tries and fails to invoke his // contextRole to write a chat in the second thread - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -798,8 +798,8 @@ export function testRecordsReadHandler(): void { it('rejects with 401 an external party attempts to RecordReads if grant has different DWN method scope', async () => { // scenario: Alice grants Bob access to RecordsWrite, then Bob tries to invoke the grant with RecordsRead - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice writes a record which Bob will later try to read const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({ @@ -839,8 +839,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice gives Bob a grant allowing him to read any record in her DWN. // Bob invokes that grant to read a record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice writes a record to her DWN const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ @@ -881,8 +881,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice writes a protocol record. Alice gives Bob a grant to read all records in her DWN // Bob invokes that grant to read the protocol record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -945,8 +945,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice writes a protocol record. Alice gives Bob a grant to read all records in the protocol // Bob invokes that grant to read the protocol record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -1009,8 +1009,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice writes a protocol record. Alice gives Bob a grant to read a different protocol // Bob invokes that grant to read the protocol record, but fails. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -1063,8 +1063,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice writes a protocol record. Alice gives Bob a grant to read a records of a certain schema. // Bob invokes that grant to read the protocol record, but fails. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -1116,8 +1116,8 @@ export function testRecordsReadHandler(): void { it('allows reads of records in the contextId specified in the grant', async () => { // scenario: Alice grants Bob access to RecordsRead records with a specific contextId. // Bob uses it to read a record in that context. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -1169,8 +1169,8 @@ export function testRecordsReadHandler(): void { it('rejects reads of records in a different contextId than is specified in the grant', async () => { // scenario: Alice grants Bob access to RecordsRead records with a specific contextId. // Bob tries and fails to invoke the grant in order to read a record outside of the context. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -1223,8 +1223,8 @@ export function testRecordsReadHandler(): void { it('allows reads of records in the protocolPath specified in the grant', async () => { // scenario: Alice grants Bob access to RecordsRead records with a specific protocolPath. // Bob uses it to read a record in that protocolPath. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -1276,8 +1276,8 @@ export function testRecordsReadHandler(): void { it('rejects reads of records in a different protocolPath than is specified in the grant', async () => { // scenario: Alice grants Bob access to RecordsRead records with a specific protocolPath. // Bob tries and fails to invoke the grant in order to read a record outside of the protocolPath. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -1333,8 +1333,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice gives Bob a grant allowing him to read records with matching schema in her DWN. // Bob invokes that grant to read a record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice writes a record to her DWN const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ @@ -1375,8 +1375,8 @@ export function testRecordsReadHandler(): void { // scenario: Alice gives Bob a grant allowing him to read records with matching schema in her DWN. // Bob invokes that grant to read a different record and is rejected. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice writes a record to her DWN const recordSchema = 'record-schema'; @@ -1419,7 +1419,7 @@ export function testRecordsReadHandler(): void { }); it('should return 404 RecordRead if data does not exist', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const recordsRead = await RecordsRead.create({ filter: { @@ -1433,7 +1433,7 @@ export function testRecordsReadHandler(): void { }); it('should return 404 RecordRead if data has been deleted', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // insert public data const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true }); @@ -1472,7 +1472,7 @@ export function testRecordsReadHandler(): void { }); it('should return 404 underlying data store cannot locate the data when data is above threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); sinon.stub(dataStore, 'get').resolves(undefined); @@ -1498,7 +1498,7 @@ export function testRecordsReadHandler(): void { describe('data from encodedData', () => { it('should not get data from DataStore if encodedData exists', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); //since the data is at the threshold it will be returned from the messageStore in the `encodedData` field. const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ @@ -1529,7 +1529,7 @@ export function testRecordsReadHandler(): void { }); it('should get data from DataStore if encodedData does not exist', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); //since the data is over the threshold it will not be returned from the messageStore in the `encodedData` field. const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ @@ -2033,7 +2033,7 @@ export function testRecordsReadHandler(): void { }); it('should return 401 if signature check fails', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const recordsRead = await RecordsRead.create({ filter: { recordId: 'any-id', @@ -2054,7 +2054,7 @@ export function testRecordsReadHandler(): void { }); it('should return 400 if fail parsing the message', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const recordsRead = await RecordsRead.create({ filter: { recordId: 'any-id', diff --git a/tests/handlers/records-subscribe.spec.ts b/tests/handlers/records-subscribe.spec.ts index a820a65d1..3f873bcdd 100644 --- a/tests/handlers/records-subscribe.spec.ts +++ b/tests/handlers/records-subscribe.spec.ts @@ -10,7 +10,6 @@ import chai, { expect } from 'chai'; import friendRoleProtocolDefinition from '../vectors/protocol-definitions/friend-role.json' assert { type: 'json' }; import threadRoleProtocolDefinition from '../vectors/protocol-definitions/thread-role.json' assert { type: 'json' }; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; import { Jws } from '../../src/utils/jws.js'; import { Message } from '../../src/core/message.js'; import { RecordsSubscribe } from '../../src/interfaces/records-subscribe.js'; @@ -20,7 +19,8 @@ import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; import { TestStubGenerator } from '../utils/test-stub-generator.js'; -import { DidResolver, Dwn, Time } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; +import { Dwn, Time } from '../../src/index.js'; import { DwnErrorCode, DwnInterfaceName, DwnMethodName } from '../../src/index.js'; chai.use(chaiAsPromised); @@ -37,7 +37,7 @@ export function testRecordsSubscribeHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -71,7 +71,7 @@ export function testRecordsSubscribeHandler(): void { await dwn.close(); // close the original dwn instance dwn = await Dwn.create({ didResolver, messageStore, dataStore, eventLog }); // leave out eventStream - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // attempt to subscribe const { message } = await TestDataGenerator.generateRecordsSubscribe({ author: alice, @@ -93,7 +93,7 @@ export function testRecordsSubscribeHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -118,7 +118,7 @@ export function testRecordsSubscribeHandler(): void { }); it('should return a subscription object', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const recordsSubscribe = await TestDataGenerator.generateRecordsSubscribe({ author : alice, @@ -132,7 +132,7 @@ export function testRecordsSubscribeHandler(): void { }); it('should return 400 if protocol is not normalized', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // subscribe for non-normalized protocol const recordsSubscribe = await TestDataGenerator.generateRecordsSubscribe({ @@ -156,7 +156,7 @@ export function testRecordsSubscribeHandler(): void { }); it('should return 400 if schema is not normalized', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // subscribe for non-normalized schema const recordsSubscribe = await TestDataGenerator.generateRecordsSubscribe({ @@ -181,7 +181,7 @@ export function testRecordsSubscribeHandler(): void { it('should return 400 if published is set to false and a datePublished range is provided', async () => { const fromDatePublished = Time.getCurrentTimestamp(); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // set to true so create does not fail const recordSubscribe = await TestDataGenerator.generateRecordsSubscribe({ author : alice, @@ -196,7 +196,7 @@ export function testRecordsSubscribeHandler(): void { }); it('should return 401 for anonymous subscriptions that filter explicitly for unpublished records', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // create an unpublished record const draftWrite = await TestDataGenerator.generateRecordsWrite({ author: alice, schema: 'post' }); @@ -257,8 +257,8 @@ export function testRecordsSubscribeHandler(): void { // only one chat message to Bob. Bob subscribes by protocol URI without invoking a protocolRole, // and he is able to receive the message addressed to him. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -333,8 +333,8 @@ export function testRecordsSubscribeHandler(): void { // scenario: Alice creates a thread and writes some chat messages writes a chat message. Bob invokes his // thread member role in order to subscribe to the chat messages. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -428,8 +428,8 @@ export function testRecordsSubscribeHandler(): void { // scenario: Alice writes some chat messages. // Bob, having a thread/participant record, can subscribe to the chat. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -537,8 +537,8 @@ export function testRecordsSubscribeHandler(): void { // scenario: Alice writes some chat messages. Bob invokes his $globalRole to subscribe those messages, // but his subscription filter does not include protocolPath. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -578,8 +578,8 @@ export function testRecordsSubscribeHandler(): void { it('does not execute $contextRole authorized subscriptions where contextId is missing from the filter', async () => { // scenario: Alice gives Bob a role allowing him to access a particular chat thread. // But Bob's filter does not contain a contextId so the subscription fails. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -633,8 +633,8 @@ export function testRecordsSubscribeHandler(): void { // scenario: Alice installs a chat protocol. // Bob invokes a $globalRole within that protocol to subscribe but fails because he does not actually have a role. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -662,8 +662,8 @@ export function testRecordsSubscribeHandler(): void { it('rejects protocol authorized subscriptions where the subscription author does not have a matching $contextRole', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; diff --git a/tests/handlers/records-write.spec.ts b/tests/handlers/records-write.spec.ts index 4f276fea6..69378816e 100644 --- a/tests/handlers/records-write.spec.ts +++ b/tests/handlers/records-write.spec.ts @@ -25,8 +25,8 @@ import { ArrayUtility } from '../../src/utils/array.js'; import { base64url } from 'multiformats/bases/base64'; import { Cid } from '../../src/utils/cid.js'; import { DataStream } from '../../src/utils/data-stream.js'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; -import { DidResolver } from '../../src/did/did-resolver.js'; +import { DidKeyMethod } from '@web5/dids'; +import { DidResolver } from '@web5/dids'; import { Dwn } from '../../src/dwn.js'; import { DwnErrorCode } from '../../src/core/dwn-error.js'; import { Encoder } from '../../src/utils/encoder.js'; @@ -63,7 +63,7 @@ export function testRecordsWriteHandler(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -89,7 +89,7 @@ export function testRecordsWriteHandler(): void { it('should only be able to overwrite existing record if new record has a later `messageTimestamp` value', async () => { // write a message into DB - const author = await DidKeyResolver.generate(); + const author = await TestDataGenerator.generateDidKeyPersona(); const data1 = new TextEncoder().encode('data1'); const recordsWriteMessageData = await TestDataGenerator.generateRecordsWrite({ author, data: data1 }); @@ -323,7 +323,7 @@ export function testRecordsWriteHandler(): void { //scenario: you have an initial write without the data and a subsequent write with data to be able to write. // the DWN should accept an initial write without data, however prevent the user from querying for it until it's updated. - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { recordsWrite } = await TestDataGenerator.generateRecordsWrite({ author: alice }); @@ -365,7 +365,7 @@ export function testRecordsWriteHandler(): void { //scenario: you have an initial write without the data and a subsequent write with data to be able to write. // the DWN should accept an initial write without data, however prevent the user from querying for it until it's updated. - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // write a record into the dwn const { recordsWrite, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ author: alice }); @@ -405,7 +405,7 @@ export function testRecordsWriteHandler(): void { }); it('should throw if associate returns undefined', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // write a record into the dwn const { recordsWrite } = await TestDataGenerator.generateRecordsWrite({ @@ -434,8 +434,8 @@ export function testRecordsWriteHandler(): void { describe('owner signature tests', () => { it('should use `ownerSignature` for authorization when it is given - flat-space', async () => { // scenario: Alice fetch a message authored by Bob from Bob's DWN and retains (writes) it in her DWN - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Bob writes a message to his DWN const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ author: bob, published: true }); @@ -476,8 +476,8 @@ export function testRecordsWriteHandler(): void { it('should use `ownerSignature` for authorization when it is given - protocol-space', async () => { // scenario: Alice and Bob both have the same protocol which does NOT allow external entities to write, // but Alice can store a message authored by Bob as a owner in her own DWN - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -525,9 +525,9 @@ export function testRecordsWriteHandler(): void { it('should throw if `ownerSignature` in `authorization` is mismatching with the tenant - flat-space', async () => { // scenario: Carol attempts to store a message with Alice being the owner, and should fail - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // Bob creates a message, we skip writing to bob's DWN because that's orthogonal to this test const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: bob, published: true }); @@ -544,9 +544,9 @@ export function testRecordsWriteHandler(): void { it('should throw if `ownerSignature` in `authorization` is mismatching with the tenant - protocol-space', async () => { // scenario: Alice, Bob, and Carol all have the same protocol which does NOT allow external entities to write, // scenario: Carol attempts to store a message with Alice being the owner, and should fail - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -576,8 +576,8 @@ export function testRecordsWriteHandler(): void { it('should throw if `ownerSignature` fails verification', async () => { // scenario: Malicious Bob attempts to retain an externally authored message in Alice's DWN by providing an invalid `ownerSignature` - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Bob creates a message, we skip writing to bob's DWN because that's orthogonal to this test const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: bob, published: true }); @@ -664,7 +664,7 @@ export function testRecordsWriteHandler(): void { describe('should return 400 if actual data size mismatches with `dataSize` in descriptor', () => { it('with dataStream and `dataSize` larger than encodedData threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author : alice, data : TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1) @@ -692,7 +692,7 @@ export function testRecordsWriteHandler(): void { }); it('with only `dataSize` larger than encodedData threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author : alice, data : TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded) @@ -720,7 +720,7 @@ export function testRecordsWriteHandler(): void { }); it('with only dataStream larger than encodedData threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author : alice, data : TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1) @@ -748,7 +748,7 @@ export function testRecordsWriteHandler(): void { }); it('with both `dataSize` and dataStream below than encodedData threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice }); @@ -840,7 +840,7 @@ export function testRecordsWriteHandler(): void { }); it('should return 400 for data CID mismatch with both dataStream and `dataSize` larger than encodedData threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite({ author : alice, data : TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1) @@ -854,7 +854,7 @@ export function testRecordsWriteHandler(): void { }); it('should return 400 for data CID mismatch with `dataSize` larger than encodedData threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite({ author : alice, data : TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1) @@ -868,7 +868,7 @@ export function testRecordsWriteHandler(): void { }); it('should return 400 for data CID mismatch with dataStream larger than encodedData threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite({ author : alice, data : TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded) @@ -882,7 +882,7 @@ export function testRecordsWriteHandler(): void { }); it('should return 400 for data CID mismatch with both dataStream and `dataSize` below than encodedData threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite({ author : alice, data : TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded) @@ -896,7 +896,7 @@ export function testRecordsWriteHandler(): void { }); it('#359 - should not allow access of data by referencing a different`dataCid` in "modify" `RecordsWrite` with large data', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // alice writes a record const dataString = TestDataGenerator.randomString(DwnConstant.maxDataSizeAllowedToBeEncoded + 1); @@ -953,7 +953,7 @@ export function testRecordsWriteHandler(): void { }); it('#359 - should not allow access of data by referencing a different`dataCid` in "modify" `RecordsWrite`', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // alice writes a record const dataString = TestDataGenerator.randomString(DwnConstant.maxDataSizeAllowedToBeEncoded); @@ -1241,8 +1241,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice creates a record on her DWN, and Bob (anyone) is able to update it. Bob is not able to // create a record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = anyoneCollaborateProtocolDefinition; @@ -1365,8 +1365,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice creates a post with Bob as recipient. Alice adds a tag to the post. Bob is able to update // the tag because he is recipient of the post. Bob is not able to create a new tag. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = recipientCanProtocol; @@ -1555,8 +1555,8 @@ export function testRecordsWriteHandler(): void { // scenario: Bob authors a post on Alice's DWN. Alice adds a comment to the post. Bob is able to update the comment, // since he authored the post. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = authorCanProtocolDefinition; @@ -1620,8 +1620,8 @@ export function testRecordsWriteHandler(): void { it('allows a $globalRole record with unique recipient to be created and updated', async () => { // scenario: Alice adds Bob to the 'friend' role. Then she updates the 'friend' record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -1656,7 +1656,7 @@ export function testRecordsWriteHandler(): void { it('rejects writes to a $globalRole if recipient is undefined', async () => { // scenario: Alice writes a global role record with no recipient and it is rejected - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -1683,8 +1683,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice adds Bob to the 'friend' role. Then she tries and fails to write another separate record // adding Bob as a 'friend' again. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -1723,8 +1723,8 @@ export function testRecordsWriteHandler(): void { it('allows a new $globalRole record to be created for the same recipient if their old one was deleted', async () => { // scenario: Alice adds Bob to the 'friend' role, then deletes the role. Alice writes a new record adding Bob as a 'friend' again. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -1772,8 +1772,8 @@ export function testRecordsWriteHandler(): void { it('allows a $contextRole record with recipient unique to the context to be created and updated', async () => { // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. Then she updates Bob's role record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -1820,8 +1820,8 @@ export function testRecordsWriteHandler(): void { it('allows a $contextRole record to be created even if there is a $contextRole in a different context', async () => { // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. Alice repeats the steps with a new thread. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -1882,8 +1882,8 @@ export function testRecordsWriteHandler(): void { it('rejects writes to a $contextRole record if there already exists one in the same context', async () => { // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. She adds Bob to the role second time and fails - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -1935,8 +1935,8 @@ export function testRecordsWriteHandler(): void { it('allows a new $contextRole record to be created for the same recipient in the same context if their old one was deleted', async () => { // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. She deletes the role and then adds a new one. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -1998,8 +1998,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a friend role. Bob invokes his // friend role in order to write a chat message - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -2038,8 +2038,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a admin role. Bob invokes his // admin role in order to update a chat message that Alice wrote - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -2085,8 +2085,8 @@ export function testRecordsWriteHandler(): void { it('rejects role-authorized writes if the protocolRole is not a valid protocol path to a role record', async () => { // scenario: Bob tries to invoke the 'chat' role to write to Alice's DWN, but 'chat' is not a role. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -2125,8 +2125,8 @@ export function testRecordsWriteHandler(): void { it('rejects global-authorized writes if there is no active role for the recipient', async () => { // scenario: Bob tries to invoke a role to write, but he has not been given one. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = friendRoleProtocolDefinition; @@ -2154,8 +2154,8 @@ export function testRecordsWriteHandler(): void { it('uses a contextRole to authorize a write', async () => { // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. Bob invokes the record to write in the thread - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -2206,8 +2206,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice creates a thread and adds Bob to the 'thread/admin' role. // Bob invokes the record to write in the thread - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -2267,8 +2267,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice creates a thread and adds Bob as a participant. ALice creates another thread. Bob tries and fails to invoke his // contextRole to write a chat in the second thread - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -2329,8 +2329,8 @@ export function testRecordsWriteHandler(): void { it('rejects attempts to invoke an invalid path as a protocolRole', async () => { // scenario: Bob tries to invoke 'notARealPath' as a protocolRole and fails - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = threadRoleProtocolDefinition; @@ -2621,7 +2621,7 @@ export function testRecordsWriteHandler(): void { }); it('should fail authorization if protocol definition cannot be found for a protocol-based RecordsWrite', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocol = 'nonExistentProtocol'; const data = Encoder.stringToBytes('any data'); const credentialApplication = await TestDataGenerator.generateRecordsWrite({ @@ -2638,7 +2638,7 @@ export function testRecordsWriteHandler(): void { }); it('should fail authorization if record schema is incorrect for a protocol-based RecordsWrite', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = credentialIssuanceProtocolDefinition; const protocol = protocolDefinition.protocol; @@ -2666,7 +2666,7 @@ export function testRecordsWriteHandler(): void { }); it('should fail authorization if given `protocolPath` contains an invalid record type', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = credentialIssuanceProtocolDefinition; const protocol = protocolDefinition.protocol; @@ -2694,7 +2694,7 @@ export function testRecordsWriteHandler(): void { }); it('should fail authorization if given `protocolPath` is mismatching with actual path', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = credentialIssuanceProtocolDefinition; const protocol = protocolDefinition.protocol; @@ -2722,7 +2722,7 @@ export function testRecordsWriteHandler(): void { }); it('should fail authorization if given `dataFormat` is mismatching with the dataFormats in protocol definition', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = socialMediaProtocolDefinition; const protocol = protocolDefinition.protocol; @@ -2767,7 +2767,7 @@ export function testRecordsWriteHandler(): void { it('should fail authorization if record schema is not allowed at the hierarchical level attempted for the RecordsWrite', async () => { // scenario: Attempt writing of records at 3 levels in the hierarchy to cover all possible cases of missing rule sets - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = credentialIssuanceProtocolDefinition; const protocol = protocolDefinition.protocol; @@ -2859,7 +2859,7 @@ export function testRecordsWriteHandler(): void { }); it('should only allow DWN owner to write if record does not have an action rule defined', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // write a protocol definition without an explicit action rule const protocolDefinition = privateProtocol; @@ -2888,7 +2888,7 @@ export function testRecordsWriteHandler(): void { expect(reply.status.code).to.equal(202); // test that Bob is not allowed to write to Alice's DWN - const bob = await DidKeyResolver.generate(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const bobWriteMessageData = await TestDataGenerator.generateRecordsWrite({ author : bob, recipient : alice.did, @@ -2908,8 +2908,8 @@ export function testRecordsWriteHandler(): void { // simulate a DEX protocol with at least 3 layers of message exchange: ask -> offer -> fulfillment // make sure recipient of offer can send fulfillment - const alice = await DidKeyResolver.generate(); - const pfi = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const pfi = await TestDataGenerator.generateDidKeyPersona(); // write a DEX protocol definition const protocolDefinition = dexProtocolDefinition; @@ -2986,8 +2986,8 @@ export function testRecordsWriteHandler(): void { // 2. Alice sends an ask to a PFI // 3. Alice sends a fulfillment to an non-existent offer to the PFI - const alice = await DidKeyResolver.generate(); - const pfi = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const pfi = await TestDataGenerator.generateDidKeyPersona(); // write a DEX protocol definition const protocolDefinition = dexProtocolDefinition; @@ -3089,7 +3089,7 @@ export function testRecordsWriteHandler(): void { }); it('should return 400 if protocol is not normalized', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = emailProtocolDefinition; @@ -3129,8 +3129,8 @@ export function testRecordsWriteHandler(): void { }); it('#359 - should not allow access of data by referencing `dataCid` in protocol authorized `RecordsWrite`', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // alice writes a private record const dataString = TestDataGenerator.randomString(DwnConstant.maxDataSizeAllowedToBeEncoded); @@ -3221,8 +3221,8 @@ export function testRecordsWriteHandler(): void { }); it('#359 - should not allow access of data by referencing `dataCid` in protocol authorized `RecordsWrite` with large data', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // alice writes a private record const dataString = TestDataGenerator.randomString(DwnConstant.maxDataSizeAllowedToBeEncoded + 1); @@ -3317,7 +3317,7 @@ export function testRecordsWriteHandler(): void { // write a protocol definition that has a record type without schema const protocolDefinition = anyoneCollaborateProtocolDefinition as ProtocolDefinition; - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({ author: alice, @@ -3376,8 +3376,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant with unrestricted RecordsWrite scope. // Bob is able to write both a protocol and a non-protocol record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -3430,8 +3430,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant to read all records in the protocol // Bob invokes that grant to write a protocol record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -3473,8 +3473,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant to write to a protocol. Bob tries and fails to // invoke the grant to write to another protocol. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -3517,8 +3517,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice issues Bob a grant allowing him to write some non-protocol records. // Bob invokes the grant to write a protocol record - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -3561,8 +3561,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant to write to a specific contextId. // Bob invokes that grant to write a record in the allowed contextId. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = emailProtocolDefinition as ProtocolDefinition; @@ -3622,8 +3622,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant to write to a specific contextId. Bob tries and fails to // invoke the grant to write to another contextId. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = emailProtocolDefinition as ProtocolDefinition; @@ -3684,8 +3684,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant to write to a specific protocolPath. // Bob invokes that grant to write a record in the allowed protocolPath. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -3728,8 +3728,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant to write to a specific protocolPath. Bob tries and fails to // invoke the grant to write to another protocolPath. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const protocolDefinition = minimalProtocolDefinition; @@ -3775,8 +3775,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice issues Bob a grant allowing him to write to flat records of a given schema. // Bob invokes that grant to write a record with matching schema - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice gives Bob a PermissionsGrant for a certain schema const schema = 'http://example.com/schema'; @@ -3808,8 +3808,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice issues a grant for Bob to write flat records of a certain schema. // Bob tries and fails to write records of a different schema - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice gives Bob a PermissionsGrant for a certain schema @@ -3844,8 +3844,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant with condition `published` === required. // Bob is able to write a public record but not able to write an unpublished record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice creates a grant for Bob with `published` === required const permissionsGrant = await TestDataGenerator.generatePermissionsGrant({ @@ -3895,8 +3895,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant with condition `published` === prohibited. // Bob is able to write a unpublished record but not able to write a public record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice creates a grant for Bob with `published` === prohibited const permissionsGrant = await TestDataGenerator.generatePermissionsGrant({ @@ -3946,8 +3946,8 @@ export function testRecordsWriteHandler(): void { // scenario: Alice gives Bob a grant without condition `published`. // Bob is able to write both an unpublished record and a published record. - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // Alice creates a grant for Bob with `published` === prohibited const permissionsGrant = await TestDataGenerator.generatePermissionsGrant({ @@ -4000,7 +4000,7 @@ export function testRecordsWriteHandler(): void { // Pruned RecordsWrite // Data large enough to use the DataStore - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const data = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1); const prunedRecordsWrite = await TestDataGenerator.generateRecordsWrite({ author : alice, @@ -4028,7 +4028,7 @@ export function testRecordsWriteHandler(): void { // Pruned RecordsWrite // Data that would be encoded within the message - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const data = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded); const prunedRecordsWrite = await TestDataGenerator.generateRecordsWrite({ author : alice, @@ -4052,8 +4052,8 @@ export function testRecordsWriteHandler(): void { describe('reference counting tests', () => { it('should not allow referencing data across tenants', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const data = Encoder.stringToBytes('test'); const dataCid = await Cid.computeDagPbCidFromBytes(data); const encodedData = Encoder.bytesToBase64Url(data); @@ -4106,7 +4106,7 @@ export function testRecordsWriteHandler(): void { describe('encodedData threshold', async () => { it('should call cloneAndAddEncodedData and not validateDataStoreIntegrity if dataSize is less than or equal to the threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes }); const processEncoded = sinon.spy(RecordsWriteHandler.prototype as any, 'cloneAndAddEncodedData'); @@ -4119,7 +4119,7 @@ export function testRecordsWriteHandler(): void { }); it('should call validateDataStoreIntegrity and not cloneAndAddEncodedData if dataSize is greater than the threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes }); const processEncoded = sinon.spy(RecordsWriteHandler.prototype as any, 'cloneAndAddEncodedData'); @@ -4132,7 +4132,7 @@ export function testRecordsWriteHandler(): void { }); it('should have encodedData field if dataSize is less than or equal to the threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes }); @@ -4145,7 +4145,7 @@ export function testRecordsWriteHandler(): void { }); it('should not have encodedData field if dataSize greater than threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes }); @@ -4158,7 +4158,7 @@ export function testRecordsWriteHandler(): void { }); it('should retain original RecordsWrite message but without the encodedData if data is under threshold', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes }); @@ -4306,8 +4306,8 @@ export function testRecordsWriteHandler(): void { }); it('should fail validation with 400 if more than 1 attester is given ', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, attesters: [alice, bob] }); const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStore, dataStore, eventLog, eventStream); @@ -4318,7 +4318,7 @@ export function testRecordsWriteHandler(): void { }); it('should fail validation with 400 if the `attestation` does not include the correct `descriptorCid`', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, attesters: [alice] }); // create another write and use its `attestation` value instead, that `attestation` will point to an entirely different `descriptorCid` @@ -4333,11 +4333,11 @@ export function testRecordsWriteHandler(): void { }); it('should fail validation with 400 if expected CID of `attestation` mismatches the `attestationCid` in `authorization`', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, attesters: [alice] }); // replace valid attestation (the one signed by `authorization` with another attestation to the same message (descriptorCid) - const bob = await DidKeyResolver.generate(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const descriptorCid = await Cid.computeCid(message.descriptor); const attestationNotReferencedByAuthorization = await RecordsWrite['createAttestation'](descriptorCid, Jws.createSigners([bob])); message.attestation = attestationNotReferencedByAuthorization; diff --git a/tests/interfaces/events-subscribe.spec.ts b/tests/interfaces/events-subscribe.spec.ts index 09a531012..3365dcba3 100644 --- a/tests/interfaces/events-subscribe.spec.ts +++ b/tests/interfaces/events-subscribe.spec.ts @@ -1,13 +1,13 @@ import { authorizeOwner } from '../../src/core/auth.js'; import { EventsSubscribe } from '../../src/interfaces/events-subscribe.js'; -import { DidKeyResolver, DwnInterfaceName, DwnMethodName, Jws, Time } from '../../src/index.js'; +import { DwnInterfaceName, DwnMethodName, Jws, TestDataGenerator, Time } from '../../src/index.js'; import { expect } from 'chai'; describe('EventsSubscribe', () => { describe('create()', () => { it('should be able to create and authorize EventsSubscribe', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const timestamp = Time.getCurrentTimestamp(); const eventsSubscribe = await EventsSubscribe.create({ signer : Jws.createSigner(alice), diff --git a/tests/interfaces/permissions-grant.spec.ts b/tests/interfaces/permissions-grant.spec.ts index 9c6703719..339f2529c 100644 --- a/tests/interfaces/permissions-grant.spec.ts +++ b/tests/interfaces/permissions-grant.spec.ts @@ -10,7 +10,7 @@ import { PermissionsGrant } from '../../src/interfaces/permissions-grant.js'; import { Secp256k1 } from '../../src/utils/secp256k1.js'; import { TestDataGenerator } from '../utils/test-data-generator.js'; import { Time } from '../../src/utils/time.js'; -import { DidKeyResolver, DwnErrorCode, DwnInterfaceName, DwnMethodName, Jws, PrivateKeySigner } from '../../src/index.js'; +import { DwnErrorCode, DwnInterfaceName, DwnMethodName, Jws, PrivateKeySigner } from '../../src/index.js'; describe('PermissionsGrant', () => { describe('create()', async () => { @@ -185,9 +185,9 @@ describe('PermissionsGrant', () => { }); it('should create a PermissionsGrant from a PermissionsRequest and overrides', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); const { privateJwk } = await Secp256k1.generateKeyPair(); const signer = new PrivateKeySigner({ privateJwk, keyId: `${alice.did}#key1` }); diff --git a/tests/interfaces/records-write.spec.ts b/tests/interfaces/records-write.spec.ts index 18de8cc87..9b3a21938 100644 --- a/tests/interfaces/records-write.spec.ts +++ b/tests/interfaces/records-write.spec.ts @@ -12,7 +12,7 @@ import { stubInterface } from 'ts-sinon'; import { TestDataGenerator } from '../utils/test-data-generator.js'; import { Time } from '../../src/utils/time.js'; -import { DidKeyResolver, DwnInterfaceName, DwnMethodName, Encoder, Jws, KeyDerivationScheme, PermissionsGrant } from '../../src/index.js'; +import { DwnInterfaceName, DwnMethodName, Encoder, Jws, KeyDerivationScheme, PermissionsGrant } from '../../src/index.js'; chai.use(chaiAsPromised); @@ -402,7 +402,7 @@ describe('RecordsWrite', () => { expect(recordsWrite.author).to.not.exist; expect(recordsWrite.signaturePayload).to.not.exist; - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); await expect(recordsWrite.signAsOwner(Jws.createSigner(alice))).to.rejectedWith(DwnErrorCode.RecordsWriteSignAsOwnerUnknownAuthor); expect(recordsWrite.owner).to.be.undefined; diff --git a/tests/jose/jws/general.spec.ts b/tests/jose/jws/general.spec.ts index 9c397e33b..ca06232f6 100644 --- a/tests/jose/jws/general.spec.ts +++ b/tests/jose/jws/general.spec.ts @@ -1,7 +1,7 @@ import chaiAsPromised from 'chai-as-promised'; import chai, { expect } from 'chai'; -import { DidResolver } from '../../../src/did/did-resolver.js'; +import { DidResolver } from '@web5/dids'; import { GeneralJwsBuilder } from '../../../src/jose/jws/general/builder.js'; import { GeneralJwsVerifier } from '../../../src/jose/jws/general/verifier.js'; import { Jws } from '../../../src/utils/jws.js'; @@ -43,7 +43,7 @@ describe('General JWS Sign/Verify', () => { const resolverStub = sinon.createStubInstance(DidResolver, { // @ts-ignore - resolve: sinon.stub().withArgs('did:jank:alice').resolves(mockResolutionResult) + resolve: sinon.stub().withArgs('did:jank:alice').resolves(mockResolutionResult), }); const verificationResult = await GeneralJwsVerifier.verifySignatures(jws, resolverStub); diff --git a/tests/scenarios/delegated-grant.spec.ts b/tests/scenarios/delegated-grant.spec.ts index e2104fc14..1aa49169c 100644 --- a/tests/scenarios/delegated-grant.spec.ts +++ b/tests/scenarios/delegated-grant.spec.ts @@ -10,8 +10,6 @@ import chai, { expect } from 'chai'; import { base64url } from 'multiformats/bases/base64'; import { DataStream } from '../../src/utils/data-stream.js'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; -import { DidResolver } from '../../src/did/did-resolver.js'; import { Dwn } from '../../src/dwn.js'; import { DwnErrorCode } from '../../src/core/dwn-error.js'; import { Jws } from '../../src/utils/jws.js'; @@ -21,6 +19,7 @@ import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; import { Time } from '../../src/utils/time.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; import { DwnInterfaceName, DwnMethodName, PermissionsGrant, RecordsDelete, RecordsQuery, RecordsRead, RecordsSubscribe } from '../../src/index.js'; chai.use(chaiAsPromised); @@ -37,7 +36,7 @@ export function testDelegatedGrantScenarios(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -67,11 +66,11 @@ export function testDelegatedGrantScenarios(): void { // 2. Device X and Y can both use their grants to write a message to Bob's DWN as Alice // 3. Messages written by device X and Y should be considered to have been authored by Alice // 4. Carol should not be able to write a message as Alice using Device X's delegated grant - const alice = await DidKeyResolver.generate(); - const deviceX = await DidKeyResolver.generate(); - const deviceY = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const deviceX = await TestDataGenerator.generateDidKeyPersona(); + const deviceY = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // Bob has the email protocol installed const protocolDefinition = emailProtocolDefinition; @@ -189,10 +188,10 @@ export function testDelegatedGrantScenarios(): void { // 2. Bob starts a chat thread with Alice on his DWN // 3. device X should be able to read the chat thread // 4. Carol should not be able to read the chat thread using device X's delegated grant - const alice = await DidKeyResolver.generate(); - const deviceX = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const deviceX = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // Bob has the chat protocol installed const protocolDefinition = threadRoleProtocolDefinition; @@ -356,10 +355,10 @@ export function testDelegatedGrantScenarios(): void { // 5. Bob writes a chat to the thread. // 6. The subscription should have received the chat. - const alice = await DidKeyResolver.generate(); - const deviceX = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const deviceX = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // Bob has the chat protocol installed const protocolDefinition = threadRoleProtocolDefinition; @@ -473,10 +472,10 @@ export function testDelegatedGrantScenarios(): void { // 3. Alice creates a delegated grant for Device X to act as her // 4. Carol should not be able to delete a chat message as Alice using Device X's delegated grant // 5. Device X should be able to delete a chat message as Alice - const alice = await DidKeyResolver.generate(); - const deviceX = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const deviceX = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // Bob has the chat protocol installed const protocolDefinition = threadRoleProtocolDefinition; @@ -601,9 +600,9 @@ export function testDelegatedGrantScenarios(): void { // 2. Bob has email protocol configured for his DWN that allows anyone to write an email to him // 3. Device X attempts to use the delegated grant to write an email to Bob as Alice // 4. Bob's DWN should reject Device X's message - const alice = await DidKeyResolver.generate(); - const deviceX = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const deviceX = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); // 1. Alice creates a delegated grant for device X to act as her for a protocol that is NOT email protocol const scope: PermissionScope = { @@ -652,14 +651,15 @@ export function testDelegatedGrantScenarios(): void { it('should fail if delegated grant has a mismatching protocol scope - query, subscribe & read', async () => { // scenario: - // 1. Alice creates a delegated grant for device X to act as her for a protocol that is NOT chat protocol - // 2. Bob starts a chat thread with Alice on his DWN - // 3. Device X attempts to use the delegated grant to read, query and subscribe to the chat thread. - // 4. Bob's DWN should reject Device X's read query or subscribe attempts + // 1. Bob starts a chat thread with Alice on his DWN + // 2. Alice creates a delegated grant for device X to act as her for a protocol that is NOT chat protocol + // 3. Device X attempts to use the delegated grant to read, query and subscribe to the chat thread and gets rejected by Bob's DWN + + const alice = await TestDataGenerator.generateDidKeyPersona(); + const deviceX = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); - const alice = await DidKeyResolver.generate(); - const deviceX = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + // 1. Bob starts a chat thread with Alice on his DWN // Bob has the chat protocol installed const protocolDefinition = threadRoleProtocolDefinition; @@ -693,36 +693,6 @@ export function testDelegatedGrantScenarios(): void { const participantRoleReply = await dwn.processMessage(bob.did, participantRoleRecord.message, { dataStream: participantRoleRecord.dataStream }); expect(participantRoleReply.status.code).to.equal(202); - // Alice creates a delegated subscribe grant for device X to act as Alice but not for chat protocol - const subscribeGrantForDeviceX = await PermissionsGrant.create({ - delegated : true, // this is a delegated grant - dateExpires : Time.createOffsetTimestamp({ seconds: 100 }), - grantedBy : alice.did, - grantedTo : deviceX.did, - grantedFor : alice.did, - scope : { - interface : DwnInterfaceName.Records, - method : DwnMethodName.Subscribe, - protocol : 'some-protocol' - }, - signer: Jws.createSigner(alice) - }); - - // verify device X subscribing to the chat message from Bob's DWN fails - const recordsSubscribeByDeviceX = await RecordsSubscribe.create({ - signer : Jws.createSigner(deviceX), - delegatedGrant : subscribeGrantForDeviceX.asDelegatedGrant(), - protocolRole : 'thread/participant', - filter : { - protocol, - contextId : threadRecord.message.contextId, - protocolPath : 'thread/chat' - } - }); - const deviceXRecordsSubscribeReply = await dwn.processMessage(bob.did, recordsSubscribeByDeviceX.message); - expect(deviceXRecordsSubscribeReply.status.code).to.equal(401); - expect(deviceXRecordsSubscribeReply.status.detail).to.contain(DwnErrorCode.RecordsGrantAuthorizationQueryOrSubscribeProtocolScopeMismatch); - // Bob writes a chat message in the thread const chatRecord = await TestDataGenerator.generateRecordsWrite({ author : bob, @@ -734,6 +704,9 @@ export function testDelegatedGrantScenarios(): void { const chatRecordReply = await dwn.processMessage(bob.did, chatRecord.message, { dataStream: chatRecord.dataStream }); expect(chatRecordReply.status.code).to.equal(202); + + // 2. Alice creates a delegated grant for device X to act as her for a protocol that is NOT chat protocol + // Alice creates a delegated query grant for device X to act as Alice but not for chat protocol const queryGrantForDeviceX = await PermissionsGrant.create({ delegated : true, // this is a delegated grant @@ -744,7 +717,7 @@ export function testDelegatedGrantScenarios(): void { scope : { interface : DwnInterfaceName.Records, method : DwnMethodName.Query, - protocol : 'some-protocol' + protocol : 'some-other-protocol' }, signer: Jws.createSigner(alice) }); @@ -759,11 +732,29 @@ export function testDelegatedGrantScenarios(): void { scope : { interface : DwnInterfaceName.Records, method : DwnMethodName.Read, - protocol : 'some-protocol' + protocol : 'some-other-protocol' }, signer: Jws.createSigner(alice) }); + // Alice creates a delegated subscribe grant for device X to act as Alice but not for chat protocol + const subscribeGrantForDeviceX = await PermissionsGrant.create({ + delegated : true, // this is a delegated grant + dateExpires : Time.createOffsetTimestamp({ seconds: 100 }), + grantedBy : alice.did, + grantedTo : deviceX.did, + grantedFor : alice.did, + scope : { + interface : DwnInterfaceName.Records, + method : DwnMethodName.Subscribe, + protocol : 'some-other-protocol' + }, + signer: Jws.createSigner(alice) + }); + + + // 3. Device X attempts to use the delegated grant to read, query and subscribe to the chat thread and gets rejected by Bob's DWN + // verify device X querying for the chat message from Bob's DWN fails const recordsQueryByDeviceX = await RecordsQuery.create({ signer : Jws.createSigner(deviceX), @@ -788,10 +779,24 @@ export function testDelegatedGrantScenarios(): void { recordId: chatRecord.message.recordId } }); - const deviceXReadReply = await dwn.processMessage(bob.did, recordsReadByDeviceX.message); expect(deviceXReadReply.status.code).to.equal(401); expect(deviceXReadReply.status.detail).to.contain(DwnErrorCode.RecordsGrantAuthorizationScopeProtocolMismatch); + + // verify device X subscribing to the chat message from Bob's DWN fails + const recordsSubscribeByDeviceX = await RecordsSubscribe.create({ + signer : Jws.createSigner(deviceX), + delegatedGrant : subscribeGrantForDeviceX.asDelegatedGrant(), + protocolRole : 'thread/participant', + filter : { + protocol, + contextId : threadRecord.message.contextId, + protocolPath : 'thread/chat' + } + }); + const deviceXRecordsSubscribeReply = await dwn.processMessage(bob.did, recordsSubscribeByDeviceX.message); + expect(deviceXRecordsSubscribeReply.status.code).to.equal(401); + expect(deviceXRecordsSubscribeReply.status.detail).to.contain(DwnErrorCode.RecordsGrantAuthorizationQueryOrSubscribeProtocolScopeMismatch); }); it('should fail if delegated grant has a mismatching protocol scope - delete', async () => { @@ -800,10 +805,10 @@ export function testDelegatedGrantScenarios(): void { // 2. Bob starts a chat thread with Carol on his DWN // 3. Alice creates a delegated delete grant for Device X to act as her for a protocol that is NOT chat protocol // 4. Device X should NOT be able to delete a chat message as Alice - const alice = await DidKeyResolver.generate(); - const deviceX = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const deviceX = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // Bob has the chat protocol installed const protocolDefinition = threadRoleProtocolDefinition; diff --git a/tests/scenarios/end-to-end-tests.spec.ts b/tests/scenarios/end-to-end-tests.spec.ts index 7cd1b24ff..325662360 100644 --- a/tests/scenarios/end-to-end-tests.spec.ts +++ b/tests/scenarios/end-to-end-tests.spec.ts @@ -7,7 +7,6 @@ import sinon from 'sinon'; import threadRoleProtocolDefinition from '../vectors/protocol-definitions/thread-role.json' assert { type: 'json' }; import { authenticate } from '../../src/core/auth.js'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; import { Encoder } from '../../src/index.js'; import { HdKey } from '../../src/utils/hd-key.js'; import { KeyDerivationScheme } from '../../src/utils/hd-key.js'; @@ -17,7 +16,8 @@ import { TestStores } from '../test-stores.js'; import { TestStubGenerator } from '../utils/test-stub-generator.js'; import chai, { expect } from 'chai'; -import { DataStream, DidResolver, Dwn, Jws, Protocols, ProtocolsConfigure, ProtocolsQuery, Records, RecordsRead } from '../../src/index.js'; +import { DataStream, Dwn, Jws, Protocols, ProtocolsConfigure, ProtocolsQuery, Records, RecordsRead } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; chai.use(chaiAsPromised); @@ -33,7 +33,7 @@ export function testEndToEndScenarios(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; diff --git a/tests/scenarios/events-query.spec.ts b/tests/scenarios/events-query.spec.ts index 2532fe72f..0e7ccbdca 100644 --- a/tests/scenarios/events-query.spec.ts +++ b/tests/scenarios/events-query.spec.ts @@ -8,12 +8,12 @@ import type { import freeForAll from '../vectors/protocol-definitions/free-for-all.json' assert { type: 'json' }; import threadProtocol from '../vectors/protocol-definitions/thread-role.json' assert { type: 'json' }; -import { TestStores } from '../test-stores.js'; -import { DidKeyResolver, DidResolver, Dwn, DwnConstant, DwnInterfaceName, DwnMethodName, Message, Time } from '../../src/index.js'; - import { expect } from 'chai'; import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; +import { TestStores } from '../test-stores.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; +import { Dwn, DwnConstant, DwnInterfaceName, DwnMethodName, Message, Time } from '../../src/index.js'; export function testEventsQueryScenarios(): void { describe('events query tests', () => { @@ -27,7 +27,7 @@ export function testEventsQueryScenarios(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -50,7 +50,7 @@ export function testEventsQueryScenarios(): void { }); it('supports multiple filter types', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const record = await TestDataGenerator.generateRecordsWrite({ author: alice }); const grant = await TestDataGenerator.generatePermissionsGrant({ author: alice }); const protocol = await TestDataGenerator.generateProtocolsConfigure({ author: alice }); @@ -88,7 +88,7 @@ export function testEventsQueryScenarios(): void { // alice creates 2 additional messages (RecordsDelete, ProtocolsRevoke) // alice queries for messages for each interface respectively providing a cursor. - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const record = await TestDataGenerator.generateRecordsWrite({ author: alice }); const grant = await TestDataGenerator.generatePermissionsGrant({ author: alice }); const protocol = await TestDataGenerator.generateProtocolsConfigure({ author: alice }); @@ -176,7 +176,7 @@ export function testEventsQueryScenarios(): void { // alice queries for only RecordsWrite messages // alice creates more messages to query beyond a cursor - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // write 1 const record1 = await TestDataGenerator.generateRecordsWrite({ author: alice }); @@ -246,7 +246,7 @@ export function testEventsQueryScenarios(): void { const firstDayOf2022 = Time.createTimestamp({ year: 2022, month: 1, day: 1 }); const firstDayOf2023 = Time.createTimestamp({ year: 2023, month: 1, day: 1 }); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write = await TestDataGenerator.generateRecordsWrite({ author: alice, dateCreated: firstDayOf2021, messageTimestamp: firstDayOf2021 }); const grant = await TestDataGenerator.generatePermissionsGrant({ author: alice, messageTimestamp: firstDayOf2022 }); const protocol = await TestDataGenerator.generateProtocolsConfigure({ author: alice, messageTimestamp: firstDayOf2023 }); @@ -295,7 +295,7 @@ export function testEventsQueryScenarios(): void { const firstDayOf2023 = Time.createTimestamp({ year: 2023, month: 1, day: 1 }); const firstDayOf2024 = Time.createTimestamp({ year: 2024, month: 1, day: 1 }); - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write1 = await TestDataGenerator.generateRecordsWrite({ author: alice, dateCreated: firstDayOf2021, messageTimestamp: firstDayOf2021 }); const write2 = await TestDataGenerator.generateRecordsWrite({ author: alice, dateCreated: firstDayOf2022, messageTimestamp: firstDayOf2022 }); const write3 = await TestDataGenerator.generateRecordsWrite({ author: alice, dateCreated: firstDayOf2023, messageTimestamp: firstDayOf2023 }); @@ -414,7 +414,7 @@ export function testEventsQueryScenarios(): void { // when issuing an EventsQuery for the specific protocol, only Events related to it should be returned. // alice then creates an additional messages to query after a cursor - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // create a proto1 const protoConf1 = await TestDataGenerator.generateProtocolsConfigure({ @@ -519,9 +519,9 @@ export function testEventsQueryScenarios(): void { // alice deletes carol participant message // alice filters for 'thread/participant' after a cursor - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // create protocol const protocolConfigure = await TestDataGenerator.generateProtocolsConfigure({ @@ -671,9 +671,9 @@ export function testEventsQueryScenarios(): void { // alice queries for events meant for specific recipients // alice then makes another message to query for using the pervious as a cursor - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); const protocolConfigure = await TestDataGenerator.generateProtocolsConfigure({ author : alice, @@ -769,7 +769,7 @@ export function testEventsQueryScenarios(): void { }); it('filters by schema', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const schema1Message1 = await TestDataGenerator.generateRecordsWrite({ author : alice, @@ -839,7 +839,7 @@ export function testEventsQueryScenarios(): void { }); it('filters by recordId', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // a write as a control, will not show up in query const controlWrite = await TestDataGenerator.generateRecordsWrite({ @@ -897,7 +897,7 @@ export function testEventsQueryScenarios(): void { // alice queries for `image/jpeg` retrieving the one message // alice adds another image to query for using the prior image as a cursor - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const textFile = await TestDataGenerator.generateRecordsWrite({ author : alice, @@ -958,7 +958,7 @@ export function testEventsQueryScenarios(): void { // alice inserts both small and large data // alice requests events for messages with data size under a threshold - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const smallSize1 = await TestDataGenerator.generateRecordsWrite({ author: alice, @@ -1020,9 +1020,9 @@ export function testEventsQueryScenarios(): void { // alice writes more messages to both bob and carol in their respective threads // alice queries for events beyond the latest from the last query, retrieving the additional messages to bob - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); const protocolConfigure = await TestDataGenerator.generateProtocolsConfigure({ author : alice, diff --git a/tests/scenarios/subscriptions.spec.ts b/tests/scenarios/subscriptions.spec.ts index 3137dbfae..b5867d558 100644 --- a/tests/scenarios/subscriptions.spec.ts +++ b/tests/scenarios/subscriptions.spec.ts @@ -13,7 +13,8 @@ import { TestDataGenerator } from '../utils/test-data-generator.js'; import { TestEventStream } from '../test-event-stream.js'; import { TestStores } from '../test-stores.js'; import { Time } from '../../src/utils/time.js'; -import { DidKeyResolver, DidResolver, Dwn, DwnConstant, DwnInterfaceName, DwnMethodName, Message } from '../../src/index.js'; +import { DidKeyMethod, DidResolver } from '@web5/dids'; +import { Dwn, DwnConstant, DwnInterfaceName, DwnMethodName, Message } from '../../src/index.js'; import { expect } from 'chai'; @@ -28,7 +29,7 @@ export function testSubscriptionScenarios(): void { // important to follow the `before` and `after` pattern to initialize and clean the stores in tests // so that different test suites can reuse the same backend store for testing before(async () => { - didResolver = new DidResolver([new DidKeyResolver()]); + didResolver = new DidResolver({ didResolvers: [DidKeyMethod] }); const stores = TestStores.get(); messageStore = stores.messageStore; @@ -52,7 +53,7 @@ export function testSubscriptionScenarios(): void { describe('events subscribe', () => { it('all events', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // create a handler that adds the messageCid of each message to an array. const messageCids: string[] = []; @@ -110,7 +111,7 @@ export function testSubscriptionScenarios(): void { // alice checks that each handler emitted the appropriate message // alice deletes the record, and revokes the grant // alice checks that the Records and Permissions handlers emitted the appropriate message - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // subscribe to records const recordsInterfaceSubscription = await TestDataGenerator.generateEventsSubscribe({ @@ -222,7 +223,7 @@ export function testSubscriptionScenarios(): void { // alice queries for only RecordsWrite messages // alice creates more messages to query beyond a cursor - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // subscribe to records write const recordsWriteSubscription = await TestDataGenerator.generateEventsSubscribe({ @@ -271,7 +272,7 @@ export function testSubscriptionScenarios(): void { // alice creates (3) different message types all related to "proto1" (Configure, RecordsWrite, RecordsDelete) // alice creates (3) different message types all related to "proto2" (Configure, RecordsWrite, RecordsDelete) // when subscribing for a specific protocol, only Messages related to it should be emitted. - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const proto1Messages:string[] = []; const proto1Handler = async (message:GenericMessage):Promise => { @@ -374,9 +375,9 @@ export function testSubscriptionScenarios(): void { // alice deletes carol participant message // alice checks that the correct messages were omitted - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // create protocol const protocolConfigure = await TestDataGenerator.generateProtocolsConfigure({ @@ -522,7 +523,7 @@ export function testSubscriptionScenarios(): void { }); it('filters by schema', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // we will add messageCids to these arrays as they are received by their handler to check against later const schema1Messages:string[] = []; @@ -595,7 +596,7 @@ export function testSubscriptionScenarios(): void { }); it('filters by recordId', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const write = await TestDataGenerator.generateRecordsWrite({ author : alice, @@ -657,9 +658,9 @@ export function testSubscriptionScenarios(): void { }); it('filters by recipient', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); const receivedMessages:string[] = []; @@ -750,7 +751,7 @@ export function testSubscriptionScenarios(): void { // alice queries for `image/jpeg` retrieving the one message // alice adds another image to query for using the prior image as a cursor - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const imageMessages: string[] = []; const imageHandler = async (message:GenericMessage):Promise => { @@ -827,7 +828,7 @@ export function testSubscriptionScenarios(): void { // alice subscribes to messages with data size under a threshold // alice inserts both small and large data - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const smallMessages: string[] = []; const subscriptionHandler = async (message:GenericMessage):Promise => { @@ -884,7 +885,7 @@ export function testSubscriptionScenarios(): void { }); it('does not emit events after subscription is closed', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); // messageCids of events const messageCids:string[] = []; @@ -927,7 +928,7 @@ export function testSubscriptionScenarios(): void { describe('records subscribe', () => { it('allows for anonymous subscriptions to published records', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages:string[] = []; const subscriptionHandler = async (message:GenericMessage):Promise => { @@ -969,9 +970,9 @@ export function testSubscriptionScenarios(): void { }); it('allows authorized subscriptions to records intended for a recipient', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // bob subscribes to any messages he's authorized to see const bobMessages:string[] = []; @@ -1044,9 +1045,9 @@ export function testSubscriptionScenarios(): void { // alice deletes carol participant message // alice checks that the correct messages were omitted - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); - const carol = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); + const carol = await TestDataGenerator.generateDidKeyPersona(); // create protocol const protocolConfigure = await TestDataGenerator.generateProtocolsConfigure({ diff --git a/tests/store/message-store.spec.ts b/tests/store/message-store.spec.ts index 6860e6ebe..5b21dae8b 100644 --- a/tests/store/message-store.spec.ts +++ b/tests/store/message-store.spec.ts @@ -4,7 +4,6 @@ import type { RecordsWriteMessage } from '../../src/types/records-types.js'; import { expect } from 'chai'; -import { DidKeyResolver } from '../../src/index.js'; import { lexicographicalCompare } from '../../src/utils/string.js'; import { Message } from '../../src/core/message.js'; import { SortDirection } from '../../src/types/query-types.js'; @@ -34,7 +33,7 @@ export function testMessageStore(): void { }); it('stores messages as cbor/sha256 encoded blocks with CID as key', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generatePermissionsRequest(); const { messageTimestamp } = message.descriptor; @@ -51,7 +50,7 @@ export function testMessageStore(): void { // https://github.com/TBD54566975/dwn-sdk-js/issues/170 it('#170 - should be able to update (delete and insert new) indexes to an existing message', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite(); const { messageTimestamp } = message.descriptor; @@ -78,7 +77,7 @@ export function testMessageStore(): void { }); it('should index properties with characters beyond just letters and digits', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const schema = 'http://my-awesome-schema/awesomeness_schema'; const { message } = await TestDataGenerator.generateRecordsWrite({ schema }); @@ -91,7 +90,7 @@ export function testMessageStore(): void { }); it('should not store anything if aborted beforehand', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite(); const { messageTimestamp } = message.descriptor; @@ -113,7 +112,7 @@ export function testMessageStore(): void { }); it('should not index anything if aborted during', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const schema = 'http://my-awesome-schema/awesomeness_schema#awesome-1?id=awesome_1'; const { message } = await TestDataGenerator.generateRecordsWrite({ schema }); @@ -141,7 +140,7 @@ export function testMessageStore(): void { }); it('should not store anything if aborted beforehand', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite(); const { messageTimestamp } = message.descriptor; @@ -163,7 +162,7 @@ export function testMessageStore(): void { }); it('should not delete if aborted', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite(); const { messageTimestamp } = message.descriptor; @@ -183,8 +182,8 @@ export function testMessageStore(): void { }); it('should not delete the message of another tenant', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite(); const { messageTimestamp } = message.descriptor; @@ -208,8 +207,8 @@ export function testMessageStore(): void { }); it('should not clear the MessageStore index of another tenant', async () => { - const alice = await DidKeyResolver.generate(); - const bob = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); + const bob = await TestDataGenerator.generateDidKeyPersona(); const { message } = await TestDataGenerator.generateRecordsWrite(); const { messageTimestamp } = message.descriptor; @@ -254,7 +253,7 @@ export function testMessageStore(): void { describe('sorting', async () => { it('should sort on messageTimestamp Ascending if no sort is specified', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ messageTimestamp: TestDataGenerator.randomTimestamp() @@ -274,7 +273,7 @@ export function testMessageStore(): void { }); it('should sort on messageTimestamp Ascending', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ messageTimestamp: TestDataGenerator.randomTimestamp() @@ -293,7 +292,7 @@ export function testMessageStore(): void { }); it('should sort on dateCreated Ascending', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ dateCreated: TestDataGenerator.randomTimestamp(), }))); @@ -313,7 +312,7 @@ export function testMessageStore(): void { }); it('should sort on dateCreated Descending', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ dateCreated: TestDataGenerator.randomTimestamp(), }))); @@ -333,7 +332,7 @@ export function testMessageStore(): void { }); it('should sort on datePublished Ascending', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ published : true, datePublished : TestDataGenerator.randomTimestamp() @@ -354,7 +353,7 @@ export function testMessageStore(): void { }); it('should sort on datePublished Descending', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ published : true, datePublished : TestDataGenerator.randomTimestamp() @@ -377,7 +376,7 @@ export function testMessageStore(): void { describe('pagination', async () => { it('should return all records if no limit is specified', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ messageTimestamp: TestDataGenerator.randomTimestamp() }))); @@ -390,7 +389,7 @@ export function testMessageStore(): void { }); it('should limit records', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ messageTimestamp: TestDataGenerator.randomTimestamp() }))); @@ -411,7 +410,7 @@ export function testMessageStore(): void { }); it('should only return a cursor if there are additional results', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ messageTimestamp: TestDataGenerator.randomTimestamp() }))); @@ -429,7 +428,7 @@ export function testMessageStore(): void { }); it('should return all records from the cursor onwards when no limit is provided', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(13).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ messageTimestamp: TestDataGenerator.randomTimestamp() }))); @@ -452,7 +451,7 @@ export function testMessageStore(): void { }); it('should limit records when a cursor and limit are provided', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(10).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ messageTimestamp: TestDataGenerator.randomTimestamp() }))); @@ -476,7 +475,7 @@ export function testMessageStore(): void { }); it('should paginate through all of the records', async () => { - const alice = await DidKeyResolver.generate(); + const alice = await TestDataGenerator.generateDidKeyPersona(); const messages = await Promise.all(Array(23).fill({}).map((_) => TestDataGenerator.generateRecordsWrite({ messageTimestamp: TestDataGenerator.randomTimestamp() }))); diff --git a/tests/utils/test-data-generator.ts b/tests/utils/test-data-generator.ts index b6a0f690d..6fc796e07 100644 --- a/tests/utils/test-data-generator.ts +++ b/tests/utils/test-data-generator.ts @@ -1,5 +1,5 @@ import type { DerivedPrivateJwk } from '../../src/utils/hd-key.js'; -import type { DidResolutionResult } from '../../src/types/did-types.js'; +import type { DidResolutionResult } from '@web5/dids'; import type { EventsGetOptions } from '../../src/interfaces/events-get.js'; import type { EventsQueryOptions } from '../../src/interfaces/events-query.js'; import type { EventsSubscribeOptions } from '../../src/interfaces/events-subscribe.js'; @@ -23,11 +23,13 @@ import type { PrivateJwk, PublicJwk } from '../../src/types/jose-types.js'; import type { ProtocolDefinition, ProtocolsConfigureMessage, ProtocolsQueryMessage } from '../../src/types/protocols-types.js'; import type { RecordsSubscribeMessage, RecordsWriteMessage } from '../../src/types/records-types.js'; - import * as cbor from '@ipld/dag-cbor'; import { CID } from 'multiformats/cid'; import { DataStream } from '../../src/utils/data-stream.js'; -import { DidKeyResolver } from '../../src/did/did-key-resolver.js'; +import { Did } from '../../src/did/did.js'; +import { DidKeyMethod } from '@web5/dids'; +import { ed25519 } from '../../src/jose/algorithms/signing/ed25519.js'; +import { Encoder } from '../../src/utils/encoder.js'; import { Encryption } from '../../src/utils/encryption.js'; import { EventsGet } from '../../src/interfaces/events-get.js'; import { EventsQuery } from '../../src/interfaces/events-query.js'; @@ -712,7 +714,7 @@ export class TestDataGenerator { * Generates a RecordsDelete for testing. */ public static async generateRecordsDelete(input?: GenerateRecordsDeleteInput): Promise { - const author = input?.author ?? await DidKeyResolver.generate(); + const author = input?.author ?? await TestDataGenerator.generateDidKeyPersona(); const recordsDelete = await RecordsDelete.create({ recordId : input?.recordId ?? await TestDataGenerator.randomCborSha256Cid(), @@ -900,6 +902,17 @@ export class TestDataGenerator { }; } + /** + * Generates a random but well-formed signature string in Base64Url format. + */ + public static async randomSignatureString(): Promise { + const keyPair = await ed25519.generateKeyPair(); + const signatureBytes = await ed25519.sign(TestDataGenerator.randomBytes(32), keyPair.privateJwk); + const signatureString = Encoder.bytesToBase64Url(signatureBytes); + return signatureString; + } + + /** * Generates a random alpha-numeric string. */ @@ -979,10 +992,45 @@ export class TestDataGenerator { controller : persona.did, id : persona.keyId, type : 'JsonWebKey2020', - publicKeyJwk : persona.keyPair.publicJwk + // TODO: #672 - port and use type from @web5/crypto - https://github.com/TBD54566975/dwn-sdk-js/issues/672 + publicKeyJwk : persona.keyPair.publicJwk as any }] }, didDocumentMetadata: {} }; } + + /** + * Generates a did:key persona. + */ + public static async generateDidKeyPersona(): Promise { + + const portableDid = await DidKeyMethod.create(); + const keyId = TestDataGenerator.getKeyId(portableDid.did); + const keyPair = { + // TODO: #672 - port and use type from @web5/crypto - https://github.com/TBD54566975/dwn-sdk-js/issues/672 + publicJwk : portableDid.keySet.verificationMethodKeys![0].publicKeyJwk as PublicJwk, + privateJwk : portableDid.keySet.verificationMethodKeys![0].privateKeyJwk as PrivateJwk, + }; + + return { + did : portableDid.did, + keyId, + keyPair, + signer : new PrivateKeySigner({ + privateJwk : keyPair.privateJwk, + algorithm : keyPair.privateJwk.alg, + keyId + }) + }; + } + + /** + * Gets the fully qualified key ID of a `did:key` DID. ie. '#' + */ + public static getKeyId(did: string): string { + const methodSpecificId = Did.getMethodSpecificId(did); + const keyId = `${did}#${methodSpecificId}`; + return keyId; + } } \ No newline at end of file diff --git a/tests/utils/test-stub-generator.ts b/tests/utils/test-stub-generator.ts index 8c837a6f7..21589c259 100644 --- a/tests/utils/test-stub-generator.ts +++ b/tests/utils/test-stub-generator.ts @@ -1,9 +1,9 @@ -import type { DidResolutionResult } from '../../src/types/did-types.js'; +import type { DidResolutionResult } from '@web5/dids'; import type { Persona } from './test-data-generator.js'; import sinon from 'sinon'; -import { DidResolver } from '../../src/did/did-resolver.js'; +import { DidResolver } from '@web5/dids'; import { TestDataGenerator } from './test-data-generator.js'; /**