From ff28ca4f181c6bf330b66ae12584c69a1784622b Mon Sep 17 00:00:00 2001 From: Ankur Banerjee Date: Tue, 26 Sep 2023 14:11:36 +0100 Subject: [PATCH] npm run format --- .prettierrc.json | 9 + package-lock.json | 20 +- package.json | 4 +- src/index.ts | 188 ++- src/modules/_.ts | 76 +- src/modules/did.ts | 493 +++---- src/modules/resource.ts | 225 ++-- src/querier.ts | 59 +- src/registry.ts | 11 +- src/signer.ts | 284 +++-- src/types.ts | 118 +- src/utils.ts | 542 ++++---- tests/index.test.ts | 313 ++--- tests/modules/did.test.ts | 2192 ++++++++++++++++++-------------- tests/modules/resource.test.ts | 2127 +++++++++++++++++-------------- tests/signer.test.ts | 398 +++--- tests/testutils.test.ts | 55 +- tests/utils.test.ts | 270 ++-- 18 files changed, 3928 insertions(+), 3456 deletions(-) create mode 100644 .prettierrc.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..5c36adc4 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "useTabs": true, + "tabWidth": 4, + "printWidth": 120, + "proseWrap": "always", + "semi": true, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/package-lock.json b/package-lock.json index dfb44eb5..96af1770 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@cheqd/sdk", - "version": "3.7.1", + "version": "3.7.2-develop.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@cheqd/sdk", - "version": "3.7.1", + "version": "3.7.2-develop.1", "license": "Apache-2.0", "dependencies": { "@cheqd/ts-proto": "^3.3.5", @@ -42,6 +42,7 @@ "cross-env": "^7.0.3", "jest": "^29.7.0", "long": "^4.0.0", + "prettier": "^3.0.3", "semantic-release": "^22.0.5", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", @@ -9363,6 +9364,21 @@ "node": ">=8" } }, + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", diff --git a/package.json b/package.json index 4fb4bc7d..c52e2ef4 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "build": "rm -rf build && npm run build:types && npm run build:esm && npm run build:cjs", "build:types": "tsc -p tsconfig.types.json", "build:esm": "tsc -p tsconfig.esm.json", - "build:cjs": "echo 'Experimental backwards compatibility! Use v2 major version or `@cjs` npm tag for deep CommonJS exports.' && tsc -p tsconfig.cjs.json" + "build:cjs": "echo 'Experimental backwards compatibility! Use v2 major version or `@cjs` npm tag for deep CommonJS exports.' && tsc -p tsconfig.cjs.json", + "format": "prettier --write 'src/**/*.{js,ts,cjs,mjs}' 'tests/**/*.{js,ts,cjs,mjs}'" }, "repository": "https://github.com/cheqd/sdk.git", "keywords": [ @@ -84,6 +85,7 @@ "cross-env": "^7.0.3", "jest": "^29.7.0", "long": "^4.0.0", + "prettier": "^3.0.3", "semantic-release": "^22.0.5", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", diff --git a/src/index.ts b/src/index.ts index 8818aa9b..8d9bce44 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,146 +1,140 @@ -import { - OfflineSigner, - Registry -} from '@cosmjs/proto-signing' -import { - DIDModule, - MinimalImportableDIDModule, - DidExtension -} from './modules/did.js'; -import { - MinimalImportableResourceModule, - ResourceModule, - ResourceExtension -} from './modules/resource.js'; +import { OfflineSigner, Registry } from '@cosmjs/proto-signing'; +import { DIDModule, MinimalImportableDIDModule, DidExtension } from './modules/did.js'; +import { MinimalImportableResourceModule, ResourceModule, ResourceExtension } from './modules/resource.js'; import { AbstractCheqdSDKModule, applyMixins, instantiateCheqdSDKModule, instantiateCheqdSDKModuleRegistryTypes, - instantiateCheqdSDKModuleQuerierExtensionSetup + instantiateCheqdSDKModuleQuerierExtensionSetup, } from './modules/_.js'; -import { createDefaultCheqdRegistry } from './registry.js' -import { CheqdSigningStargateClient } from './signer.js' -import { - CheqdNetwork, - IContext, - IModuleMethodMap -} from './types.js'; -import { - GasPrice, - QueryClient -} from '@cosmjs/stargate' -import { CheqdQuerier } from './querier.js' -import { Tendermint34Client } from '@cosmjs/tendermint-rpc' +import { createDefaultCheqdRegistry } from './registry.js'; +import { CheqdSigningStargateClient } from './signer.js'; +import { CheqdNetwork, IContext, IModuleMethodMap } from './types.js'; +import { GasPrice, QueryClient } from '@cosmjs/stargate'; +import { CheqdQuerier } from './querier.js'; +import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; export interface ICheqdSDKOptions { - modules: AbstractCheqdSDKModule[] - querierExtensions?: Record[] - rpcUrl: string - network?: CheqdNetwork - gasPrice?: GasPrice - authorizedMethods?: string[] - readonly wallet: OfflineSigner + modules: AbstractCheqdSDKModule[]; + querierExtensions?: Record[]; + rpcUrl: string; + network?: CheqdNetwork; + gasPrice?: GasPrice; + authorizedMethods?: string[]; + readonly wallet: OfflineSigner; } -export type DefaultCheqdSDKModules = MinimalImportableDIDModule & MinimalImportableResourceModule +export type DefaultCheqdSDKModules = MinimalImportableDIDModule & MinimalImportableResourceModule; export interface CheqdSDK extends DefaultCheqdSDKModules {} export class CheqdSDK { - methods: IModuleMethodMap - signer: CheqdSigningStargateClient - querier: CheqdQuerier & DidExtension & ResourceExtension - options: ICheqdSDKOptions - private protectedMethods: string[] = ['constructor', 'build', 'loadModules', 'loadRegistry'] + methods: IModuleMethodMap; + signer: CheqdSigningStargateClient; + querier: CheqdQuerier & DidExtension & ResourceExtension; + options: ICheqdSDKOptions; + private protectedMethods: string[] = ['constructor', 'build', 'loadModules', 'loadRegistry']; constructor(options: ICheqdSDKOptions) { if (!options?.wallet) { - throw new Error('No wallet provided') + throw new Error('No wallet provided'); } this.options = { authorizedMethods: [], network: CheqdNetwork.Testnet, - ...options - } + ...options, + }; - this.methods = {} - this.signer = new CheqdSigningStargateClient(undefined, this.options.wallet, {}) - this.querier = new QueryClient({} as unknown as Tendermint34Client) + this.methods = {}; + this.signer = new CheqdSigningStargateClient(undefined, this.options.wallet, {}); + this.querier = new QueryClient({} as unknown as Tendermint34Client); } async execute

