diff --git a/packages/cli/default/agent.template.yml b/packages/cli/default/agent.template.yml index 8e780514..2fd26fbd 100644 --- a/packages/cli/default/agent.template.yml +++ b/packages/cli/default/agent.template.yml @@ -71,6 +71,7 @@ constants: - checkStatus - routeCreationVerifiableCredential - routeVerificationCredential + - computeHash # Data base dbConnection: @@ -127,7 +128,7 @@ dbConnectionRevocationList: revocationList: $require: '@vckit/revocationlist#RevocationStatus2020' $args: - - revocationListPath: + - revocationListPath: $ref: /constants/baseUrl bitStringLength: 8 dbConnection: @@ -424,3 +425,4 @@ agent: $args: - RevocationList2020Status: $require: '@vckit/revocationlist?t=object#checkStatus' + - $require: '@vckit/tools#MultibaseEncodedSHA256' diff --git a/packages/cli/default/default-dev.yml b/packages/cli/default/default-dev.yml index 9aaf018f..60ee6983 100644 --- a/packages/cli/default/default-dev.yml +++ b/packages/cli/default/default-dev.yml @@ -74,6 +74,7 @@ constants: - checkStatus - routeCreationVerifiableCredential - routeVerificationCredential + - computeHash # Data base dbConnection: @@ -417,3 +418,4 @@ agent: $args: - RevocationList2020Status: $require: '@vckit/revocationlist?t=object#checkStatus' + - $require: '@vckit/tools#MultibaseEncodedSHA256' diff --git a/packages/cli/default/default.yml b/packages/cli/default/default.yml index b82d2417..993c85a1 100644 --- a/packages/cli/default/default.yml +++ b/packages/cli/default/default.yml @@ -74,6 +74,7 @@ constants: - checkStatus - routeCreationVerifiableCredential - routeVerificationCredential + - computeHash # Data base dbConnection: @@ -417,3 +418,4 @@ agent: $args: - RevocationList2020Status: $require: '@vckit/revocationlist?t=object#checkStatus' + - $require: '@vckit/tools#MultibaseEncodedSHA256' diff --git a/packages/cli/package.json b/packages/cli/package.json index 32e72f73..da1d5d78 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -50,6 +50,7 @@ "@vckit/revocationlist": "workspace:^", "@vckit/utils": "workspace:^", "@vckit/vc-api": "workspace:1.0.0-beta.7", + "@vckit/tools": "workspace:^", "@veramo/core": "5.5.3", "@veramo/credential-eip712": "5.5.3", "@veramo/credential-ld": "5.5.3", diff --git a/packages/core-types/package.json b/packages/core-types/package.json index 7ca5e7d9..c7a45a8b 100644 --- a/packages/core-types/package.json +++ b/packages/core-types/package.json @@ -31,7 +31,8 @@ "IRenderer": "./src/types/IRender.ts", "IEncryptedStorage": "./src/types/IEncryptedStorage.ts", "IRevocationList2020": "./src/types/IRevocationList2020.ts", - "ICredentialRouter": "./src/types/ICredentialRouter.ts" + "ICredentialRouter": "./src/types/ICredentialRouter.ts", + "ITools": "./src/types/ITools.ts" } }, "dependencies": { diff --git a/packages/core-types/src/index.ts b/packages/core-types/src/index.ts index 7368ce6e..23cef4ff 100644 --- a/packages/core-types/src/index.ts +++ b/packages/core-types/src/index.ts @@ -32,3 +32,4 @@ export * from './types/IRendererProvider.js'; export * from './types/IEncryptedStorage.js'; export * from './types/IRevocationList2020.js'; export * from './types/ICredentialRouter.js'; +export * from './types/ITools.js'; diff --git a/packages/core-types/src/plugin.schema.json b/packages/core-types/src/plugin.schema.json index 6627dca3..7afe6d4a 100644 --- a/packages/core-types/src/plugin.schema.json +++ b/packages/core-types/src/plugin.schema.json @@ -6739,5 +6739,21 @@ } } } + }, + "ITools": { + "components": { + "schemas": {}, + "methods": { + "computeHash": { + "description": "", + "arguments": { + "type": "string" + }, + "returnType": { + "type": "string" + } + } + } + } } } \ No newline at end of file diff --git a/packages/core-types/src/types/ITools.ts b/packages/core-types/src/types/ITools.ts new file mode 100644 index 00000000..e1306135 --- /dev/null +++ b/packages/core-types/src/types/ITools.ts @@ -0,0 +1,8 @@ +import { IPluginMethodMap } from './IAgent.js'; + +/** + * @public + */ +export interface ITools extends IPluginMethodMap { + computeHash(args: string): Promise; +} diff --git a/packages/tools/README.md b/packages/tools/README.md new file mode 100644 index 00000000..890d8480 --- /dev/null +++ b/packages/tools/README.md @@ -0,0 +1,3 @@ +# Tools + +This directory contains tools that are used to expose as library or API. diff --git a/packages/tools/__tests__/computeHash.test.ts b/packages/tools/__tests__/computeHash.test.ts new file mode 100644 index 00000000..7bc5c747 --- /dev/null +++ b/packages/tools/__tests__/computeHash.test.ts @@ -0,0 +1,36 @@ +import { jest } from '@jest/globals'; +import { MultibaseEncodedSHA256 } from '../src/hash/multibase-encoded-256'; + +describe('compute hash', () => { + let computeHash: any; + + beforeEach(() => { + const plugin = new MultibaseEncodedSHA256(); + computeHash = plugin.methods.computeHash; + }); + + it('should compute hash', async () => { + const hash = await computeHash('hello world'); + expect(hash).toBe('zQmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4'); + }); + + it('should throw error when value is empty', async () => { + await expect(computeHash('')).rejects.toThrow('Value is invalid'); + }); + + it('should throw error when value is not a string', async () => { + await expect(computeHash(123)).rejects.toThrow('Value is invalid'); + + await expect(computeHash(true)).rejects.toThrow('Value is invalid'); + + await expect(computeHash(NaN)).rejects.toThrow('Value is invalid'); + + await expect(computeHash(null)).rejects.toThrow('Value is invalid'); + + await expect(computeHash(undefined)).rejects.toThrow('Value is invalid'); + + await expect(computeHash({})).rejects.toThrow('Value is invalid'); + + await expect(computeHash([])).rejects.toThrow('Value is invalid'); + }); +}); diff --git a/packages/tools/package.json b/packages/tools/package.json new file mode 100644 index 00000000..725a88cc --- /dev/null +++ b/packages/tools/package.json @@ -0,0 +1,29 @@ +{ + "name": "@vckit/tools", + "version": "1.0.0", + "description": "", + "main": "build/index.js", + "types": "build/index.d.ts", + "exports": { + ".": "./build/index.js" + }, + "files": [ + "build/**/*", + "src/**/*", + "plugin.schema.json", + "README.md", + "LICENSE" + ], + "type": "module", + "scripts": { + "build": "tsc", + "watch": "tsc -b --watch" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@vckit/core-types": "workspace:1.0.0-beta.7", + "multiformats": "^13.1.0" + } +} diff --git a/packages/tools/src/hash/multibase-encoded-256.ts b/packages/tools/src/hash/multibase-encoded-256.ts new file mode 100644 index 00000000..2b5e94d0 --- /dev/null +++ b/packages/tools/src/hash/multibase-encoded-256.ts @@ -0,0 +1,26 @@ +import { IAgentPlugin, ITools } from '@vckit/core-types'; +import { sha256 } from 'multiformats/hashes/sha2'; +import { base58btc } from 'multiformats/bases/base58'; +import schema from '@vckit/core-types/build/plugin.schema.json' assert { type: 'json' }; + +export class MultibaseEncodedSHA256 implements IAgentPlugin { + readonly methods: ITools; + readonly schema = schema.ITools; + + constructor() { + this.methods = { + computeHash: this.computeHash.bind(this), + }; + } + + async computeHash(value: string): Promise { + if (!value || typeof value !== 'string') { + throw new Error('Value is invalid'); + } + + const bytes = new TextEncoder().encode(value); + const hash = await sha256.digest(bytes); + const multibasedHash = base58btc.encode(hash.bytes); + return multibasedHash; + } +} diff --git a/packages/tools/src/index.ts b/packages/tools/src/index.ts new file mode 100644 index 00000000..e0e192a4 --- /dev/null +++ b/packages/tools/src/index.ts @@ -0,0 +1 @@ +export { MultibaseEncodedSHA256 } from './hash/multibase-encoded-256.js'; diff --git a/packages/tools/tsconfig.json b/packages/tools/tsconfig.json new file mode 100644 index 00000000..7b4a09fd --- /dev/null +++ b/packages/tools/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.settings.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build", + "declarationDir": "build", + "skipLibCheck": true + }, + "references": [], + "include": ["./**/*.ts", "./src/plugin.schema.json"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4764bee3..ade3ac52 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -198,6 +198,9 @@ importers: '@vckit/revocationlist': specifier: workspace:^ version: link:../revocation-list-2020 + '@vckit/tools': + specifier: workspace:^ + version: link:../tools '@vckit/utils': specifier: workspace:^ version: link:../utils @@ -1247,6 +1250,15 @@ importers: specifier: ^1.0.0 version: 1.0.0 + packages/tools: + dependencies: + '@vckit/core-types': + specifier: workspace:1.0.0-beta.7 + version: link:../core-types + multiformats: + specifier: ^13.1.0 + version: 13.1.0 + packages/utils: dependencies: express: @@ -5511,7 +5523,6 @@ packages: react: 16.14.0 scheduler: 0.19.1 dev: false - bundledDependencies: false /@humanwhocodes/config-array@0.11.13: resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} @@ -12109,6 +12120,7 @@ packages: /@types/minimatch@5.1.2: resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + requiresBuild: true dev: true /@types/minimist@1.2.5: @@ -20049,7 +20061,6 @@ packages: dependencies: is-hex-prefixed: 1.0.0 strip-hex-prefix: 1.0.0 - bundledDependencies: false /ethr-did-registry@0.0.3: resolution: {integrity: sha512-4BPvMGkxAK9vTduCq6D5b8ZqjteD2cvDIPPriXP6nnmPhWKFSxypo+AFvyQ0omJGa0cGTR+dkdI/8jiF7U/qaw==} @@ -27877,6 +27888,10 @@ packages: /multiformats@13.0.0: resolution: {integrity: sha512-xiIB0p7EKmETm3wyKedOg/xuyQ18PoWwXCzzgpZAiDxL9ktl3XTh8AqoDT5kAqRg+DU48XAGPsUJL2Rn6Bx3Lw==} + /multiformats@13.1.0: + resolution: {integrity: sha512-HzdtdBwxsIkzpeXzhQ5mAhhuxcHbjEHH+JQoxt7hG/2HGFjjwyolLo7hbaexcnhoEuV4e0TNJ8kkpMjiEYY4VQ==} + dev: false + /multiformats@9.9.0: resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} @@ -32217,7 +32232,6 @@ packages: prop-types: 15.8.1 react: 16.14.0 scheduler: 0.19.1 - bundledDependencies: false /react-dom@18.2.0(react@18.2.0): resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} @@ -32918,7 +32932,6 @@ packages: loose-envify: 1.4.0 object-assign: 4.1.1 prop-types: 15.8.1 - bundledDependencies: false /react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}