(method: string, ...params: P[]): Promise { if (!Object.keys(this.methods).includes(method)) { - throw new Error(`Method ${method} is not authorized`) + throw new Error(`Method ${method} is not authorized`); } - return await this.methods[method](...params, { sdk: this } as IContext) + return await this.methods[method](...params, { sdk: this } as IContext); } private async loadModules(modules: AbstractCheqdSDKModule[]): Promise { - this.options.modules = this.options.modules.map((module: any) => instantiateCheqdSDKModule(module, this.signer, this.querier, { sdk: this } as IContext) as unknown as AbstractCheqdSDKModule) - - const methods = applyMixins(this, modules) - this.methods = { ...this.methods, ...filterUnauthorizedMethods(methods, this.options.authorizedMethods || [], this.protectedMethods) } + this.options.modules = this.options.modules.map( + (module: any) => + instantiateCheqdSDKModule(module, this.signer, this.querier, { + sdk: this, + } as IContext) as unknown as AbstractCheqdSDKModule + ); + + const methods = applyMixins(this, modules); + this.methods = { + ...this.methods, + ...filterUnauthorizedMethods(methods, this.options.authorizedMethods || [], this.protectedMethods), + }; for (const method of Object.keys(this.methods)) { // @ts-ignore this[method] = async (...params: any[]) => { - return await this.execute(method, ...params) - } + return await this.execute(method, ...params); + }; } - return this + return this; } - private loadRegistry(): Registry { - const registryTypes = this.options.modules.map((module: any) => instantiateCheqdSDKModuleRegistryTypes(module)).reduce((acc, types) => { - return [...acc, ...types] - }) - return createDefaultCheqdRegistry(registryTypes) - } + private loadRegistry(): Registry { + const registryTypes = this.options.modules + .map((module: any) => instantiateCheqdSDKModuleRegistryTypes(module)) + .reduce((acc, types) => { + return [...acc, ...types]; + }); + return createDefaultCheqdRegistry(registryTypes); + } private async loadQuerierExtensions(): Promise { - const querierExtensions = this.options.modules.map((module: any) => instantiateCheqdSDKModuleQuerierExtensionSetup(module)) - const querier = await CheqdQuerier.connectWithExtensions(this.options.rpcUrl, ...querierExtensions) - return querier + const querierExtensions = this.options.modules.map((module: any) => + instantiateCheqdSDKModuleQuerierExtensionSetup(module) + ); + const querier = await CheqdQuerier.connectWithExtensions(this.options.rpcUrl, ...querierExtensions); + return querier; } async build(): Promise { - const registry = this.loadRegistry() - - this.querier = await this.loadQuerierExtensions() - this.signer = await CheqdSigningStargateClient.connectWithSigner( - this.options.rpcUrl, - this.options.wallet, - { - registry, - gasPrice: this.options?.gasPrice, - } - ) - - return await this.loadModules(this.options.modules) + const registry = this.loadRegistry(); + + this.querier = await this.loadQuerierExtensions(); + this.signer = await CheqdSigningStargateClient.connectWithSigner(this.options.rpcUrl, this.options.wallet, { + registry, + gasPrice: this.options?.gasPrice, + }); + + return await this.loadModules(this.options.modules); } } -export function filterUnauthorizedMethods(methods: IModuleMethodMap, authorizedMethods: string[], protectedMethods: string[]): IModuleMethodMap { - let _methods = Object.keys(methods) +export function filterUnauthorizedMethods( + methods: IModuleMethodMap, + authorizedMethods: string[], + protectedMethods: string[] +): IModuleMethodMap { + let _methods = Object.keys(methods); if (authorizedMethods.length === 0) return _methods - .filter(method => !protectedMethods.includes(method)) - .reduce((acc, method) => ({ ...acc, [method]: methods[method] }), {}) + .filter((method) => !protectedMethods.includes(method)) + .reduce((acc, method) => ({ ...acc, [method]: methods[method] }), {}); return _methods - .filter(method => authorizedMethods.includes(method) && !protectedMethods.includes(method)) - .reduce((acc, method) => ({ ...acc, [method]: methods[method] }), {}) + .filter((method) => authorizedMethods.includes(method) && !protectedMethods.includes(method)) + .reduce((acc, method) => ({ ...acc, [method]: methods[method] }), {}); } export async function createCheqdSDK(options: ICheqdSDKOptions): Promise { - return await (new CheqdSDK(options)).build() + return await new CheqdSDK(options).build(); } -export { DIDModule, ResourceModule } -export { AbstractCheqdSDKModule, applyMixins } from './modules/_.js' +export { DIDModule, ResourceModule }; +export { AbstractCheqdSDKModule, applyMixins } from './modules/_.js'; export { DidExtension, MinimalImportableDIDModule, @@ -163,7 +157,7 @@ export { isMsgCreateDidDocEncodeObject, isMsgUpdateDidDocEncodeObject, isMsgDeactivateDidDocEncodeObject, -} from './modules/did.js' +} from './modules/did.js'; export { ResourceExtension, MinimalImportableResourceModule, @@ -173,14 +167,14 @@ export { typeUrlMsgCreateResourceResponse, setupResourceExtension, isMsgCreateResourceEncodeObject, -} from './modules/resource.js' -export * from './signer.js' -export * from './querier.js' -export * from './registry.js' -export * from './types.js' +} from './modules/resource.js'; +export * from './signer.js'; +export * from './querier.js'; +export * from './registry.js'; +export * from './types.js'; export { TImportableEd25519Key, - createKeyPairRaw, + createKeyPairRaw, createKeyPairBase64, createKeyPairHex, createVerificationKeys, @@ -189,8 +183,8 @@ export { createSignInputsFromImportableEd25519Key, validateSpecCompliantPayload, isEqualKeyValuePair, - createCosmosPayerWallet, + createCosmosPayerWallet, getCosmosAccount, checkBalance, - toMultibaseRaw -} from './utils.js' + toMultibaseRaw, +} from './utils.js'; diff --git a/src/modules/_.ts b/src/modules/_.ts index 21f55b8c..a2697345 100644 --- a/src/modules/_.ts +++ b/src/modules/_.ts @@ -1,61 +1,77 @@ -import { GeneratedType } from "@cosmjs/proto-signing" -import { QueryClient } from "@cosmjs/stargate" -import { CheqdSigningStargateClient } from '../signer.js' -import { - IModuleMethodMap, - QueryExtensionSetup -} from '../types.js'; -import { CheqdQuerier } from "../querier.js"; +import { GeneratedType } from '@cosmjs/proto-signing'; +import { QueryClient } from '@cosmjs/stargate'; +import { CheqdSigningStargateClient } from '../signer.js'; +import { IModuleMethodMap, QueryExtensionSetup } from '../types.js'; +import { CheqdQuerier } from '../querier.js'; export abstract class AbstractCheqdSDKModule { - _signer: CheqdSigningStargateClient - methods: IModuleMethodMap = {} - querier: CheqdQuerier - readonly _protectedMethods: string[] = ['constructor', 'getRegistryTypes', 'getQuerierExtensionSetup'] - static readonly registryTypes: Iterable<[string, GeneratedType]> = [] - static readonly querierExtensionSetup: QueryExtensionSetup = (base: QueryClient) => ({}) + _signer: CheqdSigningStargateClient; + methods: IModuleMethodMap = {}; + querier: CheqdQuerier; + readonly _protectedMethods: string[] = ['constructor', 'getRegistryTypes', 'getQuerierExtensionSetup']; + static readonly registryTypes: Iterable<[string, GeneratedType]> = []; + static readonly querierExtensionSetup: QueryExtensionSetup = (base: QueryClient) => ({}); constructor(signer: CheqdSigningStargateClient, querier: CheqdQuerier) { if (!signer) { - throw new Error("signer is required") + throw new Error('signer is required'); } if (!querier) { - throw new Error("querier is required") + throw new Error('querier is required'); } - this._signer = signer - this.querier = querier + this._signer = signer; + this.querier = querier; } - abstract getRegistryTypes(): Iterable<[string, GeneratedType]> + abstract getRegistryTypes(): Iterable<[string, GeneratedType]>; } -type ProtectedMethods = T[K] extends string[] ? T[K][number] : T[K] +type ProtectedMethods = T[K] extends string[] + ? T[K][number] + : T[K]; -export type MinimalImportableCheqdSDKModule = Omit +export type MinimalImportableCheqdSDKModule = Omit< + T, + | '_signer' + | '_protectedMethods' + | 'registryTypes' + | 'querierExtensionSetup' + | 'getRegistryTypes' + | 'getQuerierExtensionSetup' +>; -export function instantiateCheqdSDKModule T>(module: T, ...args: ConstructorParameters): T { - return new module(...args) +export function instantiateCheqdSDKModule T>( + module: T, + ...args: ConstructorParameters +): T { + return new module(...args); } export function instantiateCheqdSDKModuleRegistryTypes(module: any): Iterable<[string, GeneratedType]> { - return module.registryTypes ?? [] + return module.registryTypes ?? []; } export function instantiateCheqdSDKModuleQuerierExtensionSetup(module: any): QueryExtensionSetup { - return module.querierExtensionSetup ?? {} + return module.querierExtensionSetup ?? {}; } export function applyMixins(derivedCtor: any, constructors: any[]): IModuleMethodMap { - let methods: IModuleMethodMap = {} + let methods: IModuleMethodMap = {}; constructors.forEach((baseCtor) => { Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => { - const property = baseCtor.prototype[name] - if (typeof property !== 'function' || derivedCtor.hasOwnProperty(name) || derivedCtor?.protectedMethods.includes(name) || baseCtor.prototype?._protectedMethods?.includes(name)) return + const property = baseCtor.prototype[name]; + if ( + typeof property !== 'function' || + derivedCtor.hasOwnProperty(name) || + derivedCtor?.protectedMethods.includes(name) || + baseCtor.prototype?._protectedMethods?.includes(name) + ) + return; - methods = { ...methods, [name]: property } + methods = { ...methods, [name]: property }; }); }); - return methods + return methods; } diff --git a/src/modules/did.ts b/src/modules/did.ts index 517ae090..6d8dc50c 100644 --- a/src/modules/did.ts +++ b/src/modules/did.ts @@ -1,14 +1,6 @@ -import { - createPagination, - createProtobufRpcClient, - DeliverTxResponse, - QueryClient -} from "@cosmjs/stargate" -import { - AbstractCheqdSDKModule, - MinimalImportableCheqdSDKModule -} from './_.js'; -import { CheqdSigningStargateClient } from "../signer.js" +import { createPagination, createProtobufRpcClient, DeliverTxResponse, QueryClient } from '@cosmjs/stargate'; +import { AbstractCheqdSDKModule, MinimalImportableCheqdSDKModule } from './_.js'; +import { CheqdSigningStargateClient } from '../signer.js'; import { DIDDocument, DidStdFee, @@ -17,9 +9,9 @@ import { QueryExtensionSetup, SpecValidationResult, VerificationMethods, - DIDDocumentWithMetadata + DIDDocumentWithMetadata, } from '../types.js'; -import { +import { MsgCreateDidDoc, MsgCreateDidDocPayload, MsgCreateDidDocResponse, @@ -37,165 +29,169 @@ import { QueryAllDidDocVersionsMetadataResponse, DidDocWithMetadata, DidDoc, - Metadata -} from "@cheqd/ts-proto/cheqd/did/v2/index.js" -import { - EncodeObject, - GeneratedType -} from "@cosmjs/proto-signing" -import { v4 } from "uuid" -import { assert } from "@cosmjs/utils"; -import { PageRequest } from "@cheqd/ts-proto/cosmos/base/query/v1beta1/pagination.js"; -import { CheqdQuerier } from "../querier.js"; -import { DIDDocumentMetadata } from "did-resolver"; + Metadata, +} from '@cheqd/ts-proto/cheqd/did/v2/index.js'; +import { EncodeObject, GeneratedType } from '@cosmjs/proto-signing'; +import { v4 } from 'uuid'; +import { assert } from '@cosmjs/utils'; +import { PageRequest } from '@cheqd/ts-proto/cosmos/base/query/v1beta1/pagination.js'; +import { CheqdQuerier } from '../querier.js'; +import { DIDDocumentMetadata } from 'did-resolver'; -export const defaultDidExtensionKey = "did" as const +export const defaultDidExtensionKey = 'did' as const; export const contexts = { - W3CDIDv1: "https://www.w3.org/ns/did/v1", - W3CSuiteEd255192020: "https://w3id.org/security/suites/ed25519-2020/v1", - W3CSuiteEd255192018: "https://w3id.org/security/suites/ed25519-2018/v1", - W3CSuiteJws2020: "https://w3id.org/security/suites/jws-2020/v1", -} as const + W3CDIDv1: 'https://www.w3.org/ns/did/v1', + W3CSuiteEd255192020: 'https://w3id.org/security/suites/ed25519-2020/v1', + W3CSuiteEd255192018: 'https://w3id.org/security/suites/ed25519-2018/v1', + W3CSuiteJws2020: 'https://w3id.org/security/suites/jws-2020/v1', +} as const; export const protobufLiterals = { - MsgCreateDidDoc: "MsgCreateDidDoc", - MsgCreateDidDocResponse: "MsgCreateDidDocResponse", - MsgUpdateDidDoc: "MsgUpdateDidDoc", - MsgUpdateDidDocResponse: "MsgUpdateDidDocResponse", - MsgDeactivateDidDoc: "MsgDeactivateDidDoc", - MsgDeactivateDidDocResponse: "MsgDeactivateDidDocResponse", -} as const -export const typeUrlMsgCreateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgCreateDidDoc}` -export const typeUrlMsgCreateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgCreateDidDocResponse}` -export const typeUrlMsgUpdateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgUpdateDidDoc}` -export const typeUrlMsgUpdateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgUpdateDidDocResponse}` -export const typeUrlMsgDeactivateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgDeactivateDidDoc}` -export const typeUrlMsgDeactivateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgDeactivateDidDocResponse}` + MsgCreateDidDoc: 'MsgCreateDidDoc', + MsgCreateDidDocResponse: 'MsgCreateDidDocResponse', + MsgUpdateDidDoc: 'MsgUpdateDidDoc', + MsgUpdateDidDocResponse: 'MsgUpdateDidDocResponse', + MsgDeactivateDidDoc: 'MsgDeactivateDidDoc', + MsgDeactivateDidDocResponse: 'MsgDeactivateDidDocResponse', +} as const; +export const typeUrlMsgCreateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgCreateDidDoc}`; +export const typeUrlMsgCreateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgCreateDidDocResponse}`; +export const typeUrlMsgUpdateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgUpdateDidDoc}`; +export const typeUrlMsgUpdateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgUpdateDidDocResponse}`; +export const typeUrlMsgDeactivateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgDeactivateDidDoc}`; +export const typeUrlMsgDeactivateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgDeactivateDidDocResponse}`; export interface MsgCreateDidDocEncodeObject extends EncodeObject { - readonly typeUrl: typeof typeUrlMsgCreateDidDoc, - readonly value: Partial + readonly typeUrl: typeof typeUrlMsgCreateDidDoc; + readonly value: Partial; } export function isMsgCreateDidDocEncodeObject(obj: EncodeObject): obj is MsgCreateDidDocEncodeObject { - return obj.typeUrl === typeUrlMsgCreateDidDoc + return obj.typeUrl === typeUrlMsgCreateDidDoc; } export function isMsgUpdateDidDocEncodeObject(obj: EncodeObject): obj is MsgUpdateDidDocEncodeObject { - return obj.typeUrl === typeUrlMsgUpdateDidDoc + return obj.typeUrl === typeUrlMsgUpdateDidDoc; } export function isMsgDeactivateDidDocEncodeObject(obj: EncodeObject): obj is MsgDeactivateDidDocEncodeObject { - return obj.typeUrl === typeUrlMsgDeactivateDidDoc + return obj.typeUrl === typeUrlMsgDeactivateDidDoc; } export interface MsgCreateDidDocResponseEncodeObject extends EncodeObject { - readonly typeUrl: typeof typeUrlMsgCreateDidDocResponse, - readonly value: Partial + readonly typeUrl: typeof typeUrlMsgCreateDidDocResponse; + readonly value: Partial; } export function MsgCreateDidDocResponseEncodeObject(obj: EncodeObject): obj is MsgCreateDidDocResponseEncodeObject { - return obj.typeUrl === typeUrlMsgCreateDidDocResponse + return obj.typeUrl === typeUrlMsgCreateDidDocResponse; } export interface MsgUpdateDidDocEncodeObject extends EncodeObject { - readonly typeUrl: typeof typeUrlMsgUpdateDidDoc, - readonly value: Partial + readonly typeUrl: typeof typeUrlMsgUpdateDidDoc; + readonly value: Partial; } export function MsgUpdateDidDocEncodeObject(obj: EncodeObject): obj is MsgUpdateDidDocEncodeObject { - return obj.typeUrl === typeUrlMsgUpdateDidDoc + return obj.typeUrl === typeUrlMsgUpdateDidDoc; } export interface MsgUpdateDidDocResponseEncodeObject extends EncodeObject { - readonly typeUrl: typeof typeUrlMsgUpdateDidDocResponse, - readonly value: Partial + readonly typeUrl: typeof typeUrlMsgUpdateDidDocResponse; + readonly value: Partial; } export function MsgUpdateDidDocResponseEncodeObject(obj: EncodeObject): obj is MsgUpdateDidDocResponseEncodeObject { - return obj.typeUrl === typeUrlMsgUpdateDidDocResponse + return obj.typeUrl === typeUrlMsgUpdateDidDocResponse; } export interface MsgDeactivateDidDocEncodeObject extends EncodeObject { - readonly typeUrl: typeof typeUrlMsgDeactivateDidDoc, - readonly value: Partial + readonly typeUrl: typeof typeUrlMsgDeactivateDidDoc; + readonly value: Partial; } export function MsgDeactivateDidDocEncodeObject(obj: EncodeObject): obj is MsgUpdateDidDocEncodeObject { - return obj.typeUrl === typeUrlMsgDeactivateDidDoc + return obj.typeUrl === typeUrlMsgDeactivateDidDoc; } export interface MsgDeactivateDidDocResponseEncodeObject extends EncodeObject { - readonly typeUrl: typeof typeUrlMsgDeactivateDidDocResponse, - readonly value: Partial + readonly typeUrl: typeof typeUrlMsgDeactivateDidDocResponse; + readonly value: Partial; } -export function MsgDeactiveDidDocResponseEncodeObject(obj: EncodeObject): obj is MsgDeactivateDidDocResponseEncodeObject { - return obj.typeUrl === typeUrlMsgUpdateDidDocResponse +export function MsgDeactiveDidDocResponseEncodeObject( + obj: EncodeObject +): obj is MsgDeactivateDidDocResponseEncodeObject { + return obj.typeUrl === typeUrlMsgUpdateDidDocResponse; } - -export type MinimalImportableDIDModule = MinimalImportableCheqdSDKModule +export type MinimalImportableDIDModule = MinimalImportableCheqdSDKModule; export type DidExtension = { readonly [defaultDidExtensionKey]: { - readonly didDoc: (id: string) => Promise - readonly didDocVersion: (id: string, versionId: string) => Promise - readonly allDidDocVersionsMetadata: (id: string, paginationKey?: Uint8Array) => Promise - } -} + readonly didDoc: (id: string) => Promise; + readonly didDocVersion: (id: string, versionId: string) => Promise; + readonly allDidDocVersionsMetadata: ( + id: string, + paginationKey?: Uint8Array + ) => Promise; + }; +}; export const setupDidExtension = (base: QueryClient): DidExtension => { - const rpc = createProtobufRpcClient(base) + const rpc = createProtobufRpcClient(base); - const queryService = new QueryClientImpl(rpc) + const queryService = new QueryClientImpl(rpc); return { [defaultDidExtensionKey]: { didDoc: async (id: string) => { - const { value } = await queryService.DidDoc({ id }) - assert(value) - return value + const { value } = await queryService.DidDoc({ id }); + assert(value); + return value; }, didDocVersion: async (id: string, versionId: string) => { - const { value } = await queryService.DidDocVersion({ id, version: versionId }) - assert(value) - return value + const { value } = await queryService.DidDocVersion({ id, version: versionId }); + assert(value); + return value; }, allDidDocVersionsMetadata: async (id: string, paginationKey?: Uint8Array) => { - const response = await queryService.AllDidDocVersionsMetadata({ id, pagination: createPagination(paginationKey) as PageRequest | undefined }) - return response - } - } - } as DidExtension -} + const response = await queryService.AllDidDocVersionsMetadata({ + id, + pagination: createPagination(paginationKey) as PageRequest | undefined, + }); + return response; + }, + }, + } as DidExtension; +}; export class DIDModule extends AbstractCheqdSDKModule { static readonly registryTypes: Iterable<[string, GeneratedType]> = [ - [typeUrlMsgCreateDidDoc, MsgCreateDidDoc], - [typeUrlMsgCreateDidDocResponse, MsgCreateDidDocResponse], - [typeUrlMsgUpdateDidDoc, MsgUpdateDidDoc], - [typeUrlMsgUpdateDidDocResponse, MsgUpdateDidDocResponse], + [typeUrlMsgCreateDidDoc, MsgCreateDidDoc], + [typeUrlMsgCreateDidDocResponse, MsgCreateDidDocResponse], + [typeUrlMsgUpdateDidDoc, MsgUpdateDidDoc], + [typeUrlMsgUpdateDidDocResponse, MsgUpdateDidDocResponse], [typeUrlMsgDeactivateDidDoc, MsgDeactivateDidDoc], [typeUrlMsgDeactivateDidDocResponse, MsgDeactivateDidDocResponse], - ] + ]; - static readonly baseMinimalDenom = 'ncheq' as const + static readonly baseMinimalDenom = 'ncheq' as const; static readonly fees = { DefaultCreateDidDocFee: { amount: '50000000000', denom: DIDModule.baseMinimalDenom } as const, DefaultUpdateDidDocFee: { amount: '25000000000', denom: DIDModule.baseMinimalDenom } as const, DefaultDeactivateDidDocFee: { amount: '10000000000', denom: DIDModule.baseMinimalDenom } as const, - } as const + } as const; - static readonly querierExtensionSetup: QueryExtensionSetup = setupDidExtension + static readonly querierExtensionSetup: QueryExtensionSetup = setupDidExtension; - querier: CheqdQuerier & DidExtension + querier: CheqdQuerier & DidExtension; constructor(signer: CheqdSigningStargateClient, querier: CheqdQuerier & DidExtension) { - super(signer, querier) - this.querier = querier + super(signer, querier); + this.querier = querier; this.methods = { createDidDocTx: this.createDidDocTx.bind(this), updateDidDocTx: this.updateDidDocTx.bind(this), @@ -203,30 +199,39 @@ export class DIDModule extends AbstractCheqdSDKModule { queryDidDoc: this.queryDidDoc.bind(this), queryDidDocVersion: this.queryDidDocVersion.bind(this), queryAllDidDocVersionsMetadata: this.queryAllDidDocVersionsMetadata.bind(this), - } + }; } - public getRegistryTypes(): Iterable<[string, GeneratedType]> { - return DIDModule.registryTypes - } + public getRegistryTypes(): Iterable<[string, GeneratedType]> { + return DIDModule.registryTypes; + } public getQuerierExtensionSetup(): QueryExtensionSetup { - return DIDModule.querierExtensionSetup + return DIDModule.querierExtensionSetup; } - async createDidDocTx(signInputs: ISignInputs[] | SignInfo[], didPayload: DIDDocument, address: string, fee?: DidStdFee | 'auto' | number, memo?: string, versionId?: string, context?: IContext): Promise { + async createDidDocTx( + signInputs: ISignInputs[] | SignInfo[], + didPayload: DIDDocument, + address: string, + fee?: DidStdFee | 'auto' | number, + memo?: string, + versionId?: string, + context?: IContext + ): Promise { if (!this._signer) { - this._signer = context!.sdk!.signer + this._signer = context!.sdk!.signer; } if (!versionId || versionId === '') { - versionId = v4() + versionId = v4(); } - const { valid, error, protobufVerificationMethod, protobufService } = await DIDModule.validateSpecCompliantPayload(didPayload) + const { valid, error, protobufVerificationMethod, protobufService } = + await DIDModule.validateSpecCompliantPayload(didPayload); if (!valid) { - throw new Error(`DID payload is not spec compliant: ${error}`) + throw new Error(`DID payload is not spec compliant: ${error}`); } const payload = MsgCreateDidDocPayload.fromPartial({ @@ -241,55 +246,59 @@ export class DIDModule extends AbstractCheqdSDKModule { keyAgreement: didPayload.keyAgreement, service: protobufService, alsoKnownAs: didPayload.alsoKnownAs, - versionId: versionId - }) + versionId: versionId, + }); - let signatures: SignInfo[] - if(ISignInputs.isSignInput(signInputs)) { - signatures = await this._signer.signcreateDidDocTx(signInputs, payload) + let signatures: SignInfo[]; + if (ISignInputs.isSignInput(signInputs)) { + signatures = await this._signer.signcreateDidDocTx(signInputs, payload); } else { - signatures = signInputs + signatures = signInputs; } const value: MsgCreateDidDoc = { payload, - signatures - } + signatures, + }; const createDidMsg: MsgCreateDidDocEncodeObject = { typeUrl: typeUrlMsgCreateDidDoc, - value - } + value, + }; if (address === '') { - address = (await context!.sdk!.options.wallet.getAccounts())[0].address + address = (await context!.sdk!.options.wallet.getAccounts())[0].address; } if (!fee) { - fee = await DIDModule.generateCreateDidDocFees(address) + fee = await DIDModule.generateCreateDidDocFees(address); } - return this._signer.signAndBroadcast( - address, - [createDidMsg], - fee!, - memo - ) + return this._signer.signAndBroadcast(address, [createDidMsg], fee!, memo); } - async updateDidDocTx(signInputs: ISignInputs[] | SignInfo[], didPayload: DIDDocument, address: string, fee?: DidStdFee | 'auto' | number, memo?: string, versionId?: string, context?: IContext): Promise { + async updateDidDocTx( + signInputs: ISignInputs[] | SignInfo[], + didPayload: DIDDocument, + address: string, + fee?: DidStdFee | 'auto' | number, + memo?: string, + versionId?: string, + context?: IContext + ): Promise { if (!this._signer) { - this._signer = context!.sdk!.signer + this._signer = context!.sdk!.signer; } if (!versionId || versionId === '') { - versionId = v4() + versionId = v4(); } - const { valid, error, protobufVerificationMethod, protobufService } = await DIDModule.validateSpecCompliantPayload(didPayload) + const { valid, error, protobufVerificationMethod, protobufService } = + await DIDModule.validateSpecCompliantPayload(didPayload); if (!valid) { - throw new Error(`DID payload is not spec compliant: ${error}`) + throw new Error(`DID payload is not spec compliant: ${error}`); } const payload = MsgUpdateDidDocPayload.fromPartial({ @@ -304,232 +313,242 @@ export class DIDModule extends AbstractCheqdSDKModule { keyAgreement: didPayload.keyAgreement, service: protobufService, alsoKnownAs: didPayload.alsoKnownAs, - versionId: versionId - }) - let signatures: SignInfo[] - if(ISignInputs.isSignInput(signInputs)) { - signatures = await this._signer.signupdateDidDocTx(signInputs, payload) + versionId: versionId, + }); + let signatures: SignInfo[]; + if (ISignInputs.isSignInput(signInputs)) { + signatures = await this._signer.signupdateDidDocTx(signInputs, payload); } else { - signatures = signInputs + signatures = signInputs; } const value: MsgUpdateDidDoc = { payload, - signatures - } + signatures, + }; const updateDidMsg: MsgUpdateDidDocEncodeObject = { typeUrl: typeUrlMsgUpdateDidDoc, - value - } + value, + }; if (address === '') { - address = (await context!.sdk!.options.wallet.getAccounts())[0].address + address = (await context!.sdk!.options.wallet.getAccounts())[0].address; } if (!fee) { - fee = await DIDModule.generateUpdateDidDocFees(address) + fee = await DIDModule.generateUpdateDidDocFees(address); } - return this._signer.signAndBroadcast( - address, - [updateDidMsg], - fee!, - memo - ) + return this._signer.signAndBroadcast(address, [updateDidMsg], fee!, memo); } - async deactivateDidDocTx(signInputs: ISignInputs[] | SignInfo[], didPayload: DIDDocument, address: string, fee?: DidStdFee | 'auto' | number, memo?: string, versionId?: string, context?: IContext): Promise { + async deactivateDidDocTx( + signInputs: ISignInputs[] | SignInfo[], + didPayload: DIDDocument, + address: string, + fee?: DidStdFee | 'auto' | number, + memo?: string, + versionId?: string, + context?: IContext + ): Promise { if (!this._signer) { - this._signer = context!.sdk!.signer + this._signer = context!.sdk!.signer; } if (!versionId || versionId === '') { - versionId = v4() + versionId = v4(); } - const { valid, error, protobufVerificationMethod } = await DIDModule.validateSpecCompliantPayload(didPayload) + const { valid, error, protobufVerificationMethod } = await DIDModule.validateSpecCompliantPayload(didPayload); if (!valid) { - throw new Error(`DID payload is not spec compliant: ${error}`) + throw new Error(`DID payload is not spec compliant: ${error}`); } const payload = MsgDeactivateDidDocPayload.fromPartial({ id: didPayload.id, - versionId: versionId - }) + versionId: versionId, + }); - let signatures: SignInfo[] - if(ISignInputs.isSignInput(signInputs)) { - signatures = await this._signer.signdeactivateDidDocTx(signInputs, payload, protobufVerificationMethod!) + let signatures: SignInfo[]; + if (ISignInputs.isSignInput(signInputs)) { + signatures = await this._signer.signdeactivateDidDocTx(signInputs, payload, protobufVerificationMethod!); } else { - signatures = signInputs + signatures = signInputs; } const value: MsgDeactivateDidDoc = { payload, - signatures - } + signatures, + }; const deactivateDidMsg: MsgDeactivateDidDocEncodeObject = { typeUrl: typeUrlMsgDeactivateDidDoc, - value - } + value, + }; if (address === '') { - address = (await context!.sdk!.options.wallet.getAccounts())[0].address + address = (await context!.sdk!.options.wallet.getAccounts())[0].address; } if (!fee) { - fee = await DIDModule.generateDeactivateDidDocFees(address) + fee = await DIDModule.generateDeactivateDidDocFees(address); } - return this._signer.signAndBroadcast( - address, - [deactivateDidMsg], - fee!, - memo - ) + return this._signer.signAndBroadcast(address, [deactivateDidMsg], fee!, memo); } async queryDidDoc(id: string, context?: IContext): Promise { if (!this.querier) { - this.querier = context!.sdk!.querier + this.querier = context!.sdk!.querier; } - const { didDoc, metadata } = await this.querier[defaultDidExtensionKey].didDoc(id) + const { didDoc, metadata } = await this.querier[defaultDidExtensionKey].didDoc(id); return { didDocument: await DIDModule.toSpecCompliantPayload(didDoc!), - didDocumentMetadata: await DIDModule.toSpecCompliantMetadata(metadata!) - } as DIDDocumentWithMetadata + didDocumentMetadata: await DIDModule.toSpecCompliantMetadata(metadata!), + } as DIDDocumentWithMetadata; } async queryDidDocVersion(id: string, versionId: string, context?: IContext): Promise { if (!this.querier) { - this.querier = context!.sdk!.querier + this.querier = context!.sdk!.querier; } - const { didDoc, metadata } = await this.querier[defaultDidExtensionKey].didDocVersion(id, versionId) + const { didDoc, metadata } = await this.querier[defaultDidExtensionKey].didDocVersion(id, versionId); return { didDocument: await DIDModule.toSpecCompliantPayload(didDoc!), - didDocumentMetadata: await DIDModule.toSpecCompliantMetadata(metadata!) - } as DIDDocumentWithMetadata + didDocumentMetadata: await DIDModule.toSpecCompliantMetadata(metadata!), + } as DIDDocumentWithMetadata; } - async queryAllDidDocVersionsMetadata(id: string, context?: IContext): Promise<{ didDocumentVersionsMetadata: DIDDocumentMetadata[], pagination: QueryAllDidDocVersionsMetadataResponse['pagination']}> { + async queryAllDidDocVersionsMetadata( + id: string, + context?: IContext + ): Promise<{ + didDocumentVersionsMetadata: DIDDocumentMetadata[]; + pagination: QueryAllDidDocVersionsMetadataResponse['pagination']; + }> { if (!this.querier) { - this.querier = context!.sdk!.querier + this.querier = context!.sdk!.querier; } - const { versions, pagination } = await this.querier[defaultDidExtensionKey].allDidDocVersionsMetadata(id) + const { versions, pagination } = await this.querier[defaultDidExtensionKey].allDidDocVersionsMetadata(id); return { - didDocumentVersionsMetadata: await Promise.all(versions.map(async (m) => await DIDModule.toSpecCompliantMetadata(m))), - pagination - } + didDocumentVersionsMetadata: await Promise.all( + versions.map(async (m) => await DIDModule.toSpecCompliantMetadata(m)) + ), + pagination, + }; } static async validateSpecCompliantPayload(didDocument: DIDDocument): Promise { // id is required, validated on both compile and runtime - if (!didDocument?.id) return { valid: false, error: 'id is required' } + if (!didDocument?.id) return { valid: false, error: 'id is required' }; // verificationMethod is required - if (!didDocument?.verificationMethod) return { valid: false, error: 'verificationMethod is required' } + if (!didDocument?.verificationMethod) return { valid: false, error: 'verificationMethod is required' }; // verificationMethod must be an array - if (!Array.isArray(didDocument?.verificationMethod)) return { valid: false, error: 'verificationMethod must be an array' } + if (!Array.isArray(didDocument?.verificationMethod)) + return { valid: false, error: 'verificationMethod must be an array' }; // verificationMethod types must be supported const protoVerificationMethod = didDocument.verificationMethod.map((vm) => { switch (vm?.type) { case VerificationMethods.Ed255192020: - if (!vm?.publicKeyMultibase) throw new Error('publicKeyMultibase is required') + if (!vm?.publicKeyMultibase) throw new Error('publicKeyMultibase is required'); return VerificationMethod.fromPartial({ id: vm.id, controller: vm.controller, verificationMethodType: VerificationMethods.Ed255192020, verificationMaterial: vm.publicKeyMultibase, - }) + }); case VerificationMethods.JWK: - if (!vm?.publicKeyJwk) throw new Error('publicKeyJwk is required') + if (!vm?.publicKeyJwk) throw new Error('publicKeyJwk is required'); return VerificationMethod.fromPartial({ id: vm.id, controller: vm.controller, verificationMethodType: VerificationMethods.JWK, verificationMaterial: JSON.stringify(vm.publicKeyJwk), - }) + }); case VerificationMethods.Ed255192018: - if (!vm?.publicKeyBase58) throw new Error('publicKeyBase58 is required') + if (!vm?.publicKeyBase58) throw new Error('publicKeyBase58 is required'); return VerificationMethod.fromPartial({ id: vm.id, controller: vm.controller, verificationMethodType: VerificationMethods.Ed255192018, verificationMaterial: vm.publicKeyBase58, - }) + }); default: - throw new Error('Unsupported verificationMethod type') + throw new Error('Unsupported verificationMethod type'); } - }) + }); const protoService = didDocument?.service?.map((s) => { return Service.fromPartial({ id: s?.id, serviceType: s?.type, serviceEndpoint: s?.serviceEndpoint, - }) - }) + }); + }); - return { valid: true, protobufVerificationMethod: protoVerificationMethod, protobufService: protoService } as SpecValidationResult + return { + valid: true, + protobufVerificationMethod: protoVerificationMethod, + protobufService: protoService, + } as SpecValidationResult; } static async toSpecCompliantPayload(protobufDidDocument: DidDoc): Promise { const verificationMethod = protobufDidDocument.verificationMethod.map((vm) => { switch (vm.verificationMethodType) { case VerificationMethods.Ed255192020: - if (!protobufDidDocument.context.includes(contexts.W3CSuiteEd255192020)) - protobufDidDocument.context = [...protobufDidDocument.context, contexts.W3CSuiteEd255192020] + if (!protobufDidDocument.context.includes(contexts.W3CSuiteEd255192020)) + protobufDidDocument.context = [...protobufDidDocument.context, contexts.W3CSuiteEd255192020]; return { id: vm.id, type: vm.verificationMethodType, controller: vm.controller, publicKeyMultibase: vm.verificationMaterial, - } + }; case VerificationMethods.JWK: - if (!protobufDidDocument.context.includes(contexts.W3CSuiteJws2020)) - protobufDidDocument.context = [...protobufDidDocument.context, contexts.W3CSuiteJws2020] + if (!protobufDidDocument.context.includes(contexts.W3CSuiteJws2020)) + protobufDidDocument.context = [...protobufDidDocument.context, contexts.W3CSuiteJws2020]; return { id: vm.id, type: vm.verificationMethodType, controller: vm.controller, publicKeyJwk: JSON.parse(vm.verificationMaterial), - } + }; case VerificationMethods.Ed255192018: if (!protobufDidDocument.context.includes(contexts.W3CSuiteEd255192018)) - protobufDidDocument.context = [...protobufDidDocument.context, contexts.W3CSuiteEd255192018] + protobufDidDocument.context = [...protobufDidDocument.context, contexts.W3CSuiteEd255192018]; return { id: vm.id, type: vm.verificationMethodType, controller: vm.controller, publicKeyBase58: vm.verificationMaterial, - } + }; default: - throw new Error('Unsupported verificationMethod type') // should never happen + throw new Error('Unsupported verificationMethod type'); // should never happen } - }) + }); const service = protobufDidDocument.service.map((s) => { return { id: s.id, type: s.serviceType, serviceEndpoint: s.serviceEndpoint, - } - }) + }; + }); - const context = function () { - if (protobufDidDocument.context.includes(contexts.W3CDIDv1)) - return protobufDidDocument.context + const context = (function () { + if (protobufDidDocument.context.includes(contexts.W3CDIDv1)) return protobufDidDocument.context; - return [contexts.W3CDIDv1, ...protobufDidDocument.context] - }() + return [contexts.W3CDIDv1, ...protobufDidDocument.context]; + })(); const specCompliant = { '@context': context, @@ -543,17 +562,17 @@ export class DIDModule extends AbstractCheqdSDKModule { keyAgreement: protobufDidDocument.keyAgreement, service: service, alsoKnownAs: protobufDidDocument.alsoKnownAs, - } as DIDDocument + } as DIDDocument; - if (!protobufDidDocument.authentication?.length) delete specCompliant.authentication - if (!protobufDidDocument.assertionMethod?.length) delete specCompliant.assertionMethod - if (!protobufDidDocument.capabilityInvocation?.length) delete specCompliant.capabilityInvocation - if (!protobufDidDocument.capabilityDelegation?.length) delete specCompliant.capabilityDelegation - if (!protobufDidDocument.keyAgreement?.length) delete specCompliant.keyAgreement - if (!protobufDidDocument.service?.length) delete specCompliant.service - if (!protobufDidDocument.alsoKnownAs?.length) delete specCompliant.alsoKnownAs + if (!protobufDidDocument.authentication?.length) delete specCompliant.authentication; + if (!protobufDidDocument.assertionMethod?.length) delete specCompliant.assertionMethod; + if (!protobufDidDocument.capabilityInvocation?.length) delete specCompliant.capabilityInvocation; + if (!protobufDidDocument.capabilityDelegation?.length) delete specCompliant.capabilityDelegation; + if (!protobufDidDocument.keyAgreement?.length) delete specCompliant.keyAgreement; + if (!protobufDidDocument.service?.length) delete specCompliant.service; + if (!protobufDidDocument.alsoKnownAs?.length) delete specCompliant.alsoKnownAs; - return specCompliant + return specCompliant; } static async toSpecCompliantMetadata(protobufDidDocument: Metadata): Promise { @@ -563,39 +582,33 @@ export class DIDModule extends AbstractCheqdSDKModule { deactivated: protobufDidDocument.deactivated, versionId: protobufDidDocument.versionId, nextVersionId: protobufDidDocument?.nextVersionId, - } + }; } static async generateCreateDidDocFees(feePayer: string, granter?: string): Promise { return { - amount: [ - DIDModule.fees.DefaultCreateDidDocFee - ], + amount: [DIDModule.fees.DefaultCreateDidDocFee], gas: '360000', payer: feePayer, - granter: granter - } as DidStdFee + granter: granter, + } as DidStdFee; } static async generateUpdateDidDocFees(feePayer: string, granter?: string): Promise { return { - amount: [ - DIDModule.fees.DefaultUpdateDidDocFee - ], + amount: [DIDModule.fees.DefaultUpdateDidDocFee], gas: '360000', payer: feePayer, - granter: granter - } as DidStdFee + granter: granter, + } as DidStdFee; } static async generateDeactivateDidDocFees(feePayer: string, granter?: string): Promise { return { - amount: [ - DIDModule.fees.DefaultDeactivateDidDocFee - ], + amount: [DIDModule.fees.DefaultDeactivateDidDocFee], gas: '360000', payer: feePayer, - granter: granter - } as DidStdFee + granter: granter, + } as DidStdFee; } } diff --git a/src/modules/resource.ts b/src/modules/resource.ts index 294924eb..bf91fc3b 100644 --- a/src/modules/resource.ts +++ b/src/modules/resource.ts @@ -1,18 +1,7 @@ -import { - AbstractCheqdSDKModule, - MinimalImportableCheqdSDKModule -} from './_.js'; -import { CheqdSigningStargateClient } from "../signer.js" -import { - EncodeObject, - GeneratedType -} from "@cosmjs/proto-signing" -import { - DidStdFee, - IContext, - ISignInputs, - QueryExtensionSetup -} from '../types.js'; +import { AbstractCheqdSDKModule, MinimalImportableCheqdSDKModule } from './_.js'; +import { CheqdSigningStargateClient } from '../signer.js'; +import { EncodeObject, GeneratedType } from '@cosmjs/proto-signing'; +import { DidStdFee, IContext, ISignInputs, QueryExtensionSetup } from '../types.js'; import { Metadata, MsgCreateResource, @@ -21,231 +10,235 @@ import { QueryClientImpl, QueryCollectionResourcesResponse, ResourceWithMetadata, - protobufPackage -} from "@cheqd/ts-proto/cheqd/resource/v2/index.js" -import { - DeliverTxResponse, - QueryClient, - createPagination, - createProtobufRpcClient -} from "@cosmjs/stargate" -import { SignInfo } from "@cheqd/ts-proto/cheqd/did/v2/index.js"; -import { fileTypeFromBuffer } from "file-type"; + protobufPackage, +} from '@cheqd/ts-proto/cheqd/resource/v2/index.js'; +import { DeliverTxResponse, QueryClient, createPagination, createProtobufRpcClient } from '@cosmjs/stargate'; +import { SignInfo } from '@cheqd/ts-proto/cheqd/did/v2/index.js'; +import { fileTypeFromBuffer } from 'file-type'; import { toString } from 'uint8arrays/to-string'; import { assert } from '@cosmjs/utils'; import { PageRequest } from '@cheqd/ts-proto/cosmos/base/query/v1beta1/pagination.js'; import { CheqdQuerier } from '../querier.js'; import { isJSON } from '../utils.js'; -export const defaultResourceExtensionKey = 'resource' as const +export const defaultResourceExtensionKey = 'resource' as const; export const protobufLiterals = { MsgCreateResource: 'MsgCreateResource', - MsgCreateResourceResponse: 'MsgCreateResourceResponse' -} as const + MsgCreateResourceResponse: 'MsgCreateResourceResponse', +} as const; -export const typeUrlMsgCreateResource = `/${protobufPackage}.${protobufLiterals.MsgCreateResource}` -export const typeUrlMsgCreateResourceResponse = `/${protobufPackage}.${protobufLiterals.MsgCreateResourceResponse}` +export const typeUrlMsgCreateResource = `/${protobufPackage}.${protobufLiterals.MsgCreateResource}`; +export const typeUrlMsgCreateResourceResponse = `/${protobufPackage}.${protobufLiterals.MsgCreateResourceResponse}`; export interface MsgCreateResourceEncodeObject extends EncodeObject { - readonly typeUrl: typeof typeUrlMsgCreateResource, - readonly value: Partial + readonly typeUrl: typeof typeUrlMsgCreateResource; + readonly value: Partial; } export function isMsgCreateResourceEncodeObject(obj: EncodeObject): obj is MsgCreateResourceEncodeObject { - return obj.typeUrl === typeUrlMsgCreateResource + return obj.typeUrl === typeUrlMsgCreateResource; } -export type MinimalImportableResourceModule = MinimalImportableCheqdSDKModule +export type MinimalImportableResourceModule = MinimalImportableCheqdSDKModule; export type ResourceExtension = { readonly [defaultResourceExtensionKey]: { - readonly resource: (collectionId: string, resourceId: string) => Promise - readonly resourceMetadata: (collectionId: string, resourceId: string) => Promise - readonly collectionResources: (collectionId: string, paginationKey?: Uint8Array) => Promise - } -} + readonly resource: (collectionId: string, resourceId: string) => Promise; + readonly resourceMetadata: (collectionId: string, resourceId: string) => Promise; + readonly collectionResources: ( + collectionId: string, + paginationKey?: Uint8Array + ) => Promise; + }; +}; export const setupResourceExtension = (base: QueryClient): ResourceExtension => { - const rpc = createProtobufRpcClient(base) + const rpc = createProtobufRpcClient(base); - const queryService = new QueryClientImpl(rpc) + const queryService = new QueryClientImpl(rpc); return { [defaultResourceExtensionKey]: { resource: async (collectionId: string, resourceId: string) => { - const { resource } = await queryService.Resource({ collectionId, id: resourceId }) - assert(resource) - return resource + const { resource } = await queryService.Resource({ collectionId, id: resourceId }); + assert(resource); + return resource; }, resourceMetadata: async (collectionId: string, resourceId: string) => { - const { resource } = await queryService.ResourceMetadata({ collectionId, id: resourceId }) - assert(resource) - return resource + const { resource } = await queryService.ResourceMetadata({ collectionId, id: resourceId }); + assert(resource); + return resource; }, collectionResources: async (collectionId: string, paginationKey?: Uint8Array) => { - const response = await queryService.CollectionResources({ collectionId, pagination: createPagination(paginationKey) as PageRequest | undefined }) - return response - } - } - } as ResourceExtension -} + const response = await queryService.CollectionResources({ + collectionId, + pagination: createPagination(paginationKey) as PageRequest | undefined, + }); + return response; + }, + }, + } as ResourceExtension; +}; export class ResourceModule extends AbstractCheqdSDKModule { static readonly registryTypes: Iterable<[string, GeneratedType]> = [ [typeUrlMsgCreateResource, MsgCreateResource], - [typeUrlMsgCreateResourceResponse, MsgCreateResourceResponse] - ] + [typeUrlMsgCreateResourceResponse, MsgCreateResourceResponse], + ]; - static readonly baseMinimalDenom = 'ncheq' as const + static readonly baseMinimalDenom = 'ncheq' as const; static readonly fees = { DefaultCreateResourceImageFee: { amount: '10000000000', denom: ResourceModule.baseMinimalDenom } as const, DefaultCreateResourceJsonFee: { amount: '2500000000', denom: ResourceModule.baseMinimalDenom } as const, DefaultCreateResourceDefaultFee: { amount: '5000000000', denom: ResourceModule.baseMinimalDenom } as const, - } as const + } as const; - static readonly querierExtensionSetup: QueryExtensionSetup = setupResourceExtension + static readonly querierExtensionSetup: QueryExtensionSetup = setupResourceExtension; - querier: CheqdQuerier & ResourceExtension + querier: CheqdQuerier & ResourceExtension; constructor(signer: CheqdSigningStargateClient, querier: CheqdQuerier & ResourceExtension) { - super(signer, querier) - this.querier = querier + super(signer, querier); + this.querier = querier; this.methods = { createLinkedResourceTx: this.createLinkedResourceTx.bind(this), queryLinkedResource: this.queryLinkedResource.bind(this), queryLinkedResourceMetadata: this.queryLinkedResourceMetadata.bind(this), queryLinkedResources: this.queryLinkedResources.bind(this), - } + }; } public getRegistryTypes(): Iterable<[string, GeneratedType]> { - return ResourceModule.registryTypes + return ResourceModule.registryTypes; } public getQuerierExtensionSetup(): QueryExtensionSetup { - return ResourceModule.querierExtensionSetup + return ResourceModule.querierExtensionSetup; } - static async signPayload(payload: MsgCreateResourcePayload, signInputs: ISignInputs[] | SignInfo[]): Promise { - const signBytes = MsgCreateResourcePayload.encode(payload).finish() - let signatures: SignInfo[] - if(ISignInputs.isSignInput(signInputs)) { - signatures = await CheqdSigningStargateClient.signIdentityTx(signBytes, signInputs) + static async signPayload( + payload: MsgCreateResourcePayload, + signInputs: ISignInputs[] | SignInfo[] + ): Promise { + const signBytes = MsgCreateResourcePayload.encode(payload).finish(); + let signatures: SignInfo[]; + if (ISignInputs.isSignInput(signInputs)) { + signatures = await CheqdSigningStargateClient.signIdentityTx(signBytes, signInputs); } else { - signatures = signInputs + signatures = signInputs; } return { payload, - signatures - } + signatures, + }; } - async createLinkedResourceTx(signInputs: ISignInputs[] | SignInfo[], resourcePayload: Partial, address: string, fee?: DidStdFee | 'auto' | number, memo?: string, context?: IContext): Promise { + async createLinkedResourceTx( + signInputs: ISignInputs[] | SignInfo[], + resourcePayload: Partial, + address: string, + fee?: DidStdFee | 'auto' | number, + memo?: string, + context?: IContext + ): Promise { if (!this._signer) { - this._signer = context!.sdk!.signer + this._signer = context!.sdk!.signer; } - const payload = MsgCreateResourcePayload.fromPartial(resourcePayload) + const payload = MsgCreateResourcePayload.fromPartial(resourcePayload); - const msg = await ResourceModule.signPayload(payload, signInputs) + const msg = await ResourceModule.signPayload(payload, signInputs); const encObj: MsgCreateResourceEncodeObject = { typeUrl: typeUrlMsgCreateResource, - value: msg - } + value: msg, + }; if (address === '') { - address = (await context!.sdk!.options.wallet.getAccounts())[0].address + address = (await context!.sdk!.options.wallet.getAccounts())[0].address; } if (!fee) { if (payload.data.length === 0) { - throw new Error('Linked resource data is empty') + throw new Error('Linked resource data is empty'); } - fee = await async function() { - const mimeType = await ResourceModule.readMimeType(payload.data) + fee = await (async function () { + const mimeType = await ResourceModule.readMimeType(payload.data); if (mimeType.startsWith('image/')) { - return await ResourceModule.generateCreateResourceImageFees(address) + return await ResourceModule.generateCreateResourceImageFees(address); } if (mimeType.startsWith('application/json')) { - return await ResourceModule.generateCreateResourceJsonFees(address) + return await ResourceModule.generateCreateResourceJsonFees(address); } - return await ResourceModule.generateCreateResourceDefaultFees(address) - }() + return await ResourceModule.generateCreateResourceDefaultFees(address); + })(); } - return this._signer.signAndBroadcast( - address, - [encObj], - fee!, - memo - ) + return this._signer.signAndBroadcast(address, [encObj], fee!, memo); } - async queryLinkedResource(collectionId: string, resourceId: string, context?: IContext): Promise { + async queryLinkedResource( + collectionId: string, + resourceId: string, + context?: IContext + ): Promise { if (!this.querier) { - this.querier = context!.sdk!.querier + this.querier = context!.sdk!.querier; } - return await this.querier[defaultResourceExtensionKey].resource(collectionId, resourceId) + return await this.querier[defaultResourceExtensionKey].resource(collectionId, resourceId); } async queryLinkedResourceMetadata(collectionId: string, resourceId: string, context?: IContext): Promise { if (!this.querier) { - this.querier = context!.sdk!.querier + this.querier = context!.sdk!.querier; } - return await this.querier[defaultResourceExtensionKey].resourceMetadata(collectionId, resourceId) + return await this.querier[defaultResourceExtensionKey].resourceMetadata(collectionId, resourceId); } async queryLinkedResources(collectionId: string, context?: IContext): Promise { if (!this.querier) { - this.querier = context!.sdk!.querier + this.querier = context!.sdk!.querier; } - return await this.querier[defaultResourceExtensionKey].collectionResources(collectionId) + return await this.querier[defaultResourceExtensionKey].collectionResources(collectionId); } static async readMimeType(content: Uint8Array): Promise { - if (isJSON(toString(content, 'utf-8'))) return 'application/json' + if (isJSON(toString(content, 'utf-8'))) return 'application/json'; - return (await fileTypeFromBuffer(content))?.mime ?? 'application/octet-stream' + return (await fileTypeFromBuffer(content))?.mime ?? 'application/octet-stream'; } static async generateCreateResourceImageFees(feePayer: string, granter?: string): Promise { return { - amount: [ - ResourceModule.fees.DefaultCreateResourceImageFee - ], + amount: [ResourceModule.fees.DefaultCreateResourceImageFee], gas: '1200000', payer: feePayer, - granter: granter - } as DidStdFee + granter: granter, + } as DidStdFee; } static async generateCreateResourceJsonFees(feePayer: string, granter?: string): Promise { return { - amount: [ - ResourceModule.fees.DefaultCreateResourceJsonFee - ], + amount: [ResourceModule.fees.DefaultCreateResourceJsonFee], gas: '1200000', payer: feePayer, - granter: granter - } as DidStdFee + granter: granter, + } as DidStdFee; } static async generateCreateResourceDefaultFees(feePayer: string, granter?: string): Promise { return { - amount: [ - ResourceModule.fees.DefaultCreateResourceDefaultFee - ], + amount: [ResourceModule.fees.DefaultCreateResourceDefaultFee], gas: '1200000', payer: feePayer, - granter: granter - } as DidStdFee + granter: granter, + } as DidStdFee; } } diff --git a/src/querier.ts b/src/querier.ts index 0b5cf56d..10044352 100644 --- a/src/querier.ts +++ b/src/querier.ts @@ -1,36 +1,39 @@ -import { QueryClient } from "@cosmjs/stargate"; -import { Tendermint34Client } from "@cosmjs/tendermint-rpc"; -import { - QueryExtensionSetup, - CheqdExtensions -} from "./types.js"; +import { QueryClient } from '@cosmjs/stargate'; +import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; +import { QueryExtensionSetup, CheqdExtensions } from './types.js'; export class CheqdQuerier extends QueryClient { - constructor(tmClient: Tendermint34Client) { - super(tmClient) - } + constructor(tmClient: Tendermint34Client) { + super(tmClient); + } - static async connect(url: string): Promise { - const tmClient = await Tendermint34Client.connect(url); - return new CheqdQuerier(tmClient); - } + static async connect(url: string): Promise { + const tmClient = await Tendermint34Client.connect(url); + return new CheqdQuerier(tmClient); + } - static async fromClient(client: Tendermint34Client): Promise { - return new CheqdQuerier(client); - } + static async fromClient(client: Tendermint34Client): Promise { + return new CheqdQuerier(client); + } - static async connectWithExtension(url: string, extension: QueryExtensionSetup): Promise { - const tmClient = await Tendermint34Client.connect(url); - return CheqdQuerier.withExtensions(tmClient, extension); - } + static async connectWithExtension( + url: string, + extension: QueryExtensionSetup + ): Promise { + const tmClient = await Tendermint34Client.connect(url); + return CheqdQuerier.withExtensions(tmClient, extension); + } - static async connectWithExtensions(url: string, ...extensions: QueryExtensionSetup[]): Promise { - if (extensions.length === 1) { - return CheqdQuerier.connectWithExtension(url, extensions[0]); - } + static async connectWithExtensions( + url: string, + ...extensions: QueryExtensionSetup[] + ): Promise { + if (extensions.length === 1) { + return CheqdQuerier.connectWithExtension(url, extensions[0]); + } - const tmClient = await Tendermint34Client.connect(url); - const tupleLike = extensions as [QueryExtensionSetup, QueryExtensionSetup]; - return CheqdQuerier.withExtensions(tmClient, ...tupleLike); - } + const tmClient = await Tendermint34Client.connect(url); + const tupleLike = extensions as [QueryExtensionSetup, QueryExtensionSetup]; + return CheqdQuerier.withExtensions(tmClient, ...tupleLike); + } } diff --git a/src/registry.ts b/src/registry.ts index 7ef1a2ba..ea285648 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -1,13 +1,10 @@ -import { - Registry, - GeneratedType, -} from '@cosmjs/proto-signing' +import { Registry, GeneratedType } from '@cosmjs/proto-signing'; -import { defaultRegistryTypes } from '@cosmjs/stargate' +import { defaultRegistryTypes } from '@cosmjs/stargate'; export function createDefaultCheqdRegistry(customTypes?: Iterable<[string, GeneratedType]>): Registry { if (!customTypes) customTypes = []; - return new Registry([...defaultRegistryTypes, ...customTypes]) + return new Registry([...defaultRegistryTypes, ...customTypes]); } -export const CheqdRegistry = new Registry(defaultRegistryTypes) +export const CheqdRegistry = new Registry(defaultRegistryTypes); diff --git a/src/signer.ts b/src/signer.ts index ed6489ab..16a05ff9 100644 --- a/src/signer.ts +++ b/src/signer.ts @@ -4,8 +4,8 @@ import { OfflineSigner, encodePubkey, TxBodyEncodeObject, - makeSignDoc -} from "@cosmjs/proto-signing" + makeSignDoc, +} from '@cosmjs/proto-signing'; import { DeliverTxResponse, GasPrice, @@ -13,54 +13,36 @@ import { SigningStargateClient, SigningStargateClientOptions, calculateFee, - SignerData } from "@cosmjs/stargate" -import { Tendermint34Client } from "@cosmjs/tendermint-rpc" -import { createDefaultCheqdRegistry } from "./registry.js" -import { + SignerData, +} from '@cosmjs/stargate'; +import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; +import { createDefaultCheqdRegistry } from './registry.js'; +import { MsgCreateDidDocPayload, SignInfo, MsgUpdateDidDocPayload, MsgDeactivateDidDocPayload, - VerificationMethod + VerificationMethod, } from '@cheqd/ts-proto/cheqd/did/v2/index.js'; -import { - DidStdFee, - ISignInputs, - TSignerAlgo, - VerificationMethods -} from './types.js'; -import { - base64ToBytes, - EdDSASigner, - hexToBytes, - Signer, - ES256Signer, - ES256KSigner -} from 'did-jwt'; -import { - assert, - assertDefined -} from '@cosmjs/utils' -import { encodeSecp256k1Pubkey } from '@cosmjs/amino' -import { Int53 } from '@cosmjs/math' -import { fromBase64 } from '@cosmjs/encoding' -import { - AuthInfo, - SignerInfo, - TxRaw -} from 'cosmjs-types/cosmos/tx/v1beta1/tx.js' -import { SignMode } from 'cosmjs-types/cosmos/tx/signing/v1beta1/signing.js' -import { Any } from 'cosmjs-types/google/protobuf/any.js' -import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin.js' -import Long from 'long' +import { DidStdFee, ISignInputs, TSignerAlgo, VerificationMethods } from './types.js'; +import { base64ToBytes, EdDSASigner, hexToBytes, Signer, ES256Signer, ES256KSigner } from 'did-jwt'; +import { assert, assertDefined } from '@cosmjs/utils'; +import { encodeSecp256k1Pubkey } from '@cosmjs/amino'; +import { Int53 } from '@cosmjs/math'; +import { fromBase64 } from '@cosmjs/encoding'; +import { AuthInfo, SignerInfo, TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx.js'; +import { SignMode } from 'cosmjs-types/cosmos/tx/signing/v1beta1/signing.js'; +import { Any } from 'cosmjs-types/google/protobuf/any.js'; +import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin.js'; +import Long from 'long'; export function calculateDidFee(gasLimit: number, gasPrice: string | GasPrice): DidStdFee { - return calculateFee(gasLimit, gasPrice) + return calculateFee(gasLimit, gasPrice); } export function makeSignerInfos( signers: ReadonlyArray<{ readonly pubkey: Any; readonly sequence: number }>, - signMode: SignMode, + signMode: SignMode ): SignerInfo[] { return signers.map( ({ pubkey, sequence }): SignerInfo => ({ @@ -69,7 +51,7 @@ export function makeSignerInfos( single: { mode: signMode }, }, sequence: Long.fromNumber(sequence), - }), + }) ); } @@ -78,30 +60,34 @@ export function makeDidAuthInfoBytes( feeAmount: readonly Coin[], gasLimit: number, feePayer: string, - signMode = SignMode.SIGN_MODE_DIRECT, + signMode = SignMode.SIGN_MODE_DIRECT ): Uint8Array { const authInfo = { signerInfos: makeSignerInfos(signers, signMode), fee: { amount: [...feeAmount], gasLimit: Long.fromNumber(gasLimit), - payer: feePayer - } - } - return AuthInfo.encode(AuthInfo.fromPartial(authInfo)).finish() + payer: feePayer, + }, + }; + return AuthInfo.encode(AuthInfo.fromPartial(authInfo)).finish(); } export class CheqdSigningStargateClient extends SigningStargateClient { - private didSigners: TSignerAlgo = {} - private readonly _gasPrice: GasPrice | undefined - private readonly _signer: OfflineSigner + private didSigners: TSignerAlgo = {}; + private readonly _gasPrice: GasPrice | undefined; + private readonly _signer: OfflineSigner; - public static async connectWithSigner(endpoint: string | HttpEndpoint, signer: OfflineSigner, options?: SigningStargateClientOptions | undefined): Promise { - const tmClient = await Tendermint34Client.connect(endpoint) + public static async connectWithSigner( + endpoint: string | HttpEndpoint, + signer: OfflineSigner, + options?: SigningStargateClientOptions | undefined + ): Promise { + const tmClient = await Tendermint34Client.connect(endpoint); return new CheqdSigningStargateClient(tmClient, signer, { registry: options?.registry ? options.registry : createDefaultCheqdRegistry(), - ...options - }) + ...options, + }); } constructor( @@ -109,32 +95,32 @@ export class CheqdSigningStargateClient extends SigningStargateClient { signer: OfflineSigner, options: SigningStargateClientOptions = {} ) { - super(tmClient, signer, options) - this._signer = signer - if (options.gasPrice) this._gasPrice = options.gasPrice + super(tmClient, signer, options); + this._signer = signer; + if (options.gasPrice) this._gasPrice = options.gasPrice; } async signAndBroadcast( signerAddress: string, messages: readonly EncodeObject[], - fee: DidStdFee | "auto" | number, - memo = "", + fee: DidStdFee | 'auto' | number, + memo = '' ): Promise { - let usedFee: DidStdFee - if (fee == "auto" || typeof fee === "number") { - assertDefined(this._gasPrice, "Gas price must be set in the client options when auto gas is used.") - const gasEstimation = await this.simulate(signerAddress, messages, memo) - const multiplier = typeof fee === "number" ? fee : 1.3 - usedFee = calculateDidFee(Math.round(gasEstimation * multiplier), this._gasPrice) - usedFee.payer = signerAddress + let usedFee: DidStdFee; + if (fee == 'auto' || typeof fee === 'number') { + assertDefined(this._gasPrice, 'Gas price must be set in the client options when auto gas is used.'); + const gasEstimation = await this.simulate(signerAddress, messages, memo); + const multiplier = typeof fee === 'number' ? fee : 1.3; + usedFee = calculateDidFee(Math.round(gasEstimation * multiplier), this._gasPrice); + usedFee.payer = signerAddress; } else { - usedFee = fee - assertDefined(usedFee.payer, "Payer address must be set when fee is not auto.") - signerAddress = usedFee.payer! + usedFee = fee; + assertDefined(usedFee.payer, 'Payer address must be set when fee is not auto.'); + signerAddress = usedFee.payer!; } - const txRaw = await this.sign(signerAddress, messages, usedFee, memo) - const txBytes = TxRaw.encode(txRaw).finish() - return this.broadcastTx(txBytes, this.broadcastTimeoutMs, this.broadcastPollIntervalMs) + const txRaw = await this.sign(signerAddress, messages, usedFee, memo); + const txBytes = TxRaw.encode(txRaw).finish(); + return this.broadcastTx(txBytes, this.broadcastTimeoutMs, this.broadcastPollIntervalMs); } public async sign( @@ -142,22 +128,22 @@ export class CheqdSigningStargateClient extends SigningStargateClient { messages: readonly EncodeObject[], fee: DidStdFee, memo: string, - explicitSignerData?: SignerData, + explicitSignerData?: SignerData ): Promise { - let signerData: SignerData + let signerData: SignerData; if (explicitSignerData) { - signerData = explicitSignerData + signerData = explicitSignerData; } else { - const { accountNumber, sequence } = await this.getSequence(signerAddress) - const chainId = await this.getChainId() + const { accountNumber, sequence } = await this.getSequence(signerAddress); + const chainId = await this.getChainId(); signerData = { accountNumber: accountNumber, sequence: sequence, chainId: chainId, - } + }; } - return this._signDirect(signerAddress, messages, fee, memo, signerData) + return this._signDirect(signerAddress, messages, fee, memo, signerData); } private async _signDirect( @@ -165,109 +151,139 @@ export class CheqdSigningStargateClient extends SigningStargateClient { messages: readonly EncodeObject[], fee: DidStdFee, memo: string, - { accountNumber, sequence, chainId }: SignerData, + { accountNumber, sequence, chainId }: SignerData ): Promise { - assert(isOfflineDirectSigner(this._signer)) + assert(isOfflineDirectSigner(this._signer)); const accountFromSigner = (await this._signer.getAccounts()).find( - (account) => account.address === signerAddress, - ) + (account) => account.address === signerAddress + ); if (!accountFromSigner) { - throw new Error("Failed to retrieve account from signer") + throw new Error('Failed to retrieve account from signer'); } - const pubkey = encodePubkey(encodeSecp256k1Pubkey(accountFromSigner.pubkey)) + const pubkey = encodePubkey(encodeSecp256k1Pubkey(accountFromSigner.pubkey)); const txBodyEncodeObject: TxBodyEncodeObject = { - typeUrl: "/cosmos.tx.v1beta1.TxBody", + typeUrl: '/cosmos.tx.v1beta1.TxBody', value: { messages: messages, memo: memo, }, - } - const txBodyBytes = this.registry.encode(txBodyEncodeObject) - const gasLimit = Int53.fromString(fee.gas).toNumber() - const authInfoBytes = makeDidAuthInfoBytes([{ pubkey, sequence }], fee.amount, gasLimit, fee.payer!) - const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber) - const { signature, signed } = await this._signer.signDirect(signerAddress, signDoc) + }; + const txBodyBytes = this.registry.encode(txBodyEncodeObject); + const gasLimit = Int53.fromString(fee.gas).toNumber(); + const authInfoBytes = makeDidAuthInfoBytes([{ pubkey, sequence }], fee.amount, gasLimit, fee.payer!); + const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber); + const { signature, signed } = await this._signer.signDirect(signerAddress, signDoc); return TxRaw.fromPartial({ bodyBytes: signed.bodyBytes, authInfoBytes: signed.authInfoBytes, signatures: [fromBase64(signature.signature)], - }) + }); } async checkDidSigners(verificationMethods: Partial[] = []): Promise { if (verificationMethods.length === 0) { - throw new Error('No verification methods provided') + throw new Error('No verification methods provided'); } verificationMethods.forEach((verificationMethod) => { - if (!(Object.values(VerificationMethods) as string[]).includes(verificationMethod.verificationMethodType ?? '')) { - throw new Error(`Unsupported verification method type: ${verificationMethod.verificationMethodType}`) + if ( + !(Object.values(VerificationMethods) as string[]).includes( + verificationMethod.verificationMethodType ?? '' + ) + ) { + throw new Error(`Unsupported verification method type: ${verificationMethod.verificationMethodType}`); } if (!this.didSigners[verificationMethod.verificationMethodType ?? '']) { - this.didSigners[verificationMethod.verificationMethodType ?? ''] = EdDSASigner + this.didSigners[verificationMethod.verificationMethodType ?? ''] = EdDSASigner; } - }) + }); - return this.didSigners + return this.didSigners; } - async getDidSigner(verificationMethodId: string, verificationMethods: Partial[]): Promise<(secretKey: Uint8Array) => Signer> { - await this.checkDidSigners(verificationMethods) - const verificationMethod = verificationMethods.find(method => method.id === verificationMethodId)?.verificationMethodType + async getDidSigner( + verificationMethodId: string, + verificationMethods: Partial[] + ): Promise<(secretKey: Uint8Array) => Signer> { + await this.checkDidSigners(verificationMethods); + const verificationMethod = verificationMethods.find((method) => method.id === verificationMethodId) + ?.verificationMethodType; if (!verificationMethod) { - throw new Error(`Verification method for ${verificationMethodId} not found`) + throw new Error(`Verification method for ${verificationMethodId} not found`); } - return this.didSigners[verificationMethod]! + return this.didSigners[verificationMethod]!; } async signcreateDidDocTx(signInputs: ISignInputs[], payload: MsgCreateDidDocPayload): Promise { - await this.checkDidSigners(payload?.verificationMethod) + await this.checkDidSigners(payload?.verificationMethod); - const signBytes = MsgCreateDidDocPayload.encode(payload).finish() - const signInfos: SignInfo[] = await Promise.all(signInputs.map(async (signInput) => { - return { - verificationMethodId: signInput.verificationMethodId, - signature: base64ToBytes((await (await this.getDidSigner(signInput.verificationMethodId, payload.verificationMethod))(hexToBytes(signInput.privateKeyHex))(signBytes)) as string) - } - })) + const signBytes = MsgCreateDidDocPayload.encode(payload).finish(); + const signInfos: SignInfo[] = await Promise.all( + signInputs.map(async (signInput) => { + return { + verificationMethodId: signInput.verificationMethodId, + signature: base64ToBytes( + (await ( + await this.getDidSigner(signInput.verificationMethodId, payload.verificationMethod) + )(hexToBytes(signInput.privateKeyHex))(signBytes)) as string + ), + }; + }) + ); - return signInfos + return signInfos; } async signupdateDidDocTx(signInputs: ISignInputs[], payload: MsgUpdateDidDocPayload): Promise { - await this.checkDidSigners(payload?.verificationMethod) + await this.checkDidSigners(payload?.verificationMethod); - const signBytes = MsgUpdateDidDocPayload.encode(payload).finish() - const signInfos: SignInfo[] = await Promise.all(signInputs.map(async (signInput) => { - return { - verificationMethodId: signInput.verificationMethodId, - signature: base64ToBytes((await (await this.getDidSigner(signInput.verificationMethodId, payload.verificationMethod))(hexToBytes(signInput.privateKeyHex))(signBytes)) as string) - } - })) + const signBytes = MsgUpdateDidDocPayload.encode(payload).finish(); + const signInfos: SignInfo[] = await Promise.all( + signInputs.map(async (signInput) => { + return { + verificationMethodId: signInput.verificationMethodId, + signature: base64ToBytes( + (await ( + await this.getDidSigner(signInput.verificationMethodId, payload.verificationMethod) + )(hexToBytes(signInput.privateKeyHex))(signBytes)) as string + ), + }; + }) + ); - return signInfos + return signInfos; } - async signdeactivateDidDocTx(signInputs: ISignInputs[], payload: MsgDeactivateDidDocPayload, verificationMethod: VerificationMethod[]): Promise { - await this.checkDidSigners(verificationMethod) + async signdeactivateDidDocTx( + signInputs: ISignInputs[], + payload: MsgDeactivateDidDocPayload, + verificationMethod: VerificationMethod[] + ): Promise { + await this.checkDidSigners(verificationMethod); - const signBytes = MsgDeactivateDidDocPayload.encode(payload).finish() - const signInfos: SignInfo[] = await Promise.all(signInputs.map(async (signInput) => { - return { - verificationMethodId: signInput.verificationMethodId, - signature: base64ToBytes((await (await this.getDidSigner(signInput.verificationMethodId, verificationMethod))(hexToBytes(signInput.privateKeyHex))(signBytes)) as string) - } - })) + const signBytes = MsgDeactivateDidDocPayload.encode(payload).finish(); + const signInfos: SignInfo[] = await Promise.all( + signInputs.map(async (signInput) => { + return { + verificationMethodId: signInput.verificationMethodId, + signature: base64ToBytes( + (await ( + await this.getDidSigner(signInput.verificationMethodId, verificationMethod) + )(hexToBytes(signInput.privateKeyHex))(signBytes)) as string + ), + }; + }) + ); - return signInfos + return signInfos; } static async signIdentityTx(signBytes: Uint8Array, signInputs: ISignInputs[]): Promise { let signInfos: SignInfo[] = []; for (let signInput of signInputs) { - if (typeof(signInput.keyType) === undefined) { - throw new Error('Key type is not defined') + if (typeof signInput.keyType === undefined) { + throw new Error('Key type is not defined'); } let signature: string; @@ -288,10 +304,10 @@ export class CheqdSigningStargateClient extends SigningStargateClient { signInfos.push({ verificationMethodId: signInput.verificationMethodId, - signature: base64ToBytes(signature) + signature: base64ToBytes(signature), }); } - return signInfos + return signInfos; } } diff --git a/src/types.ts b/src/types.ts index 48418439..120d8d69 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,110 +1,104 @@ import { - Service as ProtobufService, - VerificationMethod as ProtobufVerificationMethod -} from "@cheqd/ts-proto/cheqd/did/v2/index.js" -import { CheqdSDK } from "./index.js" -import { Coin } from "@cosmjs/proto-signing" -import { Signer } from "did-jwt" -import { QueryClient } from "@cosmjs/stargate" -import { DIDResolutionResult } from "did-resolver" -import { DidExtension } from "./modules/did.js" + Service as ProtobufService, + VerificationMethod as ProtobufVerificationMethod, +} from '@cheqd/ts-proto/cheqd/did/v2/index.js'; +import { CheqdSDK } from './index.js'; +import { Coin } from '@cosmjs/proto-signing'; +import { Signer } from 'did-jwt'; +import { QueryClient } from '@cosmjs/stargate'; +import { DIDResolutionResult } from 'did-resolver'; +import { DidExtension } from './modules/did.js'; import { ResourceExtension } from './modules/resource.js'; -export { - DIDDocument, - VerificationMethod, - Service, - ServiceEndpoint, - JsonWebKey -} from "did-resolver" +export { DIDDocument, VerificationMethod, Service, ServiceEndpoint, JsonWebKey } from 'did-resolver'; export enum CheqdNetwork { - Mainnet = 'mainnet', - Testnet = 'testnet', + Mainnet = 'mainnet', + Testnet = 'testnet', } -export type QueryExtensionSetup = (base: QueryClient) => T +export type QueryExtensionSetup = (base: QueryClient) => T; export type CheqdExtension = { - [P in K]: (Record & Partial, never>>) extends infer O - ? { [Q in keyof O]: O[Q] } - : never -}[K] + [P in K]: Record & Partial, never>> extends infer O ? { [Q in keyof O]: O[Q] } : never; +}[K]; -export type CheqdExtensions = DidExtension | ResourceExtension +export type CheqdExtensions = DidExtension | ResourceExtension; export interface IModuleMethod { - (...args: any[]): Promise + (...args: any[]): Promise; } export interface IModuleMethodMap extends Record {} export interface IContext { - sdk: CheqdSDK + sdk: CheqdSDK; } -export type DIDDocumentWithMetadata = Pick +export type DIDDocumentWithMetadata = Pick; export type SpecValidationResult = { - valid: boolean - error?: string - protobufVerificationMethod?: ProtobufVerificationMethod[] - protobufService?: ProtobufService[] -} + valid: boolean; + error?: string; + protobufVerificationMethod?: ProtobufVerificationMethod[]; + protobufService?: ProtobufService[]; +}; export enum VerificationMethods { - Ed255192020 = 'Ed25519VerificationKey2020', - Ed255192018 = 'Ed25519VerificationKey2018', - JWK = 'JsonWebKey2020', + Ed255192020 = 'Ed25519VerificationKey2020', + Ed255192018 = 'Ed25519VerificationKey2018', + JWK = 'JsonWebKey2020', } export enum MethodSpecificIdAlgo { - Base58 = 'base58btc', - Uuid = 'uuid', + Base58 = 'base58btc', + Uuid = 'uuid', } export type TSignerAlgo = { - [key in VerificationMethods as string]?: (secretKey: Uint8Array) => Signer -} + [key in VerificationMethods as string]?: (secretKey: Uint8Array) => Signer; +}; export interface ISignInputs { - verificationMethodId: string - keyType?: 'Ed25519' | 'Secp256k1' | 'P256' - privateKeyHex: string + verificationMethodId: string; + keyType?: 'Ed25519' | 'Secp256k1' | 'P256'; + privateKeyHex: string; } export interface IKeyPair { - publicKey: string - privateKey: string - algo?: MethodSpecificIdAlgo + publicKey: string; + privateKey: string; + algo?: MethodSpecificIdAlgo; } export interface IKeyValuePair { - key: string - value: any + key: string; + value: any; } -export type TVerificationKeyPrefix = string +export type TVerificationKeyPrefix = string; -export type TVerificationKey = `${K}-${N}` +export type TVerificationKey = `${K}-${N}`; export interface IVerificationKeys { - readonly methodSpecificId: TMethodSpecificId - readonly didUrl: `did:cheqd:${CheqdNetwork}:${IVerificationKeys['methodSpecificId']}` extends string ? string : never - readonly keyId: `${IVerificationKeys['didUrl']}#${TVerificationKey}` - readonly publicKey: string + readonly methodSpecificId: TMethodSpecificId; + readonly didUrl: `did:cheqd:${CheqdNetwork}:${IVerificationKeys['methodSpecificId']}` extends string + ? string + : never; + readonly keyId: `${IVerificationKeys['didUrl']}#${TVerificationKey}`; + readonly publicKey: string; } -export type TMethodSpecificId = string +export type TMethodSpecificId = string; export interface DidStdFee { - readonly amount: readonly Coin[] - readonly gas: string - payer?: string - granter?: string + readonly amount: readonly Coin[]; + readonly gas: string; + payer?: string; + granter?: string; } export const ISignInputs = { - isSignInput(object: Object[]): object is ISignInputs[] { - return object.some((x)=> 'privateKeyHex' in x) - } -} \ No newline at end of file + isSignInput(object: Object[]): object is ISignInputs[] { + return object.some((x) => 'privateKeyHex' in x); + }, +}; diff --git a/src/utils.ts b/src/utils.ts index eeeddeb8..f7af6bf6 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,323 +1,333 @@ -import { - IKeyPair, - IKeyValuePair, - ISignInputs, - VerificationMethods, - TMethodSpecificId, - MethodSpecificIdAlgo, - TVerificationKey, - TVerificationKeyPrefix, - CheqdNetwork, - IVerificationKeys, - VerificationMethod, - DIDDocument, - SpecValidationResult, - JsonWebKey, -} from "./types.js" import { - fromString, - toString -} from 'uint8arrays' -import { bases } from "multiformats/basics" -import { base64ToBytes } from "did-jwt" + IKeyPair, + IKeyValuePair, + ISignInputs, + VerificationMethods, + TMethodSpecificId, + MethodSpecificIdAlgo, + TVerificationKey, + TVerificationKeyPrefix, + CheqdNetwork, + IVerificationKeys, + VerificationMethod, + DIDDocument, + SpecValidationResult, + JsonWebKey, +} from './types.js'; +import { fromString, toString } from 'uint8arrays'; +import { bases } from 'multiformats/basics'; +import { base64ToBytes } from 'did-jwt'; +import { generateKeyPair, generateKeyPairFromSeed, KeyPair } from '@stablelib/ed25519'; +import { DirectSecp256k1HdWallet, DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; +import { EnglishMnemonic as _, sha256 } from '@cosmjs/crypto'; +import { rawSecp256k1PubkeyToRawAddress } from '@cosmjs/amino'; +import pkg from 'secp256k1'; +import { v4 } from 'uuid'; import { - generateKeyPair, - generateKeyPairFromSeed, - KeyPair -} from '@stablelib/ed25519' -import { DirectSecp256k1HdWallet, DirectSecp256k1Wallet } from '@cosmjs/proto-signing' -import { EnglishMnemonic as _, sha256 } from '@cosmjs/crypto' -import { rawSecp256k1PubkeyToRawAddress } from '@cosmjs/amino' -import pkg from 'secp256k1' -import { v4 } from 'uuid' -import { - VerificationMethod as ProtoVerificationMethod, - Service as ProtoService, - MsgCreateDidDocPayload, - MsgDeactivateDidDocPayload, -} from "@cheqd/ts-proto/cheqd/did/v2/index.js" -import { DIDModule } from "./modules/did.js" -import { MsgCreateResourcePayload } from "@cheqd/ts-proto/cheqd/resource/v2/index.js" -import { toBech32 } from "@cosmjs/encoding" -import { StargateClient } from "@cosmjs/stargate" -import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin" + VerificationMethod as ProtoVerificationMethod, + Service as ProtoService, + MsgCreateDidDocPayload, + MsgDeactivateDidDocPayload, +} from '@cheqd/ts-proto/cheqd/did/v2/index.js'; +import { DIDModule } from './modules/did.js'; +import { MsgCreateResourcePayload } from '@cheqd/ts-proto/cheqd/resource/v2/index.js'; +import { toBech32 } from '@cosmjs/encoding'; +import { StargateClient } from '@cosmjs/stargate'; +import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin'; export type TImportableEd25519Key = { - publicKeyHex: string - privateKeyHex: string - kid: string - type: "Ed25519" -} + publicKeyHex: string; + privateKeyHex: string; + kid: string; + type: 'Ed25519'; +}; const MULTICODEC_ED25519_HEADER = new Uint8Array([0xed, 0x01]); export function isEqualKeyValuePair(kv1: IKeyValuePair[], kv2: IKeyValuePair[]): boolean { - return kv1.every((item, index) => item.key === kv2[index].key && item.value === kv2[index].value) + return kv1.every((item, index) => item.key === kv2[index].key && item.value === kv2[index].value); } export class EnglishMnemonic extends _ { - public static readonly _mnemonicMatcher = /^[a-z]+( [a-z]+)*$/ + public static readonly _mnemonicMatcher = /^[a-z]+( [a-z]+)*$/; } -export function createSignInputsFromImportableEd25519Key(key: TImportableEd25519Key, verificationMethod: VerificationMethod[]): ISignInputs { - if (verificationMethod?.length === 0) throw new Error('No verification methods provided') - - const publicKey = fromString(key.publicKeyHex, 'hex') - - for(const method of verificationMethod) { - switch (method?.type) { - case VerificationMethods.Ed255192020: - const publicKeyMultibase = toMultibaseRaw(publicKey) - if (method.publicKeyMultibase === publicKeyMultibase) { - return { - verificationMethodId: method.id, - privateKeyHex: key.privateKeyHex - } - } - case VerificationMethods.Ed255192018: - const publicKeyBase58 = bases['base58btc'].encode(publicKey).slice(1) - if (method.publicKeyBase58 === publicKeyBase58) { - return { - verificationMethodId: method.id, - privateKeyHex: key.privateKeyHex - } - } - case VerificationMethods.JWK: - const publicKeyJwk: JsonWebKey = { - crv: 'Ed25519', - kty: 'OKP', - x: toString( publicKey, 'base64url' ) - } - if (JSON.stringify(method.publicKeyJwk) === JSON.stringify(publicKeyJwk)) { - return { - verificationMethodId: method.id, - privateKeyHex: key.privateKeyHex - } - } - } - } - - throw new Error('No verification method type provided') +export function createSignInputsFromImportableEd25519Key( + key: TImportableEd25519Key, + verificationMethod: VerificationMethod[] +): ISignInputs { + if (verificationMethod?.length === 0) throw new Error('No verification methods provided'); + + const publicKey = fromString(key.publicKeyHex, 'hex'); + + for (const method of verificationMethod) { + switch (method?.type) { + case VerificationMethods.Ed255192020: + const publicKeyMultibase = toMultibaseRaw(publicKey); + if (method.publicKeyMultibase === publicKeyMultibase) { + return { + verificationMethodId: method.id, + privateKeyHex: key.privateKeyHex, + }; + } + case VerificationMethods.Ed255192018: + const publicKeyBase58 = bases['base58btc'].encode(publicKey).slice(1); + if (method.publicKeyBase58 === publicKeyBase58) { + return { + verificationMethodId: method.id, + privateKeyHex: key.privateKeyHex, + }; + } + case VerificationMethods.JWK: + const publicKeyJwk: JsonWebKey = { + crv: 'Ed25519', + kty: 'OKP', + x: toString(publicKey, 'base64url'), + }; + if (JSON.stringify(method.publicKeyJwk) === JSON.stringify(publicKeyJwk)) { + return { + verificationMethodId: method.id, + privateKeyHex: key.privateKeyHex, + }; + } + } + } + + throw new Error('No verification method type provided'); } export function createKeyPairRaw(seed?: string): KeyPair { - return seed ? generateKeyPairFromSeed(fromString(seed)) : generateKeyPair() + return seed ? generateKeyPairFromSeed(fromString(seed)) : generateKeyPair(); } export function createKeyPairBase64(seed?: string): IKeyPair { - const keyPair = seed ? generateKeyPairFromSeed(fromString(seed)) : generateKeyPair() - return { - publicKey: toString(keyPair.publicKey, 'base64'), - privateKey: toString(keyPair.secretKey, 'base64'), - } + const keyPair = seed ? generateKeyPairFromSeed(fromString(seed)) : generateKeyPair(); + return { + publicKey: toString(keyPair.publicKey, 'base64'), + privateKey: toString(keyPair.secretKey, 'base64'), + }; } export function createKeyPairHex(seed?: string): IKeyPair { - const keyPair = createKeyPairRaw(seed) - return { - publicKey: toString(keyPair.publicKey, 'hex'), - privateKey: toString(keyPair.secretKey, 'hex'), - } + const keyPair = createKeyPairRaw(seed); + return { + publicKey: toString(keyPair.publicKey, 'hex'), + privateKey: toString(keyPair.secretKey, 'hex'), + }; } -export function createVerificationKeys(publicKey: string, algo: MethodSpecificIdAlgo, key: TVerificationKey, network: CheqdNetwork = CheqdNetwork.Testnet): IVerificationKeys { - let methodSpecificId: TMethodSpecificId - let didUrl: IVerificationKeys['didUrl'] - - publicKey = publicKey.length == 43 ? publicKey : toString(fromString(publicKey, 'hex'), 'base64') - switch (algo) { - case MethodSpecificIdAlgo.Base58: - methodSpecificId = bases['base58btc'].encode(base64ToBytes(publicKey)) - didUrl = `did:cheqd:${network}:${(bases['base58btc'].encode((sha256(base64ToBytes(publicKey))).slice(0,16))).slice(1)}` - return { - methodSpecificId, - didUrl, - keyId: `${didUrl}#${key}`, - publicKey, - } - case MethodSpecificIdAlgo.Uuid: - methodSpecificId = bases['base58btc'].encode(base64ToBytes(publicKey)) - didUrl = `did:cheqd:${network}:${v4()}` - return { - methodSpecificId, - didUrl, - keyId: `${didUrl}#${key}`, - publicKey, - } - } +export function createVerificationKeys( + publicKey: string, + algo: MethodSpecificIdAlgo, + key: TVerificationKey, + network: CheqdNetwork = CheqdNetwork.Testnet +): IVerificationKeys { + let methodSpecificId: TMethodSpecificId; + let didUrl: IVerificationKeys['didUrl']; + + publicKey = publicKey.length == 43 ? publicKey : toString(fromString(publicKey, 'hex'), 'base64'); + switch (algo) { + case MethodSpecificIdAlgo.Base58: + methodSpecificId = bases['base58btc'].encode(base64ToBytes(publicKey)); + didUrl = `did:cheqd:${network}:${bases['base58btc'] + .encode(sha256(base64ToBytes(publicKey)).slice(0, 16)) + .slice(1)}`; + return { + methodSpecificId, + didUrl, + keyId: `${didUrl}#${key}`, + publicKey, + }; + case MethodSpecificIdAlgo.Uuid: + methodSpecificId = bases['base58btc'].encode(base64ToBytes(publicKey)); + didUrl = `did:cheqd:${network}:${v4()}`; + return { + methodSpecificId, + didUrl, + keyId: `${didUrl}#${key}`, + publicKey, + }; + } } -export function createDidVerificationMethod(verificationMethodTypes: VerificationMethods[], verificationKeys: IVerificationKeys[]): VerificationMethod[] { - return verificationMethodTypes.map((type, _) => { - switch (type) { - case VerificationMethods.Ed255192020: - return { - id: verificationKeys[_].keyId, - type, - controller: verificationKeys[_].didUrl, - publicKeyMultibase: toMultibaseRaw(base64ToBytes(verificationKeys[_].publicKey)) - } as VerificationMethod - case VerificationMethods.Ed255192018: - return { - id: verificationKeys[_].keyId, - type, - controller: verificationKeys[_].didUrl, - publicKeyBase58: verificationKeys[_].methodSpecificId.slice(1) - } as VerificationMethod - case VerificationMethods.JWK: - return { - id: verificationKeys[_].keyId, - type, - controller: verificationKeys[_].didUrl, - publicKeyJwk: { - crv: 'Ed25519', - kty: 'OKP', - x: toString( fromString( verificationKeys[_].publicKey, 'base64pad' ), 'base64url' ) - } - } as VerificationMethod - } - }) ?? [] +export function createDidVerificationMethod( + verificationMethodTypes: VerificationMethods[], + verificationKeys: IVerificationKeys[] +): VerificationMethod[] { + return ( + verificationMethodTypes.map((type, _) => { + switch (type) { + case VerificationMethods.Ed255192020: + return { + id: verificationKeys[_].keyId, + type, + controller: verificationKeys[_].didUrl, + publicKeyMultibase: toMultibaseRaw(base64ToBytes(verificationKeys[_].publicKey)), + } as VerificationMethod; + case VerificationMethods.Ed255192018: + return { + id: verificationKeys[_].keyId, + type, + controller: verificationKeys[_].didUrl, + publicKeyBase58: verificationKeys[_].methodSpecificId.slice(1), + } as VerificationMethod; + case VerificationMethods.JWK: + return { + id: verificationKeys[_].keyId, + type, + controller: verificationKeys[_].didUrl, + publicKeyJwk: { + crv: 'Ed25519', + kty: 'OKP', + x: toString(fromString(verificationKeys[_].publicKey, 'base64pad'), 'base64url'), + }, + } as VerificationMethod; + } + }) ?? [] + ); } -export function createDidPayload(verificationMethods: VerificationMethod[], verificationKeys: IVerificationKeys[]): DIDDocument { - if (!verificationMethods || verificationMethods.length === 0) - throw new Error('No verification methods provided') - if (!verificationKeys || verificationKeys.length === 0) - throw new Error('No verification keys provided') - - const did = verificationKeys[0].didUrl - return { - id: did, - controller: verificationKeys.map(key => key.didUrl), - verificationMethod: verificationMethods, - authentication: verificationKeys.map(key => key.keyId), - } as DIDDocument +export function createDidPayload( + verificationMethods: VerificationMethod[], + verificationKeys: IVerificationKeys[] +): DIDDocument { + if (!verificationMethods || verificationMethods.length === 0) throw new Error('No verification methods provided'); + if (!verificationKeys || verificationKeys.length === 0) throw new Error('No verification keys provided'); + + const did = verificationKeys[0].didUrl; + return { + id: did, + controller: verificationKeys.map((key) => key.didUrl), + verificationMethod: verificationMethods, + authentication: verificationKeys.map((key) => key.keyId), + } as DIDDocument; } export function validateSpecCompliantPayload(didDocument: DIDDocument): SpecValidationResult { - // id is required, validated on both compile and runtime - if (!didDocument?.id) return { valid: false, error: 'id is required' } - - // verificationMethod is required - if (!didDocument?.verificationMethod) return { valid: false, error: 'verificationMethod is required' } - - // verificationMethod must be an array - if (!Array.isArray(didDocument?.verificationMethod)) return { valid: false, error: 'verificationMethod must be an array' } - - // verificationMethod types must be supported - const protoVerificationMethod = didDocument.verificationMethod.map((vm) => { - switch (vm?.type) { - case VerificationMethods.Ed255192020: - if (!vm.publicKeyMultibase) throw new Error('publicKeyMultibase is required') - - return ProtoVerificationMethod.fromPartial({ - id: vm.id, - controller: vm.controller, - verificationMethodType: VerificationMethods.Ed255192020, - verificationMaterial: vm.publicKeyMultibase, - }) - case VerificationMethods.JWK: - if (!vm.publicKeyJwk) throw new Error('publicKeyJwk is required') - - return ProtoVerificationMethod.fromPartial({ - id: vm.id, - controller: vm.controller, - verificationMethodType: VerificationMethods.JWK, - verificationMaterial: JSON.stringify(vm.publicKeyJwk), - }) - case VerificationMethods.Ed255192018: - if (!vm.publicKeyBase58) throw new Error('publicKeyBase58 is required') - - return ProtoVerificationMethod.fromPartial({ - id: vm.id, - controller: vm.controller, - verificationMethodType: VerificationMethods.Ed255192018, - verificationMaterial: vm.publicKeyBase58, - }) - default: - throw new Error(`Unsupported verificationMethod type: ${vm?.type}`) - } - }) - - const protoService = didDocument?.service?.map((s) => { - return ProtoService.fromPartial({ - id: s?.id, - serviceType: s?.type, - serviceEndpoint: s?.serviceEndpoint, - }) - }) - - return { valid: true, protobufVerificationMethod: protoVerificationMethod, protobufService: protoService } + // id is required, validated on both compile and runtime + if (!didDocument?.id) return { valid: false, error: 'id is required' }; + + // verificationMethod is required + if (!didDocument?.verificationMethod) return { valid: false, error: 'verificationMethod is required' }; + + // verificationMethod must be an array + if (!Array.isArray(didDocument?.verificationMethod)) + return { valid: false, error: 'verificationMethod must be an array' }; + + // verificationMethod types must be supported + const protoVerificationMethod = didDocument.verificationMethod.map((vm) => { + switch (vm?.type) { + case VerificationMethods.Ed255192020: + if (!vm.publicKeyMultibase) throw new Error('publicKeyMultibase is required'); + + return ProtoVerificationMethod.fromPartial({ + id: vm.id, + controller: vm.controller, + verificationMethodType: VerificationMethods.Ed255192020, + verificationMaterial: vm.publicKeyMultibase, + }); + case VerificationMethods.JWK: + if (!vm.publicKeyJwk) throw new Error('publicKeyJwk is required'); + + return ProtoVerificationMethod.fromPartial({ + id: vm.id, + controller: vm.controller, + verificationMethodType: VerificationMethods.JWK, + verificationMaterial: JSON.stringify(vm.publicKeyJwk), + }); + case VerificationMethods.Ed255192018: + if (!vm.publicKeyBase58) throw new Error('publicKeyBase58 is required'); + + return ProtoVerificationMethod.fromPartial({ + id: vm.id, + controller: vm.controller, + verificationMethodType: VerificationMethods.Ed255192018, + verificationMaterial: vm.publicKeyBase58, + }); + default: + throw new Error(`Unsupported verificationMethod type: ${vm?.type}`); + } + }); + + const protoService = didDocument?.service?.map((s) => { + return ProtoService.fromPartial({ + id: s?.id, + serviceType: s?.type, + serviceEndpoint: s?.serviceEndpoint, + }); + }); + + return { valid: true, protobufVerificationMethod: protoVerificationMethod, protobufService: protoService }; } -export function createCosmosPayerWallet(cosmosPayerSeed: string) : Promise { - return EnglishMnemonic._mnemonicMatcher.test(cosmosPayerSeed) - ? DirectSecp256k1HdWallet.fromMnemonic(cosmosPayerSeed, { prefix: 'cheqd' }) - : DirectSecp256k1Wallet.fromKey(fromString(cosmosPayerSeed.replace(/^0x/, ''), 'hex'), 'cheqd') +export function createCosmosPayerWallet( + cosmosPayerSeed: string +): Promise { + return EnglishMnemonic._mnemonicMatcher.test(cosmosPayerSeed) + ? DirectSecp256k1HdWallet.fromMnemonic(cosmosPayerSeed, { prefix: 'cheqd' }) + : DirectSecp256k1Wallet.fromKey(fromString(cosmosPayerSeed.replace(/^0x/, ''), 'hex'), 'cheqd'); } export function toMultibaseRaw(key: Uint8Array) { - const multibase = new Uint8Array(MULTICODEC_ED25519_HEADER.length + key.length); + const multibase = new Uint8Array(MULTICODEC_ED25519_HEADER.length + key.length); - multibase.set(MULTICODEC_ED25519_HEADER); - multibase.set(key, MULTICODEC_ED25519_HEADER.length); + multibase.set(MULTICODEC_ED25519_HEADER); + multibase.set(key, MULTICODEC_ED25519_HEADER.length); - return bases['base58btc'].encode(multibase); + return bases['base58btc'].encode(multibase); } export async function createMsgCreateDidDocPayloadToSign(didPayload: DIDDocument, versionId: string) { - const { protobufVerificationMethod, protobufService } = await DIDModule.validateSpecCompliantPayload(didPayload) - return MsgCreateDidDocPayload.encode( - MsgCreateDidDocPayload.fromPartial({ - context: didPayload?.['@context'], - id: didPayload.id, - controller: didPayload.controller, - verificationMethod: protobufVerificationMethod, - authentication: didPayload.authentication, - assertionMethod: didPayload.assertionMethod, - capabilityInvocation: didPayload.capabilityInvocation, - capabilityDelegation: didPayload.capabilityDelegation, - keyAgreement: didPayload.keyAgreement, - service: protobufService, - alsoKnownAs: didPayload.alsoKnownAs, - versionId, - }) - ).finish() + const { protobufVerificationMethod, protobufService } = await DIDModule.validateSpecCompliantPayload(didPayload); + return MsgCreateDidDocPayload.encode( + MsgCreateDidDocPayload.fromPartial({ + context: didPayload?.['@context'], + id: didPayload.id, + controller: didPayload.controller, + verificationMethod: protobufVerificationMethod, + authentication: didPayload.authentication, + assertionMethod: didPayload.assertionMethod, + capabilityInvocation: didPayload.capabilityInvocation, + capabilityDelegation: didPayload.capabilityDelegation, + keyAgreement: didPayload.keyAgreement, + service: protobufService, + alsoKnownAs: didPayload.alsoKnownAs, + versionId, + }) + ).finish(); } -export const createMsgUpdateDidDocPayloadToSign = createMsgCreateDidDocPayloadToSign +export const createMsgUpdateDidDocPayloadToSign = createMsgCreateDidDocPayloadToSign; export function createMsgDeactivateDidDocPayloadToSign(didPayload: DIDDocument, versionId?: string) { - return MsgDeactivateDidDocPayload.encode( - MsgDeactivateDidDocPayload.fromPartial({ - id: didPayload.id, - versionId, - }) - ).finish() + return MsgDeactivateDidDocPayload.encode( + MsgDeactivateDidDocPayload.fromPartial({ + id: didPayload.id, + versionId, + }) + ).finish(); } export function createMsgResourcePayloadToSign(payload: Partial | MsgCreateResourcePayload) { - return MsgCreateResourcePayload.encode( - MsgCreateResourcePayload.fromPartial(payload) - ).finish() + return MsgCreateResourcePayload.encode(MsgCreateResourcePayload.fromPartial(payload)).finish(); } export function getCosmosAccount(publicKeyHex: string): string { - const { publicKeyConvert } = pkg - return toBech32('cheqd', rawSecp256k1PubkeyToRawAddress(publicKeyConvert(fromString(publicKeyHex, 'hex'), true))) + const { publicKeyConvert } = pkg; + return toBech32('cheqd', rawSecp256k1PubkeyToRawAddress(publicKeyConvert(fromString(publicKeyHex, 'hex'), true))); } export async function checkBalance(address: string, rpcAddress: string): Promise { - const client = await StargateClient.connect(rpcAddress) - return await client.getAllBalances(address) + const client = await StargateClient.connect(rpcAddress); + return await client.getAllBalances(address); } export function isJSON(input: any): boolean { - if (typeof input !== 'string') return false - try { - JSON.parse(input) - return true - } catch (e) { - return false - } -} \ No newline at end of file + if (typeof input !== 'string') return false; + try { + JSON.parse(input); + return true; + } catch (e) { + return false; + } +} diff --git a/tests/index.test.ts b/tests/index.test.ts index d2b5aeb9..fefe3809 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,155 +1,158 @@ -import { - DirectSecp256k1HdWallet, - GeneratedType -} from '@cosmjs/proto-signing' -import { - createCheqdSDK, - DIDModule, - ICheqdSDKOptions, - ResourceModule -} from '../src/index' -import { - localnet, - faucet -} from './testutils.test' -import { AbstractCheqdSDKModule } from '../src/modules/_' -import { CheqdSigningStargateClient } from '../src/signer' -import { createDefaultCheqdRegistry } from '../src/registry' -import { CheqdQuerier } from '../src/querier' -import { - setupDidExtension, - DidExtension, - defaultDidExtensionKey -} from '../src/modules/did'; -import { QueryExtensionSetup } from '../src/types' -import { - setupResourceExtension, - ResourceExtension, - defaultResourceExtensionKey -} from '../src/modules/resource' -import { jest } from '@jest/globals' - -describe( - 'CheqdSDK', () => { - describe('constructor', () => { - it('can be instantiated with modules', async () => { - const options = { - modules: [DIDModule as unknown as AbstractCheqdSDKModule], - rpcUrl: localnet.rpcUrl, - wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - } as ICheqdSDKOptions - const cheqdSDK = await createCheqdSDK(options) - - const sdkMethods = Object.keys(cheqdSDK.methods) - const testSigner = await CheqdSigningStargateClient.connectWithSigner(options.rpcUrl, options.wallet) - const testQuerier = await CheqdQuerier.connectWithExtension(options.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const moduleMethods = Object.keys(new DIDModule(testSigner, testQuerier).methods) - - moduleMethods.forEach((method) => { - expect(sdkMethods).toContain(method) - }) - }) - - it('should use module methods', async () => { - const rpcUrl = localnet.rpcUrl - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - - class TestModule extends AbstractCheqdSDKModule { - registryTypes: Iterable<[string, GeneratedType]> = [] - methods = { - doSomething: this.doSomething.bind(this) - } - constructor(signer: CheqdSigningStargateClient, querier: CheqdQuerier) { - super(signer, querier) - } - public getRegistryTypes(): Iterable<[string, GeneratedType]> { - return TestModule.registryTypes - } - public getQuerierExtensionSetup(): QueryExtensionSetup<{}> { - return () => ({}) - } - async doSomething(): Promise { - return 'did something' - } - } - const options = { - modules: [TestModule as unknown as AbstractCheqdSDKModule], - rpcUrl, - wallet - } as ICheqdSDKOptions - - const cheqdSDK = await createCheqdSDK(options) - - //@ts-ignore - const doSomething = await cheqdSDK.doSomething() - expect(doSomething).toBe('did something') - - const spy = jest.spyOn(cheqdSDK.methods, 'doSomething') - //@ts-ignore - await cheqdSDK.doSomething() - expect(spy).toHaveBeenCalled() - }) - - it('should instantiate registry from passed modules', async () => { - const options = { - modules: [DIDModule as unknown as AbstractCheqdSDKModule], - rpcUrl: localnet.rpcUrl, - wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - } as ICheqdSDKOptions - const cheqdSDK = await createCheqdSDK(options) - - const didRegistryTypes = DIDModule.registryTypes - const cheqdRegistry = createDefaultCheqdRegistry(didRegistryTypes) - - expect(cheqdSDK.signer.registry).toStrictEqual(cheqdRegistry) - }) - - it('should instantiate registry from multiple passed modules', async () => { - const options = { - modules: [DIDModule as unknown as AbstractCheqdSDKModule, ResourceModule as unknown as AbstractCheqdSDKModule], - rpcUrl: localnet.rpcUrl, - wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - } as ICheqdSDKOptions - const cheqdSDK = await createCheqdSDK(options) - - const didRegistryTypes = DIDModule.registryTypes - const resourceRegistryTypes = ResourceModule.registryTypes - const cheqdRegistry = createDefaultCheqdRegistry([...didRegistryTypes, ...resourceRegistryTypes]) - - expect(cheqdSDK.signer.registry).toStrictEqual(cheqdRegistry) - }) - - it('should instantiate querier extension from passed modules', async () => { - const options = { - modules: [DIDModule as unknown as AbstractCheqdSDKModule], - rpcUrl: localnet.rpcUrl, - wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - } as ICheqdSDKOptions - const cheqdSDK = await createCheqdSDK(options) - - const querier = await CheqdQuerier.connectWithExtension(options.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - - // we need to stringify the querier extension because it's a proxy object - // and the equality check will fail - expect(JSON.stringify(cheqdSDK.querier[defaultDidExtensionKey])).toStrictEqual(JSON.stringify(querier[defaultDidExtensionKey])) - }) - - it('should instantiate querier extension from multiple passed modules', async () => { - const options = { - modules: [DIDModule as unknown as AbstractCheqdSDKModule, ResourceModule as unknown as AbstractCheqdSDKModule], - rpcUrl: localnet.rpcUrl, - wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - } as ICheqdSDKOptions - const cheqdSDK = await createCheqdSDK(options) - - const didQuerier = await CheqdQuerier.connectWithExtension(options.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const resourceQuerier = await CheqdQuerier.connectWithExtension(options.rpcUrl, setupResourceExtension) as CheqdQuerier & ResourceExtension - - // we need to stringify the querier extension because it's a proxy object - // and the equality check will fail - expect(JSON.stringify(cheqdSDK.querier[defaultDidExtensionKey])).toStrictEqual(JSON.stringify(didQuerier[defaultDidExtensionKey])) - expect(JSON.stringify(cheqdSDK.querier[defaultResourceExtensionKey])).toStrictEqual(JSON.stringify(resourceQuerier[defaultResourceExtensionKey])) - }) - }) - } -) \ No newline at end of file +import { DirectSecp256k1HdWallet, GeneratedType } from '@cosmjs/proto-signing'; +import { createCheqdSDK, DIDModule, ICheqdSDKOptions, ResourceModule } from '../src/index'; +import { localnet, faucet } from './testutils.test'; +import { AbstractCheqdSDKModule } from '../src/modules/_'; +import { CheqdSigningStargateClient } from '../src/signer'; +import { createDefaultCheqdRegistry } from '../src/registry'; +import { CheqdQuerier } from '../src/querier'; +import { setupDidExtension, DidExtension, defaultDidExtensionKey } from '../src/modules/did'; +import { QueryExtensionSetup } from '../src/types'; +import { setupResourceExtension, ResourceExtension, defaultResourceExtensionKey } from '../src/modules/resource'; +import { jest } from '@jest/globals'; + +describe('CheqdSDK', () => { + describe('constructor', () => { + it('can be instantiated with modules', async () => { + const options = { + modules: [DIDModule as unknown as AbstractCheqdSDKModule], + rpcUrl: localnet.rpcUrl, + wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic), + } as ICheqdSDKOptions; + const cheqdSDK = await createCheqdSDK(options); + + const sdkMethods = Object.keys(cheqdSDK.methods); + const testSigner = await CheqdSigningStargateClient.connectWithSigner(options.rpcUrl, options.wallet); + const testQuerier = (await CheqdQuerier.connectWithExtension( + options.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const moduleMethods = Object.keys(new DIDModule(testSigner, testQuerier).methods); + + moduleMethods.forEach((method) => { + expect(sdkMethods).toContain(method); + }); + }); + + it('should use module methods', async () => { + const rpcUrl = localnet.rpcUrl; + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + + class TestModule extends AbstractCheqdSDKModule { + registryTypes: Iterable<[string, GeneratedType]> = []; + methods = { + doSomething: this.doSomething.bind(this), + }; + constructor(signer: CheqdSigningStargateClient, querier: CheqdQuerier) { + super(signer, querier); + } + public getRegistryTypes(): Iterable<[string, GeneratedType]> { + return TestModule.registryTypes; + } + public getQuerierExtensionSetup(): QueryExtensionSetup<{}> { + return () => ({}); + } + async doSomething(): Promise { + return 'did something'; + } + } + const options = { + modules: [TestModule as unknown as AbstractCheqdSDKModule], + rpcUrl, + wallet, + } as ICheqdSDKOptions; + + const cheqdSDK = await createCheqdSDK(options); + + //@ts-ignore + const doSomething = await cheqdSDK.doSomething(); + expect(doSomething).toBe('did something'); + + const spy = jest.spyOn(cheqdSDK.methods, 'doSomething'); + //@ts-ignore + await cheqdSDK.doSomething(); + expect(spy).toHaveBeenCalled(); + }); + + it('should instantiate registry from passed modules', async () => { + const options = { + modules: [DIDModule as unknown as AbstractCheqdSDKModule], + rpcUrl: localnet.rpcUrl, + wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic), + } as ICheqdSDKOptions; + const cheqdSDK = await createCheqdSDK(options); + + const didRegistryTypes = DIDModule.registryTypes; + const cheqdRegistry = createDefaultCheqdRegistry(didRegistryTypes); + + expect(cheqdSDK.signer.registry).toStrictEqual(cheqdRegistry); + }); + + it('should instantiate registry from multiple passed modules', async () => { + const options = { + modules: [ + DIDModule as unknown as AbstractCheqdSDKModule, + ResourceModule as unknown as AbstractCheqdSDKModule, + ], + rpcUrl: localnet.rpcUrl, + wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic), + } as ICheqdSDKOptions; + const cheqdSDK = await createCheqdSDK(options); + + const didRegistryTypes = DIDModule.registryTypes; + const resourceRegistryTypes = ResourceModule.registryTypes; + const cheqdRegistry = createDefaultCheqdRegistry([...didRegistryTypes, ...resourceRegistryTypes]); + + expect(cheqdSDK.signer.registry).toStrictEqual(cheqdRegistry); + }); + + it('should instantiate querier extension from passed modules', async () => { + const options = { + modules: [DIDModule as unknown as AbstractCheqdSDKModule], + rpcUrl: localnet.rpcUrl, + wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic), + } as ICheqdSDKOptions; + const cheqdSDK = await createCheqdSDK(options); + + const querier = (await CheqdQuerier.connectWithExtension( + options.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + + // we need to stringify the querier extension because it's a proxy object + // and the equality check will fail + expect(JSON.stringify(cheqdSDK.querier[defaultDidExtensionKey])).toStrictEqual( + JSON.stringify(querier[defaultDidExtensionKey]) + ); + }); + + it('should instantiate querier extension from multiple passed modules', async () => { + const options = { + modules: [ + DIDModule as unknown as AbstractCheqdSDKModule, + ResourceModule as unknown as AbstractCheqdSDKModule, + ], + rpcUrl: localnet.rpcUrl, + wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic), + } as ICheqdSDKOptions; + const cheqdSDK = await createCheqdSDK(options); + + const didQuerier = (await CheqdQuerier.connectWithExtension( + options.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const resourceQuerier = (await CheqdQuerier.connectWithExtension( + options.rpcUrl, + setupResourceExtension + )) as CheqdQuerier & ResourceExtension; + + // we need to stringify the querier extension because it's a proxy object + // and the equality check will fail + expect(JSON.stringify(cheqdSDK.querier[defaultDidExtensionKey])).toStrictEqual( + JSON.stringify(didQuerier[defaultDidExtensionKey]) + ); + expect(JSON.stringify(cheqdSDK.querier[defaultResourceExtensionKey])).toStrictEqual( + JSON.stringify(resourceQuerier[defaultResourceExtensionKey]) + ); + }); + }); +}); diff --git a/tests/modules/did.test.ts b/tests/modules/did.test.ts index 3edf6ad9..86afe49c 100644 --- a/tests/modules/did.test.ts +++ b/tests/modules/did.test.ts @@ -1,985 +1,1217 @@ -import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing" -import { DeliverTxResponse } from "@cosmjs/stargate" +import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing'; +import { DeliverTxResponse } from '@cosmjs/stargate'; +import { fromString, toString } from 'uint8arrays'; +import { DIDModule } from '../../src'; +import { createDefaultCheqdRegistry } from '../../src/registry'; +import { CheqdSigningStargateClient } from '../../src/signer'; +import { DIDDocument, ISignInputs, MethodSpecificIdAlgo, VerificationMethods } from '../../src/types'; import { - fromString, - toString -} from 'uint8arrays' -import { DIDModule } from "../../src" -import { createDefaultCheqdRegistry } from "../../src/registry" -import { CheqdSigningStargateClient } from "../../src/signer" -import { - DIDDocument, - ISignInputs, - MethodSpecificIdAlgo, - VerificationMethods -} from "../../src/types" -import { - createDidPayload, - createDidVerificationMethod, - createKeyPairBase64, - createVerificationKeys -} from "../../src/utils" -import { - localnet, - faucet, - containsAll -} from "../testutils.test" + createDidPayload, + createDidVerificationMethod, + createKeyPairBase64, + createVerificationKeys, +} from '../../src/utils'; +import { localnet, faucet, containsAll } from '../testutils.test'; import { CheqdQuerier } from '../../src/querier'; -import { - setupDidExtension, - DidExtension -} from '../../src/modules/did'; -import { v4 } from "uuid" +import { setupDidExtension, DidExtension } from '../../src/modules/did'; +import { v4 } from 'uuid'; -const defaultAsyncTxTimeout = 30000 +const defaultAsyncTxTimeout = 30000; describe('DIDModule', () => { - describe('constructor', () => { - it('should instantiate standalone module', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - expect(didModule).toBeInstanceOf(DIDModule) - }) - }) - - describe('createDidDocTx', () => { - it('should create a new multibase DID - case: Ed25519VerificationKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should create a new multibase DID - case: Ed25519VerificationKey2018', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192018], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should create a new multibase DID - case: JsonWebKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should create a new uuid DID - case: Ed25519VerificationKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Uuid, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should create a new uuid DID - case: Ed25519VerificationKey2018', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Uuid, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192018], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should create a new uuid DID - case: JsonWebKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Uuid, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - }, defaultAsyncTxTimeout) - }) - - describe('updateDidDocTx', () => { - it('should update a DID - case: Ed25519VerificationKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // update the did document - const updateDidPayload = { - '@context': didPayload?.['@context'], - id: didPayload.id, - controller: didPayload.controller, - verificationMethod: didPayload.verificationMethod, - authentication: didPayload.authentication, - assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference - } as DIDDocument - - const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer) - const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( - signInputs, - updateDidPayload, - feePayer, - feeUpdate - ) - - console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`) - - expect(updateDidDocTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should update a DID - case: Ed25519VerificationKey2018', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192018], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // update the did document - const updateDidPayload = { - '@context': didPayload?.['@context'], - id: didPayload.id, - controller: didPayload.controller, - verificationMethod: didPayload.verificationMethod, - authentication: didPayload.authentication, - assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference - } as DIDDocument - - const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer) - - const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( - signInputs, - updateDidPayload, - feePayer, - feeUpdate - ) - - console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`) - - expect(updateDidDocTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should update a DID - case: JsonWebKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // update the did document - const updateDidPayload = { - '@context': didPayload?.['@context'], - id: didPayload.id, - controller: didPayload.controller, - verificationMethod: didPayload.verificationMethod, - authentication: didPayload.authentication, - assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference - } as DIDDocument - - const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer) - - const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( - signInputs, - updateDidPayload, - feePayer, - feeUpdate - ) - - console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`) - - expect(updateDidDocTx.code).toBe(0) - }, defaultAsyncTxTimeout) - }) - - describe('deactivateDidDocTx', () => { - it('should deactivate a DID - case: Ed25519VerificationKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // deactivate the did document - const deactivateDidPayload = { - id: didPayload.id, - verificationMethod: didPayload.verificationMethod, - } as DIDDocument - - const feeDeactivate = await DIDModule.generateDeactivateDidDocFees(feePayer) - - const deactivateDidDocTx: DeliverTxResponse = await didModule.deactivateDidDocTx( - signInputs, - deactivateDidPayload, - feePayer, - feeDeactivate - ) - - console.warn(`Using payload: ${JSON.stringify(deactivateDidPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(deactivateDidDocTx)}`) - - expect(deactivateDidDocTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should deactivate a DID - case: Ed25519VerificationKey2018', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192018], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // deactivate the did document - const deactivateDidPayload = { - id: didPayload.id, - verificationMethod: didPayload.verificationMethod, - } as DIDDocument - - const feeDeactivate = await DIDModule.generateDeactivateDidDocFees(feePayer) - - const deactivateDidDocTx: DeliverTxResponse = await didModule.deactivateDidDocTx( - signInputs, - deactivateDidPayload, - feePayer, - feeDeactivate - ) - - console.warn(`Using payload: ${JSON.stringify(deactivateDidPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(deactivateDidDocTx)}`) - - expect(deactivateDidDocTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should deactivate a DID - case: JsonWebKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // deactivate the did document - const deactivateDidPayload = { - id: didPayload.id, - verificationMethod: didPayload.verificationMethod, - } as DIDDocument - - const feeDeactivate = await DIDModule.generateDeactivateDidDocFees(feePayer) - - const deactivateDidDocTx: DeliverTxResponse = await didModule.deactivateDidDocTx( - signInputs, - deactivateDidPayload, - feePayer, - feeDeactivate - ) - - console.warn(`Using payload: ${JSON.stringify(deactivateDidPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(deactivateDidDocTx)}`) - - expect(deactivateDidDocTx.code).toBe(0) - }, defaultAsyncTxTimeout) - }) - - describe('queryDidDoc', () => { - it('should query a DID document - case: Ed25519VerificationKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - const didDoc = await didModule.queryDidDoc(didPayload.id) - - expect(didDoc.didDocument!.id).toEqual(didPayload.id) - expect(didDoc.didDocument!.controller).toEqual(didPayload.controller) - expect(didDoc.didDocument!.verificationMethod).toEqual(didPayload.verificationMethod) - - // we keep 1-1 relationship of omitempty fields in proto and spec compliant json - // while converting from proto to spec compliant json, we remove omitempty fields - // as in a resolved did document - expect(didDoc.didDocument?.authentication).toEqual(didPayload?.authentication) - expect(didDoc.didDocument?.assertionMethod).toEqual(didPayload?.assertionMethod) - expect(didDoc.didDocument?.capabilityInvocation).toEqual(didPayload?.capabilityInvocation) - expect(didDoc.didDocument?.capabilityDelegation).toEqual(didPayload?.capabilityDelegation) - expect(didDoc.didDocument?.keyAgreement).toEqual(didPayload?.keyAgreement) - expect(didDoc.didDocument?.service).toEqual(didPayload?.service) - expect(didDoc.didDocument?.alsoKnownAs).toEqual(didPayload?.alsoKnownAs) - }, defaultAsyncTxTimeout) - - it('should query a DID document - case: Ed25519VerificationKey2018', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192018], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - const didDoc = await didModule.queryDidDoc(didPayload.id) - - expect(didDoc.didDocument!.id).toEqual(didPayload.id) - expect(didDoc.didDocument!.controller).toEqual(didPayload.controller) - expect(didDoc.didDocument!.verificationMethod).toEqual(didPayload.verificationMethod) - - // we keep 1-1 relationship of omitempty fields in proto and spec compliant json - // while converting from proto to spec compliant json, we remove omitempty fields - // as in a resolved did document - expect(didDoc.didDocument?.authentication).toEqual(didPayload?.authentication) - expect(didDoc.didDocument?.assertionMethod).toEqual(didPayload?.assertionMethod) - expect(didDoc.didDocument?.capabilityInvocation).toEqual(didPayload?.capabilityInvocation) - expect(didDoc.didDocument?.capabilityDelegation).toEqual(didPayload?.capabilityDelegation) - expect(didDoc.didDocument?.keyAgreement).toEqual(didPayload?.keyAgreement) - expect(didDoc.didDocument?.service).toEqual(didPayload?.service) - expect(didDoc.didDocument?.alsoKnownAs).toEqual(didPayload?.alsoKnownAs) - }, defaultAsyncTxTimeout) - - it('should query a DID document - case: JsonWebKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - const didDoc = await didModule.queryDidDoc(didPayload.id) - - expect(didDoc.didDocument!.id).toEqual(didPayload.id) - expect(didDoc.didDocument!.controller).toEqual(didPayload.controller) - expect(didDoc.didDocument!.verificationMethod).toEqual(didPayload.verificationMethod) - - // we keep 1-1 relationship of omitempty fields in proto and spec compliant json - // while converting from proto to spec compliant json, we remove omitempty fields - // as in a resolved did document - expect(didDoc.didDocument?.authentication).toEqual(didPayload?.authentication) - expect(didDoc.didDocument?.assertionMethod).toEqual(didPayload?.assertionMethod) - expect(didDoc.didDocument?.capabilityInvocation).toEqual(didPayload?.capabilityInvocation) - expect(didDoc.didDocument?.capabilityDelegation).toEqual(didPayload?.capabilityDelegation) - expect(didDoc.didDocument?.keyAgreement).toEqual(didPayload?.keyAgreement) - expect(didDoc.didDocument?.service).toEqual(didPayload?.service) - expect(didDoc.didDocument?.alsoKnownAs).toEqual(didPayload?.alsoKnownAs) - }, defaultAsyncTxTimeout) - }) - - describe('queryDidDocVersion', () => { - it('should query a DID document version - case: Ed25519VerificationKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const versionId = v4() - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee, - undefined, - versionId - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - const didDocVersion = await didModule.queryDidDocVersion(didPayload.id, versionId) - - expect(didDocVersion.didDocument!.id).toEqual(didPayload.id) - expect(didDocVersion.didDocument!.controller).toEqual(didPayload.controller) - expect(didDocVersion.didDocument!.verificationMethod).toEqual(didPayload.verificationMethod) - - // we keep 1-1 relationship of omitempty fields in proto and spec compliant json - // while converting from proto to spec compliant json, we remove omitempty fields - // as in a resolved did document - expect(didDocVersion.didDocument?.authentication).toEqual(didPayload?.authentication) - expect(didDocVersion.didDocument?.assertionMethod).toEqual(didPayload?.assertionMethod) - expect(didDocVersion.didDocument?.capabilityInvocation).toEqual(didPayload?.capabilityInvocation) - expect(didDocVersion.didDocument?.capabilityDelegation).toEqual(didPayload?.capabilityDelegation) - expect(didDocVersion.didDocument?.keyAgreement).toEqual(didPayload?.keyAgreement) - expect(didDocVersion.didDocument?.service).toEqual(didPayload?.service) - expect(didDocVersion.didDocument?.alsoKnownAs).toEqual(didPayload?.alsoKnownAs) - - expect(didDocVersion.didDocumentMetadata.versionId).toEqual(versionId) - }, defaultAsyncTxTimeout) - }) - - describe('queryAllDidDocVersionsMetadata', () => { - it('should query all DID document versions metadata - case: Ed25519VerificationKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const versionId = v4() - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee, - undefined, - versionId - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // update the did document - const updateVersionId = v4() - const updateDidPayload = { - '@context': didPayload?.['@context'], - id: didPayload.id, - controller: didPayload.controller, - verificationMethod: didPayload.verificationMethod, - authentication: didPayload.authentication, - assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference - } as DIDDocument - - const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer) - const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( - signInputs, - updateDidPayload, - feePayer, - feeUpdate, - undefined, - updateVersionId - ) - - console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`) - - expect(updateDidDocTx.code).toBe(0) - - const didDocVersionsMetadata = await didModule.queryAllDidDocVersionsMetadata(didPayload.id) - - expect(didDocVersionsMetadata.didDocumentVersionsMetadata).toHaveLength(2) - expect(containsAll([didDocVersionsMetadata.didDocumentVersionsMetadata[0].versionId, didDocVersionsMetadata.didDocumentVersionsMetadata[1].versionId], [versionId, updateVersionId])).toBe(true) - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].created).toBeDefined() - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].created).toBeDefined() - expect(containsAll([didDocVersionsMetadata.didDocumentVersionsMetadata[0]?.updated, didDocVersionsMetadata.didDocumentVersionsMetadata[1]?.updated], [undefined])).toBe(true) - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].deactivated).toBe(false) - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].deactivated).toBe(false) - }, defaultAsyncTxTimeout) - - it('should query all DID document versions metadata - case: JsonWebKey2020', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const versionId = v4() - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee, - undefined, - versionId - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // update the did document - const updateVersionId = v4() - const updateDidPayload = { - '@context': didPayload?.['@context'], - id: didPayload.id, - controller: didPayload.controller, - verificationMethod: didPayload.verificationMethod, - authentication: didPayload.authentication, - assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference - } as DIDDocument - - const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer) - const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( - signInputs, - updateDidPayload, - feePayer, - feeUpdate, - undefined, - updateVersionId - ) - - console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`) - - expect(updateDidDocTx.code).toBe(0) - - const didDocVersionsMetadata = await didModule.queryAllDidDocVersionsMetadata(didPayload.id) - - expect(didDocVersionsMetadata.didDocumentVersionsMetadata).toHaveLength(2) - expect(containsAll([didDocVersionsMetadata.didDocumentVersionsMetadata[0].versionId, didDocVersionsMetadata.didDocumentVersionsMetadata[1].versionId], [versionId, updateVersionId])).toBe(true) - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].created).toBeDefined() - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].created).toBeDefined() - expect(containsAll([didDocVersionsMetadata.didDocumentVersionsMetadata[0]?.updated, didDocVersionsMetadata.didDocumentVersionsMetadata[1]?.updated], [undefined])).toBe(true) - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].deactivated).toBe(false) - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].deactivated).toBe(false) - }, defaultAsyncTxTimeout) - - it('should query all DID document versions metadata - case: Ed25519VerificationKey2018', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(DIDModule.registryTypes) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupDidExtension) as CheqdQuerier & DidExtension - const didModule = new DIDModule(signer, querier) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const versionId = v4() - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee, - undefined, - versionId - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // update the did document - const updateVersionId = v4() - const updateDidPayload = { - '@context': didPayload?.['@context'], - id: didPayload.id, - controller: didPayload.controller, - verificationMethod: didPayload.verificationMethod, - authentication: didPayload.authentication, - assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference - } as DIDDocument - - const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer) - const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( - signInputs, - updateDidPayload, - feePayer, - feeUpdate, - undefined, - updateVersionId - ) - - console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`) - - expect(updateDidDocTx.code).toBe(0) - - const didDocVersionsMetadata = await didModule.queryAllDidDocVersionsMetadata(didPayload.id) - - expect(didDocVersionsMetadata.didDocumentVersionsMetadata).toHaveLength(2) - expect(containsAll([didDocVersionsMetadata.didDocumentVersionsMetadata[0].versionId, didDocVersionsMetadata.didDocumentVersionsMetadata[1].versionId], [versionId, updateVersionId])).toBe(true) - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].created).toBeDefined() - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].created).toBeDefined() - expect(containsAll([didDocVersionsMetadata.didDocumentVersionsMetadata[0]?.updated, didDocVersionsMetadata.didDocumentVersionsMetadata[1]?.updated], [undefined])).toBe(true) - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].deactivated).toBe(false) - expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].deactivated).toBe(false) - }, defaultAsyncTxTimeout) - }) -}) \ No newline at end of file + describe('constructor', () => { + it('should instantiate standalone module', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + expect(didModule).toBeInstanceOf(DIDModule); + }); + }); + + describe('createDidDocTx', () => { + it( + 'should create a new multibase DID - case: Ed25519VerificationKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should create a new multibase DID - case: Ed25519VerificationKey2018', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192018], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should create a new multibase DID - case: JsonWebKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should create a new uuid DID - case: Ed25519VerificationKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Uuid, 'key-1'); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should create a new uuid DID - case: Ed25519VerificationKey2018', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Uuid, 'key-1'); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192018], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should create a new uuid DID - case: JsonWebKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Uuid, 'key-1'); + const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + }); + + describe('updateDidDocTx', () => { + it( + 'should update a DID - case: Ed25519VerificationKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // update the did document + const updateDidPayload = { + '@context': didPayload?.['@context'], + id: didPayload.id, + controller: didPayload.controller, + verificationMethod: didPayload.verificationMethod, + authentication: didPayload.authentication, + assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference + } as DIDDocument; + + const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer); + const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( + signInputs, + updateDidPayload, + feePayer, + feeUpdate + ); + + console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`); + + expect(updateDidDocTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should update a DID - case: Ed25519VerificationKey2018', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192018], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // update the did document + const updateDidPayload = { + '@context': didPayload?.['@context'], + id: didPayload.id, + controller: didPayload.controller, + verificationMethod: didPayload.verificationMethod, + authentication: didPayload.authentication, + assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference + } as DIDDocument; + + const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer); + + const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( + signInputs, + updateDidPayload, + feePayer, + feeUpdate + ); + + console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`); + + expect(updateDidDocTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should update a DID - case: JsonWebKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // update the did document + const updateDidPayload = { + '@context': didPayload?.['@context'], + id: didPayload.id, + controller: didPayload.controller, + verificationMethod: didPayload.verificationMethod, + authentication: didPayload.authentication, + assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference + } as DIDDocument; + + const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer); + + const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( + signInputs, + updateDidPayload, + feePayer, + feeUpdate + ); + + console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`); + + expect(updateDidDocTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + }); + + describe('deactivateDidDocTx', () => { + it( + 'should deactivate a DID - case: Ed25519VerificationKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // deactivate the did document + const deactivateDidPayload = { + id: didPayload.id, + verificationMethod: didPayload.verificationMethod, + } as DIDDocument; + + const feeDeactivate = await DIDModule.generateDeactivateDidDocFees(feePayer); + + const deactivateDidDocTx: DeliverTxResponse = await didModule.deactivateDidDocTx( + signInputs, + deactivateDidPayload, + feePayer, + feeDeactivate + ); + + console.warn(`Using payload: ${JSON.stringify(deactivateDidPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(deactivateDidDocTx)}`); + + expect(deactivateDidDocTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should deactivate a DID - case: Ed25519VerificationKey2018', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192018], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // deactivate the did document + const deactivateDidPayload = { + id: didPayload.id, + verificationMethod: didPayload.verificationMethod, + } as DIDDocument; + + const feeDeactivate = await DIDModule.generateDeactivateDidDocFees(feePayer); + + const deactivateDidDocTx: DeliverTxResponse = await didModule.deactivateDidDocTx( + signInputs, + deactivateDidPayload, + feePayer, + feeDeactivate + ); + + console.warn(`Using payload: ${JSON.stringify(deactivateDidPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(deactivateDidDocTx)}`); + + expect(deactivateDidDocTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should deactivate a DID - case: JsonWebKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // deactivate the did document + const deactivateDidPayload = { + id: didPayload.id, + verificationMethod: didPayload.verificationMethod, + } as DIDDocument; + + const feeDeactivate = await DIDModule.generateDeactivateDidDocFees(feePayer); + + const deactivateDidDocTx: DeliverTxResponse = await didModule.deactivateDidDocTx( + signInputs, + deactivateDidPayload, + feePayer, + feeDeactivate + ); + + console.warn(`Using payload: ${JSON.stringify(deactivateDidPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(deactivateDidDocTx)}`); + + expect(deactivateDidDocTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + }); + + describe('queryDidDoc', () => { + it( + 'should query a DID document - case: Ed25519VerificationKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + const didDoc = await didModule.queryDidDoc(didPayload.id); + + expect(didDoc.didDocument!.id).toEqual(didPayload.id); + expect(didDoc.didDocument!.controller).toEqual(didPayload.controller); + expect(didDoc.didDocument!.verificationMethod).toEqual(didPayload.verificationMethod); + + // we keep 1-1 relationship of omitempty fields in proto and spec compliant json + // while converting from proto to spec compliant json, we remove omitempty fields + // as in a resolved did document + expect(didDoc.didDocument?.authentication).toEqual(didPayload?.authentication); + expect(didDoc.didDocument?.assertionMethod).toEqual(didPayload?.assertionMethod); + expect(didDoc.didDocument?.capabilityInvocation).toEqual(didPayload?.capabilityInvocation); + expect(didDoc.didDocument?.capabilityDelegation).toEqual(didPayload?.capabilityDelegation); + expect(didDoc.didDocument?.keyAgreement).toEqual(didPayload?.keyAgreement); + expect(didDoc.didDocument?.service).toEqual(didPayload?.service); + expect(didDoc.didDocument?.alsoKnownAs).toEqual(didPayload?.alsoKnownAs); + }, + defaultAsyncTxTimeout + ); + + it( + 'should query a DID document - case: Ed25519VerificationKey2018', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192018], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + const didDoc = await didModule.queryDidDoc(didPayload.id); + + expect(didDoc.didDocument!.id).toEqual(didPayload.id); + expect(didDoc.didDocument!.controller).toEqual(didPayload.controller); + expect(didDoc.didDocument!.verificationMethod).toEqual(didPayload.verificationMethod); + + // we keep 1-1 relationship of omitempty fields in proto and spec compliant json + // while converting from proto to spec compliant json, we remove omitempty fields + // as in a resolved did document + expect(didDoc.didDocument?.authentication).toEqual(didPayload?.authentication); + expect(didDoc.didDocument?.assertionMethod).toEqual(didPayload?.assertionMethod); + expect(didDoc.didDocument?.capabilityInvocation).toEqual(didPayload?.capabilityInvocation); + expect(didDoc.didDocument?.capabilityDelegation).toEqual(didPayload?.capabilityDelegation); + expect(didDoc.didDocument?.keyAgreement).toEqual(didPayload?.keyAgreement); + expect(didDoc.didDocument?.service).toEqual(didPayload?.service); + expect(didDoc.didDocument?.alsoKnownAs).toEqual(didPayload?.alsoKnownAs); + }, + defaultAsyncTxTimeout + ); + + it( + 'should query a DID document - case: JsonWebKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + const didDoc = await didModule.queryDidDoc(didPayload.id); + + expect(didDoc.didDocument!.id).toEqual(didPayload.id); + expect(didDoc.didDocument!.controller).toEqual(didPayload.controller); + expect(didDoc.didDocument!.verificationMethod).toEqual(didPayload.verificationMethod); + + // we keep 1-1 relationship of omitempty fields in proto and spec compliant json + // while converting from proto to spec compliant json, we remove omitempty fields + // as in a resolved did document + expect(didDoc.didDocument?.authentication).toEqual(didPayload?.authentication); + expect(didDoc.didDocument?.assertionMethod).toEqual(didPayload?.assertionMethod); + expect(didDoc.didDocument?.capabilityInvocation).toEqual(didPayload?.capabilityInvocation); + expect(didDoc.didDocument?.capabilityDelegation).toEqual(didPayload?.capabilityDelegation); + expect(didDoc.didDocument?.keyAgreement).toEqual(didPayload?.keyAgreement); + expect(didDoc.didDocument?.service).toEqual(didPayload?.service); + expect(didDoc.didDocument?.alsoKnownAs).toEqual(didPayload?.alsoKnownAs); + }, + defaultAsyncTxTimeout + ); + }); + + describe('queryDidDocVersion', () => { + it( + 'should query a DID document version - case: Ed25519VerificationKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const versionId = v4(); + const didTx: DeliverTxResponse = await didModule.createDidDocTx( + signInputs, + didPayload, + feePayer, + fee, + undefined, + versionId + ); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + const didDocVersion = await didModule.queryDidDocVersion(didPayload.id, versionId); + + expect(didDocVersion.didDocument!.id).toEqual(didPayload.id); + expect(didDocVersion.didDocument!.controller).toEqual(didPayload.controller); + expect(didDocVersion.didDocument!.verificationMethod).toEqual(didPayload.verificationMethod); + + // we keep 1-1 relationship of omitempty fields in proto and spec compliant json + // while converting from proto to spec compliant json, we remove omitempty fields + // as in a resolved did document + expect(didDocVersion.didDocument?.authentication).toEqual(didPayload?.authentication); + expect(didDocVersion.didDocument?.assertionMethod).toEqual(didPayload?.assertionMethod); + expect(didDocVersion.didDocument?.capabilityInvocation).toEqual(didPayload?.capabilityInvocation); + expect(didDocVersion.didDocument?.capabilityDelegation).toEqual(didPayload?.capabilityDelegation); + expect(didDocVersion.didDocument?.keyAgreement).toEqual(didPayload?.keyAgreement); + expect(didDocVersion.didDocument?.service).toEqual(didPayload?.service); + expect(didDocVersion.didDocument?.alsoKnownAs).toEqual(didPayload?.alsoKnownAs); + + expect(didDocVersion.didDocumentMetadata.versionId).toEqual(versionId); + }, + defaultAsyncTxTimeout + ); + }); + + describe('queryAllDidDocVersionsMetadata', () => { + it( + 'should query all DID document versions metadata - case: Ed25519VerificationKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const versionId = v4(); + const didTx: DeliverTxResponse = await didModule.createDidDocTx( + signInputs, + didPayload, + feePayer, + fee, + undefined, + versionId + ); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // update the did document + const updateVersionId = v4(); + const updateDidPayload = { + '@context': didPayload?.['@context'], + id: didPayload.id, + controller: didPayload.controller, + verificationMethod: didPayload.verificationMethod, + authentication: didPayload.authentication, + assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference + } as DIDDocument; + + const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer); + const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( + signInputs, + updateDidPayload, + feePayer, + feeUpdate, + undefined, + updateVersionId + ); + + console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`); + + expect(updateDidDocTx.code).toBe(0); + + const didDocVersionsMetadata = await didModule.queryAllDidDocVersionsMetadata(didPayload.id); + + expect(didDocVersionsMetadata.didDocumentVersionsMetadata).toHaveLength(2); + expect( + containsAll( + [ + didDocVersionsMetadata.didDocumentVersionsMetadata[0].versionId, + didDocVersionsMetadata.didDocumentVersionsMetadata[1].versionId, + ], + [versionId, updateVersionId] + ) + ).toBe(true); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].created).toBeDefined(); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].created).toBeDefined(); + expect( + containsAll( + [ + didDocVersionsMetadata.didDocumentVersionsMetadata[0]?.updated, + didDocVersionsMetadata.didDocumentVersionsMetadata[1]?.updated, + ], + [undefined] + ) + ).toBe(true); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].deactivated).toBe(false); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].deactivated).toBe(false); + }, + defaultAsyncTxTimeout + ); + + it( + 'should query all DID document versions metadata - case: JsonWebKey2020', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const versionId = v4(); + const didTx: DeliverTxResponse = await didModule.createDidDocTx( + signInputs, + didPayload, + feePayer, + fee, + undefined, + versionId + ); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // update the did document + const updateVersionId = v4(); + const updateDidPayload = { + '@context': didPayload?.['@context'], + id: didPayload.id, + controller: didPayload.controller, + verificationMethod: didPayload.verificationMethod, + authentication: didPayload.authentication, + assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference + } as DIDDocument; + + const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer); + const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( + signInputs, + updateDidPayload, + feePayer, + feeUpdate, + undefined, + updateVersionId + ); + + console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`); + + expect(updateDidDocTx.code).toBe(0); + + const didDocVersionsMetadata = await didModule.queryAllDidDocVersionsMetadata(didPayload.id); + + expect(didDocVersionsMetadata.didDocumentVersionsMetadata).toHaveLength(2); + expect( + containsAll( + [ + didDocVersionsMetadata.didDocumentVersionsMetadata[0].versionId, + didDocVersionsMetadata.didDocumentVersionsMetadata[1].versionId, + ], + [versionId, updateVersionId] + ) + ).toBe(true); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].created).toBeDefined(); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].created).toBeDefined(); + expect( + containsAll( + [ + didDocVersionsMetadata.didDocumentVersionsMetadata[0]?.updated, + didDocVersionsMetadata.didDocumentVersionsMetadata[1]?.updated, + ], + [undefined] + ) + ).toBe(true); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].deactivated).toBe(false); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].deactivated).toBe(false); + }, + defaultAsyncTxTimeout + ); + + it( + 'should query all DID document versions metadata - case: Ed25519VerificationKey2018', + async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry(DIDModule.registryTypes); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupDidExtension + )) as CheqdQuerier & DidExtension; + const didModule = new DIDModule(signer, querier); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const versionId = v4(); + const didTx: DeliverTxResponse = await didModule.createDidDocTx( + signInputs, + didPayload, + feePayer, + fee, + undefined, + versionId + ); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // update the did document + const updateVersionId = v4(); + const updateDidPayload = { + '@context': didPayload?.['@context'], + id: didPayload.id, + controller: didPayload.controller, + verificationMethod: didPayload.verificationMethod, + authentication: didPayload.authentication, + assertionMethod: [didPayload.verificationMethod![0].id], // <-- This is the only difference + } as DIDDocument; + + const feeUpdate = await DIDModule.generateUpdateDidDocFees(feePayer); + const updateDidDocTx: DeliverTxResponse = await didModule.updateDidDocTx( + signInputs, + updateDidPayload, + feePayer, + feeUpdate, + undefined, + updateVersionId + ); + + console.warn(`Using payload: ${JSON.stringify(updateDidPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(updateDidDocTx)}`); + + expect(updateDidDocTx.code).toBe(0); + + const didDocVersionsMetadata = await didModule.queryAllDidDocVersionsMetadata(didPayload.id); + + expect(didDocVersionsMetadata.didDocumentVersionsMetadata).toHaveLength(2); + expect( + containsAll( + [ + didDocVersionsMetadata.didDocumentVersionsMetadata[0].versionId, + didDocVersionsMetadata.didDocumentVersionsMetadata[1].versionId, + ], + [versionId, updateVersionId] + ) + ).toBe(true); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].created).toBeDefined(); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].created).toBeDefined(); + expect( + containsAll( + [ + didDocVersionsMetadata.didDocumentVersionsMetadata[0]?.updated, + didDocVersionsMetadata.didDocumentVersionsMetadata[1]?.updated, + ], + [undefined] + ) + ).toBe(true); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[1].deactivated).toBe(false); + expect(didDocVersionsMetadata.didDocumentVersionsMetadata[0].deactivated).toBe(false); + }, + defaultAsyncTxTimeout + ); + }); +}); diff --git a/tests/modules/resource.test.ts b/tests/modules/resource.test.ts index fc673040..cb70c3e6 100644 --- a/tests/modules/resource.test.ts +++ b/tests/modules/resource.test.ts @@ -1,991 +1,1152 @@ -import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing" -import { DeliverTxResponse } from "@cosmjs/stargate" +import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing'; +import { DeliverTxResponse } from '@cosmjs/stargate'; +import { fromString, toString } from 'uint8arrays'; +import { DIDModule, ResourceModule } from '../../src'; +import { createDefaultCheqdRegistry } from '../../src/registry'; +import { CheqdSigningStargateClient } from '../../src/signer'; import { - fromString, - toString -} from 'uint8arrays' -import { - DIDModule, - ResourceModule -} from "../../src" -import { createDefaultCheqdRegistry } from "../../src/registry" -import { CheqdSigningStargateClient } from "../../src/signer" -import { - ISignInputs, - MethodSpecificIdAlgo, - QueryExtensionSetup, - VerificationMethods, - CheqdExtensions + ISignInputs, + MethodSpecificIdAlgo, + QueryExtensionSetup, + VerificationMethods, + CheqdExtensions, } from '../../src/types'; import { - createDidPayload, - createDidVerificationMethod, - createKeyPairBase64, - createVerificationKeys -} from "../../src/utils" + createDidPayload, + createDidVerificationMethod, + createKeyPairBase64, + createVerificationKeys, +} from '../../src/utils'; import { - localnet, - faucet, - image_content, - default_content, - json_content, - containsAllButOmittedFields + localnet, + faucet, + image_content, + default_content, + json_content, + containsAllButOmittedFields, } from '../testutils.test'; -import { - AlternativeUri, - Metadata, - MsgCreateResourcePayload -} from '@cheqd/ts-proto/cheqd/resource/v2'; -import { v4 } from "uuid" -import { CheqdQuerier } from "../../src/querier" -import { - setupResourceExtension, - ResourceExtension -} from '../../src/modules/resource'; -import { - DidExtension, - setupDidExtension -} from "../../src/modules/did" -import { sha256 } from "@cosmjs/crypto" +import { AlternativeUri, Metadata, MsgCreateResourcePayload } from '@cheqd/ts-proto/cheqd/resource/v2'; +import { v4 } from 'uuid'; +import { CheqdQuerier } from '../../src/querier'; +import { setupResourceExtension, ResourceExtension } from '../../src/modules/resource'; +import { DidExtension, setupDidExtension } from '../../src/modules/did'; +import { sha256 } from '@cosmjs/crypto'; -const defaultAsyncTxTimeout = 30000 +const defaultAsyncTxTimeout = 30000; describe('ResourceModule', () => { - describe('constructor', () => { - it('should instantiate standalone module', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - const querier = await CheqdQuerier.connectWithExtension(localnet.rpcUrl, setupResourceExtension) as CheqdQuerier & ResourceExtension - const resourceModule = new ResourceModule(signer, querier) - expect(resourceModule).toBeInstanceOf(ResourceModule) - }) - }) - - describe('createLinkedResourceTx', () => { - it('should create a new Resource - case: json', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: didPayload.id.split(":").reverse()[0], - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: new TextEncoder().encode(json_content) - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceJson = await ResourceModule.generateCreateResourceJsonFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceJson - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should create a new Resource - case: image', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: didPayload.id.split(":").reverse()[0], - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: fromString(image_content, 'base64') - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceImage = await ResourceModule.generateCreateResourceImageFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceImage - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - }, defaultAsyncTxTimeout) - - it('should create a new Resource - case: default', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: didPayload.id.split(":").reverse()[0], - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: new TextEncoder().encode(default_content) - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceDefault = await ResourceModule.generateCreateResourceDefaultFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceDefault - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - }, defaultAsyncTxTimeout) - }) - - describe('queryLinkedResource', () => { - it('should query a linked resource - case: json', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const collectionId = didPayload.id.split(":").reverse()[0] - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: collectionId, - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: new TextEncoder().encode(json_content) - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceJson = await ResourceModule.generateCreateResourceJsonFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceJson, - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - - // query the resource - const resourceWithMetadata = await resourceModule.queryLinkedResource(collectionId, resourcePayload.id) - - // ledger constructed - const alsoKnownAs = [{ description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }] - const checksum = toString(sha256(resourcePayload.data), 'hex') - const mimeType = 'application/json' - - expect(resourceWithMetadata.metadata?.collectionId).toBe(collectionId) - expect(resourceWithMetadata.metadata?.id).toBe(resourcePayload.id) - expect(resourceWithMetadata.metadata?.name).toBe(resourcePayload.name) - expect(resourceWithMetadata.metadata?.version).toBe(resourcePayload.version) - expect(resourceWithMetadata.metadata?.resourceType).toBe(resourcePayload.resourceType) - expect(resourceWithMetadata.metadata?.alsoKnownAs).toEqual(alsoKnownAs) - expect(resourceWithMetadata.metadata?.mediaType).toBe(mimeType) - expect(resourceWithMetadata.metadata?.checksum).toBe(checksum) - expect(resourceWithMetadata.metadata?.previousVersionId).toBe('') - expect(resourceWithMetadata.metadata?.nextVersionId).toBe('') - expect(resourceWithMetadata.resource?.data).toEqual(resourcePayload.data) - }, defaultAsyncTxTimeout) - - it('should query a linked resource - case: image', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const collectionId = didPayload.id.split(":").reverse()[0] - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: collectionId, - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: fromString(image_content, 'base64') - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceImage = await ResourceModule.generateCreateResourceImageFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceImage, - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - - // query the resource - const resourceWithMetadata = await resourceModule.queryLinkedResource(collectionId, resourcePayload.id) - - // ledger constructed - const alsoKnownAs = [{ description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }] - const checksum = toString(sha256(resourcePayload.data), 'hex') - const mimeType = 'image/png' - - expect(resourceWithMetadata.metadata?.collectionId).toBe(collectionId) - expect(resourceWithMetadata.metadata?.id).toBe(resourcePayload.id) - expect(resourceWithMetadata.metadata?.name).toBe(resourcePayload.name) - expect(resourceWithMetadata.metadata?.version).toBe(resourcePayload.version) - expect(resourceWithMetadata.metadata?.resourceType).toBe(resourcePayload.resourceType) - expect(resourceWithMetadata.metadata?.alsoKnownAs).toEqual(alsoKnownAs) - expect(resourceWithMetadata.metadata?.mediaType).toBe(mimeType) - expect(resourceWithMetadata.metadata?.checksum).toBe(checksum) - expect(resourceWithMetadata.metadata?.previousVersionId).toBe('') - expect(resourceWithMetadata.metadata?.nextVersionId).toBe('') - expect(resourceWithMetadata.resource?.data).toEqual(resourcePayload.data) - }, defaultAsyncTxTimeout) - - it('should query a linked resource - case: default', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const collectionId = didPayload.id.split(":").reverse()[0] - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: collectionId, - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: new TextEncoder().encode(default_content) - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceDefault = await ResourceModule.generateCreateResourceDefaultFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceDefault, - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - - // query the resource - const resourceWithMetadata = await resourceModule.queryLinkedResource(collectionId, resourcePayload.id) - - // ledger constructed - const alsoKnownAs = [{ description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }] - const checksum = toString(sha256(resourcePayload.data), 'hex') - const mimeType = 'text/html; charset=utf-8' - - expect(resourceWithMetadata.metadata?.collectionId).toBe(collectionId) - expect(resourceWithMetadata.metadata?.id).toBe(resourcePayload.id) - expect(resourceWithMetadata.metadata?.name).toBe(resourcePayload.name) - expect(resourceWithMetadata.metadata?.version).toBe(resourcePayload.version) - expect(resourceWithMetadata.metadata?.resourceType).toBe(resourcePayload.resourceType) - expect(resourceWithMetadata.metadata?.alsoKnownAs).toEqual(alsoKnownAs) - expect(resourceWithMetadata.metadata?.mediaType).toBe(mimeType) - expect(resourceWithMetadata.metadata?.checksum).toBe(checksum) - expect(resourceWithMetadata.metadata?.previousVersionId).toBe('') - expect(resourceWithMetadata.metadata?.nextVersionId).toBe('') - expect(resourceWithMetadata.resource?.data).toEqual(resourcePayload.data) - }, defaultAsyncTxTimeout) - }) - - describe('queryLinkedResourceMetadata', () => { - it('should query a linked resource metadata - case: json', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const collectionId = didPayload.id.split(":").reverse()[0] - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: collectionId, - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: new TextEncoder().encode(json_content) - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceJson = await ResourceModule.generateCreateResourceJsonFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceJson, - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - - // query the linked resource metadata - const metadata = await resourceModule.queryLinkedResourceMetadata(collectionId, resourcePayload.id) - - // ledger constructed - const alsoKnownAs = [{ description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }] - const checksum = toString(sha256(resourcePayload.data), 'hex') - const mimeType = 'application/json' - - expect(metadata?.collectionId).toBe(collectionId) - expect(metadata?.id).toBe(resourcePayload.id) - expect(metadata?.name).toBe(resourcePayload.name) - expect(metadata?.version).toBe(resourcePayload.version) - expect(metadata?.resourceType).toBe(resourcePayload.resourceType) - expect(metadata?.alsoKnownAs).toEqual(alsoKnownAs) - expect(metadata?.mediaType).toBe(mimeType) - expect(metadata?.checksum).toBe(checksum) - expect(metadata?.previousVersionId).toBe('') - expect(metadata?.nextVersionId).toBe('') - }, defaultAsyncTxTimeout) - - it('should query a linked resource metadata - case: image', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const collectionId = didPayload.id.split(":").reverse()[0] - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: collectionId, - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: fromString(image_content, 'base64') - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceImage = await ResourceModule.generateCreateResourceImageFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceImage, - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - - // query the linked resource metadata - const metadata = await resourceModule.queryLinkedResourceMetadata(collectionId, resourcePayload.id) - - // ledger constructed - const alsoKnownAs = [{ description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }] - const checksum = toString(sha256(resourcePayload.data), 'hex') - const mimeType = 'image/png' - - expect(metadata?.collectionId).toBe(collectionId) - expect(metadata?.id).toBe(resourcePayload.id) - expect(metadata?.name).toBe(resourcePayload.name) - expect(metadata?.version).toBe(resourcePayload.version) - expect(metadata?.resourceType).toBe(resourcePayload.resourceType) - expect(metadata?.alsoKnownAs).toEqual(alsoKnownAs) - expect(metadata?.mediaType).toBe(mimeType) - expect(metadata?.checksum).toBe(checksum) - expect(metadata?.previousVersionId).toBe('') - expect(metadata?.nextVersionId).toBe('') - }, defaultAsyncTxTimeout) - - it('should query a linked resource metadata - case: default', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const collectionId = didPayload.id.split(":").reverse()[0] - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: collectionId, - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: new TextEncoder().encode(default_content) - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceDefault = await ResourceModule.generateCreateResourceDefaultFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceDefault, - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - - // query the linked resource metadata - const metadata = await resourceModule.queryLinkedResourceMetadata(collectionId, resourcePayload.id) - - // ledger constructed - const alsoKnownAs = [{ description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }] - const checksum = toString(sha256(resourcePayload.data), 'hex') - const mimeType = 'text/html; charset=utf-8' - - expect(metadata?.collectionId).toBe(collectionId) - expect(metadata?.id).toBe(resourcePayload.id) - expect(metadata?.name).toBe(resourcePayload.name) - expect(metadata?.version).toBe(resourcePayload.version) - expect(metadata?.resourceType).toBe(resourcePayload.resourceType) - expect(metadata?.alsoKnownAs).toEqual(alsoKnownAs) - expect(metadata?.mediaType).toBe(mimeType) - expect(metadata?.checksum).toBe(checksum) - expect(metadata?.previousVersionId).toBe('') - expect(metadata?.nextVersionId).toBe('') - }, defaultAsyncTxTimeout) - }) - - describe('queryLinkedResources', () => { - it('should query linked resource collection', async () => { - // create an associated did document - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {prefix: faucet.prefix}) - const registry = createDefaultCheqdRegistry(Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes))) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - const querier = await CheqdQuerier.connectWithExtensions(localnet.rpcUrl, ...[setupDidExtension, setupResourceExtension] as unknown as QueryExtensionSetup[]) - const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension) - - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feePayer = (await wallet.getAccounts())[0].address - const fee = await DIDModule.generateCreateDidDocFees(feePayer) - const didTx: DeliverTxResponse = await didModule.createDidDocTx( - signInputs, - didPayload, - feePayer, - fee - ) - - console.warn(`Using payload: ${JSON.stringify(didPayload)}`) - console.warn(`DID Tx: ${JSON.stringify(didTx)}`) - - expect(didTx.code).toBe(0) - - // create a did linked resource - const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension) - - const collectionId = didPayload.id.split(":").reverse()[0] - - const resourcePayload: MsgCreateResourcePayload = { - collectionId: collectionId, - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: new TextEncoder().encode(json_content) - } - - const resourceSignInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - keyType: 'Ed25519', - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - - const feeResourceJson = await ResourceModule.generateCreateResourceJsonFees(feePayer) - const resourceTx = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload, - feePayer, - feeResourceJson, - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`) - - expect(resourceTx.code).toBe(0) - - // create a did linked resource following version - const resourcePayload2: MsgCreateResourcePayload = { - collectionId: collectionId, - id: v4(), - version: "2.0", - alsoKnownAs: [], - name: 'Test Resource', - resourceType: 'test-resource-type', - data: new TextEncoder().encode(json_content) - } - - const resourceTx2 = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload2, - feePayer, - feeResourceJson, - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx2)}`) - - expect(resourceTx2.code).toBe(0) - - // create a different did linked resource - const resourcePayload3: MsgCreateResourcePayload = { - collectionId: collectionId, - id: v4(), - version: "1.0", - alsoKnownAs: [], - name: 'Different Test Resource', - resourceType: 'different-test-resource-type', - data: new TextEncoder().encode(json_content) // different regardless of data - } - - const resourceTx3 = await resourceModule.createLinkedResourceTx( - resourceSignInputs, - resourcePayload3, - feePayer, - feeResourceJson, - ) - - console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`) - console.warn(`Resource Tx: ${JSON.stringify(resourceTx3)}`) - - expect(resourceTx3.code).toBe(0) - - // query the linked resource collection - const resources = await resourceModule.queryLinkedResources(collectionId) - - console.warn(`Resources: ${JSON.stringify(resources)}`) - - // ledger constructed - const alsoKnownAs = (resourceId: string): AlternativeUri[] => [{ uri: `${didPayload.id}/resources/${resourceId}`, description: 'did-url' }] - const checksum = toString(sha256(resourcePayload.data), 'hex') - const mimeType = 'application/json' - - // expected unordered - const expected: Omit[] = [ - { - collectionId: collectionId, - id: resourcePayload.id, - name: resourcePayload.name, - version: resourcePayload.version, - resourceType: resourcePayload.resourceType, - alsoKnownAs: alsoKnownAs(resourcePayload.id), - mediaType: mimeType, - checksum: checksum, - previousVersionId: '', - nextVersionId: resourcePayload2.id, - }, - { - collectionId: collectionId, - id: resourcePayload2.id, - name: resourcePayload2.name, - version: resourcePayload2.version, - resourceType: resourcePayload2.resourceType, - alsoKnownAs: alsoKnownAs(resourcePayload2.id), - mediaType: mimeType, - checksum: checksum, - previousVersionId: resourcePayload.id, - nextVersionId: '', - }, - { - collectionId: collectionId, - id: resourcePayload3.id, - name: resourcePayload3.name, - version: resourcePayload3.version, - resourceType: resourcePayload3.resourceType, - alsoKnownAs: alsoKnownAs(resourcePayload3.id), - mediaType: mimeType, - checksum: checksum, - previousVersionId: '', - nextVersionId: '', - } - ] - - expect(resources.resources).toHaveLength(3) - expect(containsAllButOmittedFields(resources.resources, expected, ['created'])).toBe(true) - }, defaultAsyncTxTimeout * 3) - }) -}) + describe('constructor', () => { + it('should instantiate standalone module', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + const querier = (await CheqdQuerier.connectWithExtension( + localnet.rpcUrl, + setupResourceExtension + )) as CheqdQuerier & ResourceExtension; + const resourceModule = new ResourceModule(signer, querier); + expect(resourceModule).toBeInstanceOf(ResourceModule); + }); + }); + + describe('createLinkedResourceTx', () => { + it( + 'should create a new Resource - case: json', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: didPayload.id.split(':').reverse()[0], + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: new TextEncoder().encode(json_content), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceJson = await ResourceModule.generateCreateResourceJsonFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceJson + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should create a new Resource - case: image', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: didPayload.id.split(':').reverse()[0], + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: fromString(image_content, 'base64'), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceImage = await ResourceModule.generateCreateResourceImageFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceImage + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + + it( + 'should create a new Resource - case: default', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: didPayload.id.split(':').reverse()[0], + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: new TextEncoder().encode(default_content), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceDefault = await ResourceModule.generateCreateResourceDefaultFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceDefault + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + }, + defaultAsyncTxTimeout + ); + }); + + describe('queryLinkedResource', () => { + it( + 'should query a linked resource - case: json', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const collectionId = didPayload.id.split(':').reverse()[0]; + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: collectionId, + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: new TextEncoder().encode(json_content), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceJson = await ResourceModule.generateCreateResourceJsonFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceJson + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + + // query the resource + const resourceWithMetadata = await resourceModule.queryLinkedResource(collectionId, resourcePayload.id); + + // ledger constructed + const alsoKnownAs = [ + { description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }, + ]; + const checksum = toString(sha256(resourcePayload.data), 'hex'); + const mimeType = 'application/json'; + + expect(resourceWithMetadata.metadata?.collectionId).toBe(collectionId); + expect(resourceWithMetadata.metadata?.id).toBe(resourcePayload.id); + expect(resourceWithMetadata.metadata?.name).toBe(resourcePayload.name); + expect(resourceWithMetadata.metadata?.version).toBe(resourcePayload.version); + expect(resourceWithMetadata.metadata?.resourceType).toBe(resourcePayload.resourceType); + expect(resourceWithMetadata.metadata?.alsoKnownAs).toEqual(alsoKnownAs); + expect(resourceWithMetadata.metadata?.mediaType).toBe(mimeType); + expect(resourceWithMetadata.metadata?.checksum).toBe(checksum); + expect(resourceWithMetadata.metadata?.previousVersionId).toBe(''); + expect(resourceWithMetadata.metadata?.nextVersionId).toBe(''); + expect(resourceWithMetadata.resource?.data).toEqual(resourcePayload.data); + }, + defaultAsyncTxTimeout + ); + + it( + 'should query a linked resource - case: image', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const collectionId = didPayload.id.split(':').reverse()[0]; + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: collectionId, + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: fromString(image_content, 'base64'), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceImage = await ResourceModule.generateCreateResourceImageFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceImage + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + + // query the resource + const resourceWithMetadata = await resourceModule.queryLinkedResource(collectionId, resourcePayload.id); + + // ledger constructed + const alsoKnownAs = [ + { description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }, + ]; + const checksum = toString(sha256(resourcePayload.data), 'hex'); + const mimeType = 'image/png'; + + expect(resourceWithMetadata.metadata?.collectionId).toBe(collectionId); + expect(resourceWithMetadata.metadata?.id).toBe(resourcePayload.id); + expect(resourceWithMetadata.metadata?.name).toBe(resourcePayload.name); + expect(resourceWithMetadata.metadata?.version).toBe(resourcePayload.version); + expect(resourceWithMetadata.metadata?.resourceType).toBe(resourcePayload.resourceType); + expect(resourceWithMetadata.metadata?.alsoKnownAs).toEqual(alsoKnownAs); + expect(resourceWithMetadata.metadata?.mediaType).toBe(mimeType); + expect(resourceWithMetadata.metadata?.checksum).toBe(checksum); + expect(resourceWithMetadata.metadata?.previousVersionId).toBe(''); + expect(resourceWithMetadata.metadata?.nextVersionId).toBe(''); + expect(resourceWithMetadata.resource?.data).toEqual(resourcePayload.data); + }, + defaultAsyncTxTimeout + ); + + it( + 'should query a linked resource - case: default', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const collectionId = didPayload.id.split(':').reverse()[0]; + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: collectionId, + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: new TextEncoder().encode(default_content), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceDefault = await ResourceModule.generateCreateResourceDefaultFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceDefault + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + + // query the resource + const resourceWithMetadata = await resourceModule.queryLinkedResource(collectionId, resourcePayload.id); + + // ledger constructed + const alsoKnownAs = [ + { description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }, + ]; + const checksum = toString(sha256(resourcePayload.data), 'hex'); + const mimeType = 'text/html; charset=utf-8'; + + expect(resourceWithMetadata.metadata?.collectionId).toBe(collectionId); + expect(resourceWithMetadata.metadata?.id).toBe(resourcePayload.id); + expect(resourceWithMetadata.metadata?.name).toBe(resourcePayload.name); + expect(resourceWithMetadata.metadata?.version).toBe(resourcePayload.version); + expect(resourceWithMetadata.metadata?.resourceType).toBe(resourcePayload.resourceType); + expect(resourceWithMetadata.metadata?.alsoKnownAs).toEqual(alsoKnownAs); + expect(resourceWithMetadata.metadata?.mediaType).toBe(mimeType); + expect(resourceWithMetadata.metadata?.checksum).toBe(checksum); + expect(resourceWithMetadata.metadata?.previousVersionId).toBe(''); + expect(resourceWithMetadata.metadata?.nextVersionId).toBe(''); + expect(resourceWithMetadata.resource?.data).toEqual(resourcePayload.data); + }, + defaultAsyncTxTimeout + ); + }); + + describe('queryLinkedResourceMetadata', () => { + it( + 'should query a linked resource metadata - case: json', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const collectionId = didPayload.id.split(':').reverse()[0]; + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: collectionId, + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: new TextEncoder().encode(json_content), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceJson = await ResourceModule.generateCreateResourceJsonFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceJson + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + + // query the linked resource metadata + const metadata = await resourceModule.queryLinkedResourceMetadata(collectionId, resourcePayload.id); + + // ledger constructed + const alsoKnownAs = [ + { description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }, + ]; + const checksum = toString(sha256(resourcePayload.data), 'hex'); + const mimeType = 'application/json'; + + expect(metadata?.collectionId).toBe(collectionId); + expect(metadata?.id).toBe(resourcePayload.id); + expect(metadata?.name).toBe(resourcePayload.name); + expect(metadata?.version).toBe(resourcePayload.version); + expect(metadata?.resourceType).toBe(resourcePayload.resourceType); + expect(metadata?.alsoKnownAs).toEqual(alsoKnownAs); + expect(metadata?.mediaType).toBe(mimeType); + expect(metadata?.checksum).toBe(checksum); + expect(metadata?.previousVersionId).toBe(''); + expect(metadata?.nextVersionId).toBe(''); + }, + defaultAsyncTxTimeout + ); + + it( + 'should query a linked resource metadata - case: image', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const collectionId = didPayload.id.split(':').reverse()[0]; + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: collectionId, + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: fromString(image_content, 'base64'), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceImage = await ResourceModule.generateCreateResourceImageFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceImage + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + + // query the linked resource metadata + const metadata = await resourceModule.queryLinkedResourceMetadata(collectionId, resourcePayload.id); + + // ledger constructed + const alsoKnownAs = [ + { description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }, + ]; + const checksum = toString(sha256(resourcePayload.data), 'hex'); + const mimeType = 'image/png'; + + expect(metadata?.collectionId).toBe(collectionId); + expect(metadata?.id).toBe(resourcePayload.id); + expect(metadata?.name).toBe(resourcePayload.name); + expect(metadata?.version).toBe(resourcePayload.version); + expect(metadata?.resourceType).toBe(resourcePayload.resourceType); + expect(metadata?.alsoKnownAs).toEqual(alsoKnownAs); + expect(metadata?.mediaType).toBe(mimeType); + expect(metadata?.checksum).toBe(checksum); + expect(metadata?.previousVersionId).toBe(''); + expect(metadata?.nextVersionId).toBe(''); + }, + defaultAsyncTxTimeout + ); + + it( + 'should query a linked resource metadata - case: default', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const collectionId = didPayload.id.split(':').reverse()[0]; + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: collectionId, + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: new TextEncoder().encode(default_content), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceDefault = await ResourceModule.generateCreateResourceDefaultFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceDefault + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + + // query the linked resource metadata + const metadata = await resourceModule.queryLinkedResourceMetadata(collectionId, resourcePayload.id); + + // ledger constructed + const alsoKnownAs = [ + { description: 'did-url', uri: `${didPayload.id}/resources/${resourcePayload.id}` }, + ]; + const checksum = toString(sha256(resourcePayload.data), 'hex'); + const mimeType = 'text/html; charset=utf-8'; + + expect(metadata?.collectionId).toBe(collectionId); + expect(metadata?.id).toBe(resourcePayload.id); + expect(metadata?.name).toBe(resourcePayload.name); + expect(metadata?.version).toBe(resourcePayload.version); + expect(metadata?.resourceType).toBe(resourcePayload.resourceType); + expect(metadata?.alsoKnownAs).toEqual(alsoKnownAs); + expect(metadata?.mediaType).toBe(mimeType); + expect(metadata?.checksum).toBe(checksum); + expect(metadata?.previousVersionId).toBe(''); + expect(metadata?.nextVersionId).toBe(''); + }, + defaultAsyncTxTimeout + ); + }); + + describe('queryLinkedResources', () => { + it( + 'should query linked resource collection', + async () => { + // create an associated did document + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, { prefix: faucet.prefix }); + const registry = createDefaultCheqdRegistry( + Array.from(DIDModule.registryTypes).concat(Array.from(ResourceModule.registryTypes)) + ); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { + registry, + }); + const querier = await CheqdQuerier.connectWithExtensions( + localnet.rpcUrl, + ...([ + setupDidExtension, + setupResourceExtension, + ] as unknown as QueryExtensionSetup[]) + ); + const didModule = new DIDModule(signer, querier as CheqdQuerier & DidExtension); + + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys( + keyPair.publicKey, + MethodSpecificIdAlgo.Base58, + 'key-1' + ); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feePayer = (await wallet.getAccounts())[0].address; + const fee = await DIDModule.generateCreateDidDocFees(feePayer); + const didTx: DeliverTxResponse = await didModule.createDidDocTx(signInputs, didPayload, feePayer, fee); + + console.warn(`Using payload: ${JSON.stringify(didPayload)}`); + console.warn(`DID Tx: ${JSON.stringify(didTx)}`); + + expect(didTx.code).toBe(0); + + // create a did linked resource + const resourceModule = new ResourceModule(signer, querier as CheqdQuerier & ResourceExtension); + + const collectionId = didPayload.id.split(':').reverse()[0]; + + const resourcePayload: MsgCreateResourcePayload = { + collectionId: collectionId, + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: new TextEncoder().encode(json_content), + }; + + const resourceSignInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + keyType: 'Ed25519', + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + + const feeResourceJson = await ResourceModule.generateCreateResourceJsonFees(feePayer); + const resourceTx = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload, + feePayer, + feeResourceJson + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx)}`); + + expect(resourceTx.code).toBe(0); + + // create a did linked resource following version + const resourcePayload2: MsgCreateResourcePayload = { + collectionId: collectionId, + id: v4(), + version: '2.0', + alsoKnownAs: [], + name: 'Test Resource', + resourceType: 'test-resource-type', + data: new TextEncoder().encode(json_content), + }; + + const resourceTx2 = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload2, + feePayer, + feeResourceJson + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx2)}`); + + expect(resourceTx2.code).toBe(0); + + // create a different did linked resource + const resourcePayload3: MsgCreateResourcePayload = { + collectionId: collectionId, + id: v4(), + version: '1.0', + alsoKnownAs: [], + name: 'Different Test Resource', + resourceType: 'different-test-resource-type', + data: new TextEncoder().encode(json_content), // different regardless of data + }; + + const resourceTx3 = await resourceModule.createLinkedResourceTx( + resourceSignInputs, + resourcePayload3, + feePayer, + feeResourceJson + ); + + console.warn(`Using payload: ${JSON.stringify(resourcePayload)}`); + console.warn(`Resource Tx: ${JSON.stringify(resourceTx3)}`); + + expect(resourceTx3.code).toBe(0); + + // query the linked resource collection + const resources = await resourceModule.queryLinkedResources(collectionId); + + console.warn(`Resources: ${JSON.stringify(resources)}`); + + // ledger constructed + const alsoKnownAs = (resourceId: string): AlternativeUri[] => [ + { uri: `${didPayload.id}/resources/${resourceId}`, description: 'did-url' }, + ]; + const checksum = toString(sha256(resourcePayload.data), 'hex'); + const mimeType = 'application/json'; + + // expected unordered + const expected: Omit[] = [ + { + collectionId: collectionId, + id: resourcePayload.id, + name: resourcePayload.name, + version: resourcePayload.version, + resourceType: resourcePayload.resourceType, + alsoKnownAs: alsoKnownAs(resourcePayload.id), + mediaType: mimeType, + checksum: checksum, + previousVersionId: '', + nextVersionId: resourcePayload2.id, + }, + { + collectionId: collectionId, + id: resourcePayload2.id, + name: resourcePayload2.name, + version: resourcePayload2.version, + resourceType: resourcePayload2.resourceType, + alsoKnownAs: alsoKnownAs(resourcePayload2.id), + mediaType: mimeType, + checksum: checksum, + previousVersionId: resourcePayload.id, + nextVersionId: '', + }, + { + collectionId: collectionId, + id: resourcePayload3.id, + name: resourcePayload3.name, + version: resourcePayload3.version, + resourceType: resourcePayload3.resourceType, + alsoKnownAs: alsoKnownAs(resourcePayload3.id), + mediaType: mimeType, + checksum: checksum, + previousVersionId: '', + nextVersionId: '', + }, + ]; + + expect(resources.resources).toHaveLength(3); + expect(containsAllButOmittedFields(resources.resources, expected, ['created'])).toBe(true); + }, + defaultAsyncTxTimeout * 3 + ); + }); +}); diff --git a/tests/signer.test.ts b/tests/signer.test.ts index 06f49f6a..a3c19ed5 100644 --- a/tests/signer.test.ts +++ b/tests/signer.test.ts @@ -1,202 +1,206 @@ +import { MsgCreateDidDoc, MsgCreateDidDocPayload, VerificationMethod } from '@cheqd/ts-proto/cheqd/did/v2'; +import { DirectSecp256k1HdWallet, Registry } from '@cosmjs/proto-signing'; +import { EdDSASigner } from 'did-jwt'; +import { typeUrlMsgCreateDidDoc } from '../src/modules/did'; +import { CheqdSigningStargateClient } from '../src/signer'; +import { ISignInputs, MethodSpecificIdAlgo, VerificationMethods } from '../src/types'; +import { fromString, toString } from 'uint8arrays'; import { - MsgCreateDidDoc, - MsgCreateDidDocPayload, - VerificationMethod -} from "@cheqd/ts-proto/cheqd/did/v2" -import { - DirectSecp256k1HdWallet, - Registry -} from "@cosmjs/proto-signing" -import { EdDSASigner } from "did-jwt" -import { typeUrlMsgCreateDidDoc } from '../src/modules/did' -import { CheqdSigningStargateClient } from "../src/signer" -import { - ISignInputs, - MethodSpecificIdAlgo, - VerificationMethods -} from "../src/types" -import { - fromString, - toString -} from 'uint8arrays' -import { - createDidPayload, - createDidVerificationMethod, - createKeyPairBase64, - createVerificationKeys, - validateSpecCompliantPayload + createDidPayload, + createDidVerificationMethod, + createKeyPairBase64, + createVerificationKeys, + validateSpecCompliantPayload, } from '../src/utils'; -import { - localnet, - faucet -} from "./testutils.test" -import { verify } from "@stablelib/ed25519" -import { v4 } from "uuid" - -const nonExistingDid = "did:cHeQd:fantasticnet:123" -const nonExistingKeyId = 'did:cHeQd:fantasticnet:123#key-678' -const nonExistingPublicKeyMultibase = '1234567890' -const nonExistingVerificationMethod = 'ExtraTerrestrialVerificationKey2045' +import { localnet, faucet } from './testutils.test'; +import { verify } from '@stablelib/ed25519'; +import { v4 } from 'uuid'; + +const nonExistingDid = 'did:cHeQd:fantasticnet:123'; +const nonExistingKeyId = 'did:cHeQd:fantasticnet:123#key-678'; +const nonExistingPublicKeyMultibase = '1234567890'; +const nonExistingVerificationMethod = 'ExtraTerrestrialVerificationKey2045'; const nonExistingVerificationDidDocument = { - "authentication": [ - "did:cheqd:testnet:z6Jn6NmYkaCepQe2#key-1" - ], - "controller": [ - "did:cheqd:testnet:z6Jn6NmYkaCepQe2" - ], - "id": "did:cheqd:testnet:z6Jn6NmYkaCepQe2", - "verificationMethod": [ - { - "controller": "did:cheqd:testnet:z6Jn6NmYkaCepQe2", - "id": "did:cheqd:testnet:z6Jn6NmYkaCepQe2#key-1", - "publicKeyMultibase": "z6Jn6NmYkaCepQe29vgCZQhFfRkN3YpEPiu14F8HbbmqW", - "type": nonExistingVerificationMethod - } - ] -} + authentication: ['did:cheqd:testnet:z6Jn6NmYkaCepQe2#key-1'], + controller: ['did:cheqd:testnet:z6Jn6NmYkaCepQe2'], + id: 'did:cheqd:testnet:z6Jn6NmYkaCepQe2', + verificationMethod: [ + { + controller: 'did:cheqd:testnet:z6Jn6NmYkaCepQe2', + id: 'did:cheqd:testnet:z6Jn6NmYkaCepQe2#key-1', + publicKeyMultibase: 'z6Jn6NmYkaCepQe29vgCZQhFfRkN3YpEPiu14F8HbbmqW', + type: nonExistingVerificationMethod, + }, + ], +}; describe('CheqdSigningStargateClient', () => { - describe('constructor', () => { - it('can be instantiated & works for cheqd networks', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - expect(signer).toBeInstanceOf(CheqdSigningStargateClient) - }) - - it('can be constructed with cheqd custom registry', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const registry = new Registry() - registry.register(typeUrlMsgCreateDidDoc, MsgCreateDidDoc) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }) - expect(signer.registry.lookupType(typeUrlMsgCreateDidDoc)).toBe(MsgCreateDidDoc) - }) - }) - - describe('getDidSigner', () => { - it('can get a signer for a did', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const { protobufVerificationMethod } = validateSpecCompliantPayload(didPayload) - - const didSigner = await signer.getDidSigner(didPayload.verificationMethod![0].id, protobufVerificationMethod!) - - expect(didSigner).toBe(EdDSASigner) - }) - - it('should throw for a non-supported verification method', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - - await expect(signer.getDidSigner(nonExistingVerificationDidDocument.verificationMethod[0].id, nonExistingVerificationDidDocument.verificationMethod)).rejects.toThrow() - }) - - it('should throw for non-matching verification method id', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const payload = createDidPayload(verificationMethods, [verificationKeys]) - const { protobufVerificationMethod } = validateSpecCompliantPayload(payload) - - await expect(signer.getDidSigner(nonExistingKeyId, protobufVerificationMethod!)).rejects.toThrow() - }) - }) - - describe('checkDidSigners', () => { - it('it should instantiate a signer for a did', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const payload = createDidPayload(verificationMethods, [verificationKeys]) - const { protobufVerificationMethod } = validateSpecCompliantPayload(payload) - const didSigners = await signer.checkDidSigners(protobufVerificationMethod) - - expect(didSigners[VerificationMethods.Ed255192020]).toBe(EdDSASigner) - }) - - it('should instantiate multiple signers for a did with multiple verification methods', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - const keyPair1 = createKeyPairBase64() - const keyPair2 = createKeyPairBase64() - const keyPair3 = createKeyPairBase64() - const verificationKeys1 = createVerificationKeys(keyPair1.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationKeys2 = createVerificationKeys(keyPair2.publicKey, MethodSpecificIdAlgo.Base58, 'key-2') - const verificationKeys3 = createVerificationKeys(keyPair3.publicKey, MethodSpecificIdAlgo.Base58, 'key-3') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020, VerificationMethods.JWK, VerificationMethods.Ed255192018], [verificationKeys1, verificationKeys2, verificationKeys3]) - - const payload = createDidPayload(verificationMethods, [verificationKeys1, verificationKeys2, verificationKeys3]) - const { protobufVerificationMethod } = validateSpecCompliantPayload(payload) - - const didSigners = await signer.checkDidSigners(protobufVerificationMethod) - - expect(didSigners[VerificationMethods.Ed255192020]).toBe(EdDSASigner) - expect(didSigners[VerificationMethods.JWK]).toBe(EdDSASigner) - expect(didSigners[VerificationMethods.Ed255192018]).toBe(EdDSASigner) - }) - - it('should throw for non-supported verification method', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - const verificationMethod: Partial = { - id: nonExistingKeyId, - verificationMethodType: nonExistingVerificationMethod, - controller: nonExistingDid, - verificationMaterial: JSON.stringify({publicKeyMultibase: nonExistingPublicKeyMultibase}) - } - - await expect(signer.checkDidSigners([VerificationMethod.fromPartial(verificationMethod)])).rejects.toThrow() - }) - }) - - describe('signcreateDidDocTx', () => { - it('should sign a did tx with valid signature', async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic) - const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet) - const keyPair = createKeyPairBase64() - const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethods = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const didPayload = createDidPayload(verificationMethods, [verificationKeys]) - const signInputs: ISignInputs[] = [ - { - verificationMethodId: didPayload.verificationMethod![0].id, - privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex') - } - ] - const { protobufVerificationMethod, protobufService } = validateSpecCompliantPayload(didPayload) - const versionId = v4() - const payload = MsgCreateDidDocPayload.fromPartial({ - context: didPayload?.['@context'], - id: didPayload.id, - controller: didPayload.controller, - verificationMethod: protobufVerificationMethod, - authentication: didPayload.authentication, - assertionMethod: didPayload.assertionMethod, - capabilityInvocation: didPayload.capabilityInvocation, - capabilityDelegation: didPayload.capabilityDelegation, - keyAgreement: didPayload.keyAgreement, - service: protobufService, - alsoKnownAs: didPayload.alsoKnownAs, - versionId: versionId - }) - const signInfos = await signer.signcreateDidDocTx(signInputs, payload) - const publicKeyRaw = fromString(keyPair.publicKey, 'base64') - const messageRaw = MsgCreateDidDocPayload.encode(payload).finish() - - const verified = verify( - publicKeyRaw, - messageRaw, - signInfos[0].signature - ) - - expect(verified).toBe(true) - }) - }) -}) \ No newline at end of file + describe('constructor', () => { + it('can be instantiated & works for cheqd networks', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + expect(signer).toBeInstanceOf(CheqdSigningStargateClient); + }); + + it('can be constructed with cheqd custom registry', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const registry = new Registry(); + registry.register(typeUrlMsgCreateDidDoc, MsgCreateDidDoc); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry }); + expect(signer.registry.lookupType(typeUrlMsgCreateDidDoc)).toBe(MsgCreateDidDoc); + }); + }); + + describe('getDidSigner', () => { + it('can get a signer for a did', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1'); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const { protobufVerificationMethod } = validateSpecCompliantPayload(didPayload); + + const didSigner = await signer.getDidSigner( + didPayload.verificationMethod![0].id, + protobufVerificationMethod! + ); + + expect(didSigner).toBe(EdDSASigner); + }); + + it('should throw for a non-supported verification method', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + + await expect( + signer.getDidSigner( + nonExistingVerificationDidDocument.verificationMethod[0].id, + nonExistingVerificationDidDocument.verificationMethod + ) + ).rejects.toThrow(); + }); + + it('should throw for non-matching verification method id', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1'); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const payload = createDidPayload(verificationMethods, [verificationKeys]); + const { protobufVerificationMethod } = validateSpecCompliantPayload(payload); + + await expect(signer.getDidSigner(nonExistingKeyId, protobufVerificationMethod!)).rejects.toThrow(); + }); + }); + + describe('checkDidSigners', () => { + it('it should instantiate a signer for a did', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1'); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const payload = createDidPayload(verificationMethods, [verificationKeys]); + const { protobufVerificationMethod } = validateSpecCompliantPayload(payload); + const didSigners = await signer.checkDidSigners(protobufVerificationMethod); + + expect(didSigners[VerificationMethods.Ed255192020]).toBe(EdDSASigner); + }); + + it('should instantiate multiple signers for a did with multiple verification methods', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + const keyPair1 = createKeyPairBase64(); + const keyPair2 = createKeyPairBase64(); + const keyPair3 = createKeyPairBase64(); + const verificationKeys1 = createVerificationKeys(keyPair1.publicKey, MethodSpecificIdAlgo.Base58, 'key-1'); + const verificationKeys2 = createVerificationKeys(keyPair2.publicKey, MethodSpecificIdAlgo.Base58, 'key-2'); + const verificationKeys3 = createVerificationKeys(keyPair3.publicKey, MethodSpecificIdAlgo.Base58, 'key-3'); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020, VerificationMethods.JWK, VerificationMethods.Ed255192018], + [verificationKeys1, verificationKeys2, verificationKeys3] + ); + + const payload = createDidPayload(verificationMethods, [ + verificationKeys1, + verificationKeys2, + verificationKeys3, + ]); + const { protobufVerificationMethod } = validateSpecCompliantPayload(payload); + + const didSigners = await signer.checkDidSigners(protobufVerificationMethod); + + expect(didSigners[VerificationMethods.Ed255192020]).toBe(EdDSASigner); + expect(didSigners[VerificationMethods.JWK]).toBe(EdDSASigner); + expect(didSigners[VerificationMethods.Ed255192018]).toBe(EdDSASigner); + }); + + it('should throw for non-supported verification method', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + const verificationMethod: Partial = { + id: nonExistingKeyId, + verificationMethodType: nonExistingVerificationMethod, + controller: nonExistingDid, + verificationMaterial: JSON.stringify({ publicKeyMultibase: nonExistingPublicKeyMultibase }), + }; + + await expect( + signer.checkDidSigners([VerificationMethod.fromPartial(verificationMethod)]) + ).rejects.toThrow(); + }); + }); + + describe('signcreateDidDocTx', () => { + it('should sign a did tx with valid signature', async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet); + const keyPair = createKeyPairBase64(); + const verificationKeys = createVerificationKeys(keyPair.publicKey, MethodSpecificIdAlgo.Base58, 'key-1'); + const verificationMethods = createDidVerificationMethod( + [VerificationMethods.Ed255192020], + [verificationKeys] + ); + const didPayload = createDidPayload(verificationMethods, [verificationKeys]); + const signInputs: ISignInputs[] = [ + { + verificationMethodId: didPayload.verificationMethod![0].id, + privateKeyHex: toString(fromString(keyPair.privateKey, 'base64'), 'hex'), + }, + ]; + const { protobufVerificationMethod, protobufService } = validateSpecCompliantPayload(didPayload); + const versionId = v4(); + const payload = MsgCreateDidDocPayload.fromPartial({ + context: didPayload?.['@context'], + id: didPayload.id, + controller: didPayload.controller, + verificationMethod: protobufVerificationMethod, + authentication: didPayload.authentication, + assertionMethod: didPayload.assertionMethod, + capabilityInvocation: didPayload.capabilityInvocation, + capabilityDelegation: didPayload.capabilityDelegation, + keyAgreement: didPayload.keyAgreement, + service: protobufService, + alsoKnownAs: didPayload.alsoKnownAs, + versionId: versionId, + }); + const signInfos = await signer.signcreateDidDocTx(signInputs, payload); + const publicKeyRaw = fromString(keyPair.publicKey, 'base64'); + const messageRaw = MsgCreateDidDocPayload.encode(payload).finish(); + + const verified = verify(publicKeyRaw, messageRaw, signInfos[0].signature); + + expect(verified).toBe(true); + }); + }); +}); diff --git a/tests/testutils.test.ts b/tests/testutils.test.ts index bb7dae70..c02c887b 100644 --- a/tests/testutils.test.ts +++ b/tests/testutils.test.ts @@ -1,38 +1,47 @@ -import { GasPrice } from "@cosmjs/stargate" +import { GasPrice } from '@cosmjs/stargate'; export const faucet = { - prefix: 'cheqd', - minimalDenom: 'ncheq', - mnemonic: 'sketch mountain erode window enact net enrich smoke claim kangaroo another visual write meat latin bacon pulp similar forum guilt father state erase bright', - address: 'cheqd1rnr5jrt4exl0samwj0yegv99jeskl0hsxmcz96', -} + prefix: 'cheqd', + minimalDenom: 'ncheq', + mnemonic: + 'sketch mountain erode window enact net enrich smoke claim kangaroo another visual write meat latin bacon pulp similar forum guilt father state erase bright', + address: 'cheqd1rnr5jrt4exl0samwj0yegv99jeskl0hsxmcz96', +}; export const localnet = { - network: 'testnet', - rpcUrl: 'http://localhost:26657', - gasPrice: GasPrice.fromString( `50${faucet.minimalDenom}` ) -} + network: 'testnet', + rpcUrl: 'http://localhost:26657', + gasPrice: GasPrice.fromString(`50${faucet.minimalDenom}`), +}; -export const json_content = "{\"message\": \"hello world\"}" +export const json_content = '{"message": "hello world"}'; -export const image_content = 'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAAA1BMVEW10NBjBBbqAAAAH0lEQVRoge3BAQ0AAADCoPdPbQ43oAAAAAAAAAAAvg0hAAABmmDh1QAAAABJRU5ErkJggg' as const +export const image_content = + 'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAAA1BMVEW10NBjBBbqAAAAH0lEQVRoge3BAQ0AAADCoPdPbQ43oAAAAAAAAAAAvg0hAAABmmDh1QAAAABJRU5ErkJggg' as const; -export const default_content = '

Test file content

' +export const default_content = '

Test file content

'; -// They are connected -export const pubkey_hex = "04adf6cad45e58a7e1908bebefcc358de229c108fb1170566f83be5ce028eb6b1997711067ffcb445532667ed4a4efc2b334c16421edb52ec5e0324a1c0e570663" +// They are connected +export const pubkey_hex = + '04adf6cad45e58a7e1908bebefcc358de229c108fb1170566f83be5ce028eb6b1997711067ffcb445532667ed4a4efc2b334c16421edb52ec5e0324a1c0e570663'; -export const bech32_account = "cheqd1ehcg0jarxkyxtkzrwcxayedxrskwyftxj4exm9" +export const bech32_account = 'cheqd1ehcg0jarxkyxtkzrwcxayedxrskwyftxj4exm9'; // Testnet RPC and faucet address -export const faucet_address = "cheqd1rnr5jrt4exl0samwj0yegv99jeskl0hsxmcz96" +export const faucet_address = 'cheqd1rnr5jrt4exl0samwj0yegv99jeskl0hsxmcz96'; -export const testnet_rpc = "https://rpc.cheqd.network:443" +export const testnet_rpc = 'https://rpc.cheqd.network:443'; export function containsAll(array: T[], values: T[]): boolean { - return values.every(value => array.includes(value)) + return values.every((value) => array.includes(value)); } -export function containsAllButOmittedFields>(array: T[], values: T[], omit: string[]): boolean { - const replacer = (key: string, value: any) => omit.includes(key) ? undefined : value - return values.every(value => array.some(item => JSON.stringify(item, replacer) === JSON.stringify(value, replacer))) -} \ No newline at end of file +export function containsAllButOmittedFields>( + array: T[], + values: T[], + omit: string[] +): boolean { + const replacer = (key: string, value: any) => (omit.includes(key) ? undefined : value); + return values.every((value) => + array.some((item) => JSON.stringify(item, replacer) === JSON.stringify(value, replacer)) + ); +} diff --git a/tests/utils.test.ts b/tests/utils.test.ts index 824cf390..32ae534a 100644 --- a/tests/utils.test.ts +++ b/tests/utils.test.ts @@ -1,138 +1,138 @@ import { - TImportableEd25519Key, - checkBalance, - createSignInputsFromImportableEd25519Key, - getCosmosAccount, - isJSON, -} from '../src/utils' -import { - createDidVerificationMethod, - createVerificationKeys, - createKeyPairRaw -} from '../src/utils' -import { toString } from 'uint8arrays/to-string' -import { - IKeyPair, - MethodSpecificIdAlgo, - VerificationMethods -} from '../src/types' -import { faucet_address, pubkey_hex, testnet_rpc } from './testutils.test' + TImportableEd25519Key, + checkBalance, + createSignInputsFromImportableEd25519Key, + getCosmosAccount, + isJSON, +} from '../src/utils'; +import { createDidVerificationMethod, createVerificationKeys, createKeyPairRaw } from '../src/utils'; +import { toString } from 'uint8arrays/to-string'; +import { IKeyPair, MethodSpecificIdAlgo, VerificationMethods } from '../src/types'; +import { faucet_address, pubkey_hex, testnet_rpc } from './testutils.test'; describe('createSignInputsFromImportableEd25519Key', () => { - it('should create a sign input from an importable ed25519 key 2020', async () => { - const keyPair = createKeyPairRaw() - const importableEd25519Key: TImportableEd25519Key = { - publicKeyHex: toString(keyPair.publicKey, 'hex'), - privateKeyHex: toString(keyPair.secretKey, 'hex'), - kid: toString(keyPair.publicKey, 'hex'), - type: 'Ed25519' - } - const keyPairBase64: IKeyPair = { - publicKey: toString(keyPair.publicKey, 'base64'), - privateKey: toString(keyPair.secretKey, 'base64'), - } - - const verificationKeys = createVerificationKeys(keyPairBase64.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethod = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]) - const signInput = createSignInputsFromImportableEd25519Key(importableEd25519Key, verificationMethod) - - expect(signInput).toEqual({ verificationMethodId: verificationKeys.keyId, privateKeyHex: importableEd25519Key.privateKeyHex }) - }) - - it('should create a sign input from an importable ed25519 key 2018', async () => { - const keyPair = createKeyPairRaw() - const importableEd25519Key: TImportableEd25519Key = { - publicKeyHex: toString(keyPair.publicKey, 'hex'), - privateKeyHex: toString(keyPair.secretKey, 'hex'), - kid: toString(keyPair.publicKey, 'hex'), - type: 'Ed25519' - } - const keyPairBase64: IKeyPair = { - publicKey: toString(keyPair.publicKey, 'base64'), - privateKey: toString(keyPair.secretKey, 'base64'), - } - - const verificationKeys = createVerificationKeys(keyPairBase64.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethod = createDidVerificationMethod([VerificationMethods.Ed255192018], [verificationKeys]) - const signInput = createSignInputsFromImportableEd25519Key(importableEd25519Key, verificationMethod) - - expect(signInput).toEqual({ verificationMethodId: verificationKeys.keyId, privateKeyHex: importableEd25519Key.privateKeyHex }) - }) - - it('should create a sign input from an importable ed25519 key with VM type JWK', () => { - const keyPair = createKeyPairRaw() - const importableEd25519Key: TImportableEd25519Key = { - publicKeyHex: toString(keyPair.publicKey, 'hex'), - privateKeyHex: toString(keyPair.secretKey, 'hex'), - kid: toString(keyPair.publicKey, 'hex'), - type: 'Ed25519' - } - const keyPairBase64: IKeyPair = { - publicKey: toString(keyPair.publicKey, 'base64'), - privateKey: toString(keyPair.secretKey, 'base64'), - } - - const verificationKeys = createVerificationKeys(keyPairBase64.publicKey, MethodSpecificIdAlgo.Base58, 'key-1') - const verificationMethod = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]) - const signInput = createSignInputsFromImportableEd25519Key(importableEd25519Key, verificationMethod) - - expect(signInput).toEqual({ verificationMethodId: verificationKeys.keyId, privateKeyHex: importableEd25519Key.privateKeyHex }) - }) - - it('should get the cosmos account from publicKeyHex', () => { - // We know, that such point could be transformed to a cheqd account cheqd1ehcg0jarxkyxtkzrwcxayedxrskwyftxj4exm9 - const expectedAddress = "cheqd1ehcg0jarxkyxtkzrwcxayedxrskwyftxj4exm9" - - expect(expectedAddress).toEqual(getCosmosAccount(pubkey_hex)) - - }) - - it('should return not empty account balance', async () => { - const balances = await checkBalance(faucet_address, testnet_rpc) - expect(balances.length).toBeGreaterThan(0) - expect(balances[0].denom).toEqual("ncheq") - expect(+balances[0].amount).toBeGreaterThan(0) - }) - - it('should return valid json', async () => { - // define invalid cases - const invalid = [ - 'invalid', - '{invalid: json}', - '{"invalid": "json"', - '"invalid": "json"}', - '{""}', - 0, - 1, - true, - null, - undefined, - ] - - // define valid cases - const valid = [ - '{"valid": "json"}', - '{"valid": "json", "with": "multiple", "keys": "and", "values": "of", "different": "types"}', - '{"valid": "json", "with": "multiple", "keys": "and", "values": "of", "different": "types", "and": {"nested": "objects"}}', - '{"valid": "json", "with": "multiple", "keys": "and", "values": "of", "different": "types", "and": {"nested": "objects", "and": {"even": {"more": {"nested": "objects"}}}}}', - '{"": ""}', - '{"boolean": true}', - '{"boolean": false}', - '{"number": 0}', - '{"nullish": null}', - '{"array": []}', - '{"array": [1, 2, 3]}', - '{"array": [1, 2, 3], "with": ["multiple", "arrays"]}', - ] - - // check invalid cases - invalid.forEach((invalidCase) => { - expect(isJSON(invalidCase)).toBe(false) - }) - - // check valid cases - valid.forEach((validCase) => { - expect(isJSON(validCase)).toBe(true) - }) - }) -}) \ No newline at end of file + it('should create a sign input from an importable ed25519 key 2020', async () => { + const keyPair = createKeyPairRaw(); + const importableEd25519Key: TImportableEd25519Key = { + publicKeyHex: toString(keyPair.publicKey, 'hex'), + privateKeyHex: toString(keyPair.secretKey, 'hex'), + kid: toString(keyPair.publicKey, 'hex'), + type: 'Ed25519', + }; + const keyPairBase64: IKeyPair = { + publicKey: toString(keyPair.publicKey, 'base64'), + privateKey: toString(keyPair.secretKey, 'base64'), + }; + + const verificationKeys = createVerificationKeys(keyPairBase64.publicKey, MethodSpecificIdAlgo.Base58, 'key-1'); + const verificationMethod = createDidVerificationMethod([VerificationMethods.Ed255192020], [verificationKeys]); + const signInput = createSignInputsFromImportableEd25519Key(importableEd25519Key, verificationMethod); + + expect(signInput).toEqual({ + verificationMethodId: verificationKeys.keyId, + privateKeyHex: importableEd25519Key.privateKeyHex, + }); + }); + + it('should create a sign input from an importable ed25519 key 2018', async () => { + const keyPair = createKeyPairRaw(); + const importableEd25519Key: TImportableEd25519Key = { + publicKeyHex: toString(keyPair.publicKey, 'hex'), + privateKeyHex: toString(keyPair.secretKey, 'hex'), + kid: toString(keyPair.publicKey, 'hex'), + type: 'Ed25519', + }; + const keyPairBase64: IKeyPair = { + publicKey: toString(keyPair.publicKey, 'base64'), + privateKey: toString(keyPair.secretKey, 'base64'), + }; + + const verificationKeys = createVerificationKeys(keyPairBase64.publicKey, MethodSpecificIdAlgo.Base58, 'key-1'); + const verificationMethod = createDidVerificationMethod([VerificationMethods.Ed255192018], [verificationKeys]); + const signInput = createSignInputsFromImportableEd25519Key(importableEd25519Key, verificationMethod); + + expect(signInput).toEqual({ + verificationMethodId: verificationKeys.keyId, + privateKeyHex: importableEd25519Key.privateKeyHex, + }); + }); + + it('should create a sign input from an importable ed25519 key with VM type JWK', () => { + const keyPair = createKeyPairRaw(); + const importableEd25519Key: TImportableEd25519Key = { + publicKeyHex: toString(keyPair.publicKey, 'hex'), + privateKeyHex: toString(keyPair.secretKey, 'hex'), + kid: toString(keyPair.publicKey, 'hex'), + type: 'Ed25519', + }; + const keyPairBase64: IKeyPair = { + publicKey: toString(keyPair.publicKey, 'base64'), + privateKey: toString(keyPair.secretKey, 'base64'), + }; + + const verificationKeys = createVerificationKeys(keyPairBase64.publicKey, MethodSpecificIdAlgo.Base58, 'key-1'); + const verificationMethod = createDidVerificationMethod([VerificationMethods.JWK], [verificationKeys]); + const signInput = createSignInputsFromImportableEd25519Key(importableEd25519Key, verificationMethod); + + expect(signInput).toEqual({ + verificationMethodId: verificationKeys.keyId, + privateKeyHex: importableEd25519Key.privateKeyHex, + }); + }); + + it('should get the cosmos account from publicKeyHex', () => { + // We know, that such point could be transformed to a cheqd account cheqd1ehcg0jarxkyxtkzrwcxayedxrskwyftxj4exm9 + const expectedAddress = 'cheqd1ehcg0jarxkyxtkzrwcxayedxrskwyftxj4exm9'; + + expect(expectedAddress).toEqual(getCosmosAccount(pubkey_hex)); + }); + + it('should return not empty account balance', async () => { + const balances = await checkBalance(faucet_address, testnet_rpc); + expect(balances.length).toBeGreaterThan(0); + expect(balances[0].denom).toEqual('ncheq'); + expect(+balances[0].amount).toBeGreaterThan(0); + }); + + it('should return valid json', async () => { + // define invalid cases + const invalid = [ + 'invalid', + '{invalid: json}', + '{"invalid": "json"', + '"invalid": "json"}', + '{""}', + 0, + 1, + true, + null, + undefined, + ]; + + // define valid cases + const valid = [ + '{"valid": "json"}', + '{"valid": "json", "with": "multiple", "keys": "and", "values": "of", "different": "types"}', + '{"valid": "json", "with": "multiple", "keys": "and", "values": "of", "different": "types", "and": {"nested": "objects"}}', + '{"valid": "json", "with": "multiple", "keys": "and", "values": "of", "different": "types", "and": {"nested": "objects", "and": {"even": {"more": {"nested": "objects"}}}}}', + '{"": ""}', + '{"boolean": true}', + '{"boolean": false}', + '{"number": 0}', + '{"nullish": null}', + '{"array": []}', + '{"array": [1, 2, 3]}', + '{"array": [1, 2, 3], "with": ["multiple", "arrays"]}', + ]; + + // check invalid cases + invalid.forEach((invalidCase) => { + expect(isJSON(invalidCase)).toBe(false); + }); + + // check valid cases + valid.forEach((validCase) => { + expect(isJSON(validCase)).toBe(true); + }); + }); +});