diff --git a/.gitignore b/.gitignore index 421b39a5..c659f56c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ dist # IntelliJ Project Files .idea coverage/* + diff --git a/README.md b/README.md index e5b5dd67..fee4e067 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,12 @@ Typescript source files needs to be transpiled before running scripts or integra npm run build ``` + To build and generate TypeScript types from KERIA OpenAPI docs dynamically + + ``` + SPEC_URL=http://localhost:3902/spec.yaml npm run build + ``` + - ready() must be called before library is useable. Example minimum viable client code. ```javascript diff --git a/package.json b/package.json index e7feae32..fc2ae03c 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ ], "scripts": { "start": "npm run build -- --watch", - "build": "tsc -p tsconfig.build.json && tsc -p tsconfig.json --noEmit", + "generate:types": "node scripts/generate-types.js", + "build": "npm run generate:types && tsc -p tsconfig.build.json && tsc -p tsconfig.json --noEmit", "test": "vitest", "prepare": "tsc -p tsconfig.build.json", "test:integration": "vitest -c vitest.integration.ts", diff --git a/scripts/generate-types.js b/scripts/generate-types.js new file mode 100644 index 00000000..33a88671 --- /dev/null +++ b/scripts/generate-types.js @@ -0,0 +1,36 @@ +import { execSync } from 'child_process'; +import fs from 'fs'; +import path from 'path'; + +const specUrl = process.env.SPEC_URL; +const outputFile = path.resolve('src/types/keria-api-schema.ts'); + +if (!specUrl) { + console.log('⚠️ Skipping OpenAPI type generation: SPEC_URL is not set.'); + process.exit(0); +} + +console.log(`📦 Generating types from ${specUrl}`); +execSync(`npx openapi-typescript "${specUrl}" --output ${outputFile} --enum`, { + stdio: 'inherit', +}); + +// Read the full file +const fullContent = fs.readFileSync(outputFile, 'utf8'); + +// Extract the `export interface components { ... }` block +const componentsMatch = fullContent.match(/export interface components \{[\s\S]+?\n\}/); + +// Extract all `export enum ... { ... }` blocks +const enumMatches = [...fullContent.matchAll(/export enum [\w\d_]+ \{[\s\S]+?\n\}/g)]; + +if (!componentsMatch) { + console.error("❌ Could not find 'export interface components' block."); + process.exit(1); +} + +// Combine the interface and enums +const enumsText = enumMatches.map(m => m[0]).join('\n\n'); +const cleaned = `// AUTO-GENERATED: Only components and enums retained from OpenAPI schema\n\n${enumsText}\n\n${componentsMatch[0]}\n`; + +fs.writeFileSync(outputFile, cleaned, 'utf8'); diff --git a/src/keri/app/aiding.ts b/src/keri/app/aiding.ts index 6cfa9300..b4b13324 100644 --- a/src/keri/app/aiding.ts +++ b/src/keri/app/aiding.ts @@ -1,13 +1,14 @@ -import { Tier } from '../core/salter.ts'; -import { Algos } from '../core/manager.ts'; -import { incept, interact, reply, rotate } from '../core/eventing.ts'; +import { components } from '../../types/keria-api-schema.ts'; import { b, Ilks, Serials, Vrsn_1_0 } from '../core/core.ts'; -import { Tholder } from '../core/tholder.ts'; -import { MtrDex } from '../core/matter.ts'; -import { Serder } from '../core/serder.ts'; +import { incept, interact, reply, EndRoleAddAttributes, rotate } from '../core/eventing.ts'; import { parseRangeHeaders } from '../core/httping.ts'; import { IdentifierManagerFactory } from '../core/keeping.ts'; import { HabState } from '../core/keyState.ts'; +import { Algos } from '../core/manager.ts'; +import { MtrDex } from '../core/matter.ts'; +import { Tier } from '../core/salter.ts'; +import { Serder } from '../core/serder.ts'; +import { Tholder } from '../core/tholder.ts'; /** Arguments required to create an identfier */ export interface CreateIdentiferArgs { @@ -73,6 +74,8 @@ export interface IdentifierInfo { name: string; } +export type GroupMember = components['schemas']['GroupMember']; + /** Identifier */ export class Identifier { public client: IdentifierDeps; @@ -472,7 +475,7 @@ export class Identifier { eid?: string, stamp?: string ): Serder { - const data: any = { + const data: EndRoleAddAttributes = { cid: pre, role: role, }; @@ -487,9 +490,9 @@ export class Identifier { * Get the members of a group identifier * @async * @param {string} name - Name or alias of the identifier - * @returns {Promise} - A promise to the list of members + * @returns {Promise} - A promise to the list of members */ - async members(name: string): Promise { + async members(name: string): Promise { const res = await this.client.fetch( '/identifiers/' + name + '/members', 'GET', diff --git a/src/keri/app/clienting.ts b/src/keri/app/clienting.ts index add940ba..789836d9 100644 --- a/src/keri/app/clienting.ts +++ b/src/keri/app/clienting.ts @@ -1,12 +1,13 @@ +import { components } from '../../types/keria-api-schema.ts'; import { Authenticater } from '../core/authing.ts'; import { HEADER_SIG_TIME } from '../core/httping.ts'; import { ExternalModule, IdentifierManagerFactory } from '../core/keeping.ts'; import { Tier } from '../core/salter.ts'; import { Identifier } from './aiding.ts'; -import { Contacts, Challenges } from './contacting.ts'; +import { Challenges, Contacts } from './contacting.ts'; import { Agent, Controller } from './controller.ts'; -import { Oobis, Operations, KeyEvents, KeyStates, Config } from './coring.ts'; +import { Config, KeyEvents, KeyStates, Oobis, Operations } from './coring.ts'; import { Credentials, Ipex, Registries, Schemas } from './credentialing.ts'; import { Delegations } from './delegating.ts'; import { Escrows } from './escrowing.ts'; @@ -16,6 +17,9 @@ import { Notifications } from './notifying.ts'; const DEFAULT_BOOT_URL = 'http://localhost:3903'; +// Export type outside the class +export type AgentResourceResult = components["schemas"]["AgentResourceResult"]; + class State { agent: any | null; controller: any | null; @@ -117,7 +121,7 @@ export class SignifyClient { throw new Error(`agent does not exist for controller ${caid}`); } - const data = await res.json(); + const data = await res.json() as AgentResourceResult; const state = new State(); state.agent = data.agent ?? {}; state.controller = data.controller ?? {}; @@ -147,7 +151,7 @@ export class SignifyClient { 'commitment to controller AID missing in agent inception event' ); } - if (this.controller.serder.sad.s == 0) { + if (Number(this.controller.serder.sad.s) == 0) { await this.approveDelegation(); } this.manager = new IdentifierManagerFactory( @@ -172,7 +176,7 @@ export class SignifyClient { async fetch( path: string, method: string, - data: any, + data: unknown | null | undefined, extraHeaders?: Headers ): Promise { const headers = new Headers(); diff --git a/src/keri/app/contacting.ts b/src/keri/app/contacting.ts index 2af3e1ec..5deb6d5c 100644 --- a/src/keri/app/contacting.ts +++ b/src/keri/app/contacting.ts @@ -1,12 +1,9 @@ import { SignifyClient } from './clienting.ts'; import { Operation } from './coring.ts'; +import { components } from '../../types/keria-api-schema.ts'; -export interface Contact { - alias: string; - oobi: string; - id: string; - [key: string]: unknown; -} + +export type Contact = components['schemas']['Contact']; export interface ContactInfo { [key: string]: unknown; @@ -111,9 +108,7 @@ export class Contacts { } } -export interface Challenge { - words: string[]; -} +export type Challenge = components['schemas']['Challenge']; /** * Challenges @@ -189,15 +184,15 @@ export class Challenges { * Mark challenge response as signed and accepted * @param source Prefix of the identifier that was challenged * @param said qb64 AID of exn message representing the signed response - * @returns {Promise} A promise to the result + * @returns {Promise>} A promise to the result */ - async responded(source: string, said: string): Promise { + async responded(source: string, said: string): Promise> { const path = `/challenges_verify/${source}`; const method = 'PUT'; const data = { said: said, }; const res = await this.client.fetch(path, method, data); - return res; + return await res.json() as Operation; } } diff --git a/src/keri/app/controller.ts b/src/keri/app/controller.ts index 2495ee9e..7c8f36dd 100644 --- a/src/keri/app/controller.ts +++ b/src/keri/app/controller.ts @@ -1,17 +1,18 @@ +import { Cipher } from '../core/cipher.ts'; +import { b, Ilks, Serials, Vrsn_1_0 } from '../core/core.ts'; +import { Decrypter } from '../core/decrypter.ts'; +import { Diger } from '../core/diger.ts'; +import { Encrypter } from '../core/encrypter.ts'; +import { incept, InceptEventSAD, interact, InteractEventSAD, rotate } from '../core/eventing.ts'; import { SaltyCreator } from '../core/manager.ts'; -import { Salter, Tier } from '../core/salter.ts'; import { MtrDex } from '../core/matter.ts'; -import { Diger } from '../core/diger.ts'; -import { incept, rotate, interact } from '../core/eventing.ts'; +import { CesrNumber } from '../core/number.ts'; +import { Salter, Tier } from '../core/salter.ts'; +import { Seqner } from '../core/seqner.ts'; import { Serder } from '../core/serder.ts'; +import { Signer } from '../core/signer.ts'; import { Tholder } from '../core/tholder.ts'; -import { Ilks, b, Serials, Vrsn_1_0 } from '../core/core.ts'; import { Verfer } from '../core/verfer.ts'; -import { Encrypter } from '../core/encrypter.ts'; -import { Decrypter } from '../core/decrypter.ts'; -import { Cipher } from '../core/cipher.ts'; -import { Seqner } from '../core/seqner.ts'; -import { CesrNumber } from '../core/number.ts'; /** * Agent is a custodial entity that can be used in conjuntion with a local Client to establish the @@ -128,7 +129,7 @@ export class Controller { /** * Either the current establishment event, inception or rotation, or the interaction event used for delegation approval. */ - public serder: Serder; + public serder: Serder; /** * Current public keys formatted in fully-qualified Base64. * @private @@ -227,8 +228,9 @@ export class Controller { approveDelegation(_agent: Agent) { const seqner = new Seqner({ sn: _agent.sn }); - const anchor = { i: _agent.pre, s: seqner.snh, d: _agent.said }; - const sn = new CesrNumber({}, undefined, this.serder.sad['s']).num + 1; + const anchor = { i: _agent.pre, s: seqner.snh, d: _agent.said! }; + const sn = + new CesrNumber({}, undefined, this.serder.sad['s']).num + 1; this.serder = interact({ pre: this.serder.pre, dig: this.serder.sad['d'], @@ -265,7 +267,10 @@ export class Controller { wits: [], }); } else { - return new Serder({ sad: state.controller['ee'] }); + return new Serder({ + sad: state.controller['ee'], + d: '', + }); } } @@ -386,7 +391,7 @@ export class Controller { const signers = []; for (const prx of prxs) { const cipher = new Cipher({ qb64: prx }); - const dsigner = decrypter.decrypt(null, cipher, true); + const dsigner = decrypter.decrypt(null, cipher, true) as Signer; signers.push(dsigner); nprxs.push(encrypter.encrypt(b(dsigner.qb64)).qb64); } diff --git a/src/keri/app/coring.ts b/src/keri/app/coring.ts index 6f7daaf4..a6df21c7 100644 --- a/src/keri/app/coring.ts +++ b/src/keri/app/coring.ts @@ -2,6 +2,13 @@ import { SignifyClient } from './clienting.ts'; import libsodium from 'libsodium-wrappers-sumo'; import { Salter } from '../core/salter.ts'; import { Matter, MtrDex } from '../core/matter.ts'; +import { components } from '../../types/keria-api-schema.ts'; + +type OperationBase = components['schemas']['OperationBase']; +type OOBI = components['schemas']['OOBI']; +type KeyState = components['schemas']['KeyStateRecord']; +type KeyEventRecord = components['schemas']['KeyEventRecord']; +type AgentConfig = components['schemas']['AgentConfig']; export function randomPasscode(): string { const raw = libsodium.randombytes_buf(16); @@ -33,7 +40,7 @@ export class Oobis { * @param {string} role Authorized role * @returns {Promise} A promise to the OOBI(s) */ - async get(name: string, role: string = 'agent'): Promise { + async get(name: string, role: string = 'agent'): Promise { const path = `/identifiers/${name}/oobis?role=${role}`; const method = 'GET'; const res = await this.client.fetch(path, method, null); @@ -45,9 +52,9 @@ export class Oobis { * @async * @param {string} oobi The OOBI to be resolver * @param {string} [alias] Optional name or alias to link the OOBI resolution to a contact - * @returns {Promise} A promise to the long-running operation + * @returns {Promise>} A promise to the long-running operation */ - async resolve(oobi: string, alias?: string): Promise { + async resolve(oobi: string, alias?: string): Promise> { const path = `/oobis`; const data: any = { url: oobi, @@ -61,16 +68,13 @@ export class Oobis { } } -export interface Operation { - name: string; +export type Operation = OperationBase & { + response?: T; metadata?: { depends?: Operation; [property: string]: any; }; - done?: boolean; - error?: any; - response?: T; -} +}; export interface OperationsDeps { fetch( @@ -81,10 +85,6 @@ export interface OperationsDeps { ): Promise; } -export interface AgentConfig { - iurls?: string[]; -} - /** * Operations * @remarks @@ -204,9 +204,9 @@ export class KeyEvents { * Retrieve key events for an identifier * @async * @param {string} pre Identifier prefix - * @returns {Promise} A promise to the key events + * @returns {Promise} A promise to the key events */ - async get(pre: string): Promise { + async get(pre: string): Promise { const path = `/events?pre=${pre}`; const data = null; const method = 'GET'; @@ -232,9 +232,9 @@ export class KeyStates { * Retriene the key state for an identifier * @async * @param {string} pre Identifier prefix - * @returns {Promise} A promise to the key states + * @returns {Promise} A promise to the key states */ - async get(pre: string): Promise { + async get(pre: string): Promise { const path = `/states?pre=${pre}`; const data = null; const method = 'GET'; @@ -248,7 +248,7 @@ export class KeyStates { * @param {Array} pres List of identifier prefixes * @returns {Promise} A promise to the key states */ - async list(pres: string[]): Promise { + async list(pres: string[]): Promise { const path = `/states?${pres.map((pre) => `pre=${pre}`).join('&')}`; const data = null; const method = 'GET'; @@ -262,9 +262,9 @@ export class KeyStates { * @param {string} pre Identifier prefix * @param {number} [sn] Optional sequence number * @param {any} [anchor] Optional anchor - * @returns {Promise} A promise to the long-running operation + * @returns {Promise>} A promise to the long-running operation */ - async query(pre: string, sn?: string, anchor?: any): Promise { + async query(pre: string, sn?: string, anchor?: any): Promise> { const path = `/queries`; const data: any = { pre: pre, diff --git a/src/keri/app/credentialing.ts b/src/keri/app/credentialing.ts index 9c342da0..8b94a769 100644 --- a/src/keri/app/credentialing.ts +++ b/src/keri/app/credentialing.ts @@ -1,26 +1,32 @@ -import { SignifyClient } from './clienting.ts'; -import { interact, messagize } from '../core/eventing.ts'; -import { vdr } from '../core/vdring.ts'; import { b, d, Dict, - Protocols, Ilks, + Protocols, Serials, versify, Vrsn_1_0, } from '../core/core.ts'; -import { Saider } from '../core/saider.ts'; +import { interact, SealSourceTriple, messagize } from '../core/eventing.ts'; +import { HabState } from '../core/keyState.ts'; +import { BaseSAD, Saider } from '../core/saider.ts'; import { Serder } from '../core/serder.ts'; import { Siger } from '../core/siger.ts'; -import { TraitDex } from './habery.ts'; import { serializeACDCAttachment, serializeIssExnAttachment, } from '../core/utils.ts'; +import { vdr } from '../core/vdring.ts'; +import { SignifyClient } from './clienting.ts'; import { Operation } from './coring.ts'; -import { HabState } from '../core/keyState.ts'; +import { TraitDex } from './habery.ts'; + +import { components } from '../../types/keria-api-schema.ts'; + +export type CredentialResult = components['schemas']['Credential']; +export type Registry = components['schemas']['Registry']; +export type Schema = components['schemas']['Schema']; /** Types of credentials */ export class CredentialTypes { @@ -229,25 +235,7 @@ export interface IpexAdmitArgs { datetime?: string; } -export type CredentialState = { - vn: [number, number]; - i: string; - s: string; - d: string; - ri: string; - a: { s: number; d: string }; - dt: string; - et: string; -} & ( - | { - et: 'iss' | 'rev'; - ra: Record; - } - | { - et: 'bis' | 'brv'; - ra: { i: string; s: string; d: string }; - } -); +export type CredentialState = components['schemas']['CredentialState']; /** * Credentials @@ -266,9 +254,9 @@ export class Credentials { * List credentials * @async * @param {CredentialFilter} [kargs] Optional parameters to filter the credentials - * @returns {Promise} A promise to the list of credentials + * @returns {Promise} A promise to the list of credentials */ - async list(kargs: CredentialFilter = {}): Promise { + async list(kargs: CredentialFilter = {}): Promise { const path = `/credentials/query`; const filtr = kargs.filter === undefined ? {} : kargs.filter; const sort = kargs.sort === undefined ? [] : kargs.sort; @@ -292,9 +280,15 @@ export class Credentials { * @async * @param {string} said - SAID of the credential * @param {boolean} [includeCESR=false] - Optional flag export the credential in CESR format - * @returns {Promise} A promise to the credential + * @returns {Promise} A promise to the credential */ - async get(said: string, includeCESR: boolean = false): Promise { + async get(said: string): Promise; + async get(said: string, includeCESR: false): Promise; + async get(said: string, includeCESR: true): Promise; + async get( + said: string, + includeCESR: boolean = false + ): Promise { const path = `/credentials/${said}`; const method = 'GET'; const headers = includeCESR @@ -423,7 +417,7 @@ export class Credentials { * @param {string} name Name or alias of the identifier * @param {string} said SAID of the credential * @param {string} datetime date time of revocation - * @returns {Promise} A promise to the long-running operation + * @returns {Promise} A promise to the long-running operation */ async revoke( name: string, @@ -454,20 +448,16 @@ export class Credentials { const [, rev] = Saider.saidify(_rev); // create ixn - let ixn = {}; + let ixn: BaseSAD; let sigs = []; const state = hab.state; - if (state.c !== undefined && state.c.includes('EO')) { - var estOnly = true; - } else { - var estOnly = false; - } + const estOnly = state.c !== undefined && state.c.includes('EO'); const sn = parseInt(state.s, 16); const dig = state.d; - const data: any = [ + const data: SealSourceTriple[] = [ { i: rev.i, s: rev.s, @@ -552,7 +542,7 @@ export class RegistryResult { return this._sigs; } - async op(): Promise { + async op(): Promise { const res = await this.promise; return await res.json(); } @@ -575,9 +565,9 @@ export class Registries { * List registries * @async * @param {string} name Name or alias of the identifier - * @returns {Promise} A promise to the list of registries + * @returns {Promise} A promise to the list of registries */ - async list(name: string): Promise { + async list(name: string): Promise { const path = `/identifiers/${name}/registries`; const method = 'GET'; const res = await this.client.fetch(path, method, null); @@ -680,13 +670,13 @@ export class Registries { * @param {string} name Name or alias of the identifier * @param {string} registryName Current registry name * @param {string} newName New registry name - * @returns {Promise} A promise to the registry record + * @returns {Promise} A promise to the registry record */ async rename( name: string, registryName: string, newName: string - ): Promise { + ): Promise { const path = `/identifiers/${name}/registries/${registryName}`; const method = 'PUT'; const data = { @@ -713,9 +703,9 @@ export class Schemas { * Get a schema * @async * @param {string} said SAID of the schema - * @returns {Promise} A promise to the schema + * @returns {Promise} A promise to the schema */ - async get(said: string): Promise { + async get(said: string): Promise { const path = `/schema/${said}`; const method = 'GET'; const res = await this.client.fetch(path, method, null); @@ -725,9 +715,9 @@ export class Schemas { /** * List schemas * @async - * @returns {Promise} A promise to the list of schemas + * @returns {Promise} A promise to the list of schemas */ - async list(): Promise { + async list(): Promise { const path = `/schema`; const method = 'GET'; const res = await this.client.fetch(path, method, null); diff --git a/src/keri/app/delegating.ts b/src/keri/app/delegating.ts index cccb30d9..3840401d 100644 --- a/src/keri/app/delegating.ts +++ b/src/keri/app/delegating.ts @@ -1,3 +1,4 @@ +import { SealSourceTriple } from '../core/eventing.ts'; import { EventResult } from './aiding.ts'; import { SignifyClient } from './clienting.ts'; @@ -18,7 +19,7 @@ export class Delegations { * @param {any} [data] The anchoring interaction event * @returns {Promise} A promise to the delegated approval result */ - async approve(name: string, data?: any): Promise { + async approve(name: string, data: SealSourceTriple): Promise { const { serder, sigs, jsondata } = await this.client .identifiers() .createInteract(name, data); diff --git a/src/keri/app/escrowing.ts b/src/keri/app/escrowing.ts index a72fbc02..bdfe4c86 100644 --- a/src/keri/app/escrowing.ts +++ b/src/keri/app/escrowing.ts @@ -1,5 +1,8 @@ import { SignifyClient } from './clienting.ts'; +import { components } from '../../types/keria-api-schema.ts'; + +export type Rpy = components['schemas']['Rpy']; /** * Escrows */ @@ -18,9 +21,9 @@ export class Escrows { * List replay messages * @async * @param {string} [route] Optional route in the replay message - * @returns {Promise} A promise to the list of replay messages + * @returns {Promise} A promise to the list of replay messages */ - async listReply(route?: string): Promise { + async listReply(route?: string): Promise { const params = new URLSearchParams(); if (route !== undefined) { params.append('route', route); diff --git a/src/keri/app/exchanging.ts b/src/keri/app/exchanging.ts index 94946649..1faf43cc 100644 --- a/src/keri/app/exchanging.ts +++ b/src/keri/app/exchanging.ts @@ -4,7 +4,7 @@ import { Serder } from '../core/serder.ts'; import { nowUTC } from '../core/utils.ts'; import { Pather } from '../core/pather.ts'; import { Counter, CtrDex } from '../core/counter.ts'; -import { Saider } from '../core/saider.ts'; +import { BaseSAD, Saider } from '../core/saider.ts'; import { HabState } from '../core/keyState.ts'; /** @@ -165,7 +165,7 @@ export function exchange( const q = modifiers !== undefined ? modifiers : {}; const ems = embeds != undefined ? embeds : {}; - let e = {} as Dict; + let e = {} as BaseSAD; let end = ''; Object.entries(ems).forEach(([key, value]) => { const serder = value[0]; diff --git a/src/keri/app/habery.ts b/src/keri/app/habery.ts index eeacadfd..b21beca9 100644 --- a/src/keri/app/habery.ts +++ b/src/keri/app/habery.ts @@ -1,10 +1,10 @@ +import { Diger } from '../core/diger.ts'; +import { incept } from '../core/eventing.ts'; import { Algos, Manager } from '../core/manager.ts'; import { MtrDex } from '../core/matter.ts'; import { Salter } from '../core/salter.ts'; +import { Serder, SerderSAD } from '../core/serder.ts'; import { Verfer } from '../core/verfer.ts'; -import { Diger } from '../core/diger.ts'; -import { incept } from '../core/eventing.ts'; -import { Serder } from '../core/serder.ts'; export class TraitCodex { EstOnly: string = 'EO'; // Only allow establishment events @@ -39,16 +39,16 @@ export interface MakeHabArgs { data?: any; } -export class Hab { +export class Hab { public name: string; - public serder: Serder; + public serder: Serder; - constructor(name: string, icp: Serder) { + constructor(name: string, icp: Serder) { this.name = name; this.serder = icp; } - get pre(): string { + get pre(): T['i'] { return this.serder.sad['i']; } } diff --git a/src/keri/core/authing.ts b/src/keri/core/authing.ts index 424979ea..92e55c98 100644 --- a/src/keri/core/authing.ts +++ b/src/keri/core/authing.ts @@ -41,7 +41,11 @@ export class Authenticater { } inputs.forEach((input) => { const items = new Array(); - input.fields!.forEach((field: string) => { + input.fields!.forEach((field) => { + if (typeof field !== 'string') { + throw new Error("Invalid siginput field type"); + } + if (field.startsWith('@')) { if (field == '@method') { items.push(`"${field}": ${method}`); diff --git a/src/keri/core/decrypter.ts b/src/keri/core/decrypter.ts index 4e5f04db..6ad83cb0 100644 --- a/src/keri/core/decrypter.ts +++ b/src/keri/core/decrypter.ts @@ -7,7 +7,7 @@ import { EmptyMaterialError } from './kering.ts'; import { Salter } from './salter.ts'; export class Decrypter extends Matter { - private readonly _decrypt: any; + private readonly _decrypt: typeof this._x25519; constructor( { raw, code = MtrDex.X25519_Private, qb64, qb64b, qb2 }: MatterArgs, seed: Uint8Array | undefined = undefined @@ -59,7 +59,7 @@ export class Decrypter extends Matter { cipher = new Cipher({ qb64b: ser }); } - return this._decrypt(cipher, this.raw, transferable); + return this._decrypt(cipher!, this.raw, transferable); } _x25519(cipher: Cipher, prikey: Uint8Array, transferable: boolean = false) { diff --git a/src/keri/core/encrypter.ts b/src/keri/core/encrypter.ts index 825b9fc0..dfa3a3ad 100644 --- a/src/keri/core/encrypter.ts +++ b/src/keri/core/encrypter.ts @@ -7,7 +7,7 @@ import { Cipher } from './cipher.ts'; import { arrayEquals } from './utils.ts'; export class Encrypter extends Matter { - private _encrypt: any; + private _encrypt: typeof this._x25519; constructor( { raw, code = MtrDex.X25519, qb64, qb64b, qb2 }: MatterArgs, verkey: Uint8Array | null = null @@ -60,7 +60,7 @@ export class Encrypter extends Matter { code = MtrDex.X25519_Cipher_Seed; } - return this._encrypt(matter!.qb64, this.raw, code); + return this._encrypt(matter!.qb64b, this.raw, code); } _x25519(ser: Uint8Array, pubkey: Uint8Array, code: string) { diff --git a/src/keri/core/eventing.ts b/src/keri/core/eventing.ts index 6d14101d..9b324921 100644 --- a/src/keri/core/eventing.ts +++ b/src/keri/core/eventing.ts @@ -1,24 +1,24 @@ +import { components } from '../../types/keria-api-schema.ts'; +import { Cigar } from './cigar.ts'; import { b, concat, - Dict, - Protocols, Ilks, + Protocols, Serials, versify, Version, Vrsn_1_0, } from './core.ts'; -import { Tholder } from './tholder.ts'; +import { Counter, CtrDex } from './counter.ts'; +import { MtrDex, NonTransDex } from './matter.ts'; import { CesrNumber } from './number.ts'; import { Prefixer } from './prefixer.ts'; +import { BaseSAD, Saider } from './saider.ts'; +import { Seqner } from './seqner.ts'; import { Serder } from './serder.ts'; -import { MtrDex, NonTransDex } from './matter.ts'; -import { Saider } from './saider.ts'; import { Siger } from './siger.ts'; -import { Cigar } from './cigar.ts'; -import { Counter, CtrDex } from './counter.ts'; -import { Seqner } from './seqner.ts'; +import { Tholder } from './tholder.ts'; const MaxIntThold = 2 ** 32 - 1; @@ -28,9 +28,9 @@ export interface RotateArgs { dig?: string; ilk?: string; sn?: number; - isith?: number | string | Array; + isith?: number | string | Array | string[][]; ndigs?: Array; - nsith?: number | string | Array; + nsith?: number | string | Array | string[][]; toad?: number; wits?: Array; cuts?: Array; @@ -43,6 +43,55 @@ export interface RotateArgs { intive?: boolean; } +export interface EndRoleAddAttributes extends Record { + cid: string; + role: string; + eid?: string; +} + +export interface RotateEventSAD extends BaseSAD, Record { + v: string; + t: string; + d: string; + i: string; + s: string; + p?: string; + kt: string | string[] | string[][]; + k: string[]; + nt: string | string[] | string[][]; + n: string[]; + bt: number | string; + br?: string[]; + ba?: string[]; + a: Record[]; +} + +export type DelegateInceptEventSAD = + | components['schemas']['DipV1'] + | components['schemas']['DipV2']; + +export type InceptEventSAD = + | components['schemas']['IcpV1'] + | components['schemas']['IcpV2'] + | DelegateInceptEventSAD; + +export type SealSourceTriple = components['schemas']['Seal']; + +export type InteractEventSAD = + | components['schemas']['IxnV1'] + | components['schemas']['IxnV2']; +export interface ReplyEventSAD extends BaseSAD { + t: string; + dt: string; + r: '/end/role/add'; + a: EndRoleAddAttributes; +} + +export type Seal = SealSourceTriple> = [ + 'SealEvent', + T, +]; + export function rotate({ pre = undefined, keys, @@ -198,11 +247,11 @@ export function rotate({ throw new Error(`Invalid toad = ${_toad} for wit = ${wits}`); } } - const _sad = { + const _sad: RotateEventSAD = { v: vs, t: _ilk, d: '', - i: pre, + i: pre || '', s: sner.numh, p: dig, kt: @@ -227,7 +276,7 @@ export function rotate({ : _toad.toString(16), br: cuts, ba: adds, - a: data != undefined ? data : [], + a: data != undefined ? (data as Record[]) : [], }; const [, sad] = Saider.saidify(_sad); return new Serder(sad); @@ -358,7 +407,7 @@ export function incept({ cnfg = cnfg == undefined ? new Array() : cnfg; data = data == undefined ? new Array() : data; - let sad = { + let sad: InceptEventSAD = { v: vs, t: ilk, d: '', @@ -366,16 +415,19 @@ export function incept({ s: sner.numh, kt: intive && tholder.num != undefined ? tholder.num : tholder.sith, k: keys, - nt: intive && tholder.num != undefined ? ntholder.num : ntholder.sith, + nt: + intive && tholder.num != undefined && ntholder.num + ? ntholder.num + : ntholder.sith, n: ndigs, bt: intive ? toader.num : toader.numh, b: wits, c: cnfg, - a: data, - } as Dict; + a: data as Record[], + }; if (delpre != undefined) { - sad['di'] = delpre; + (sad as DelegateInceptEventSAD)['di'] = delpre; if (code == undefined) { code = MtrDex.Blake3_256; } @@ -413,7 +465,7 @@ export function incept({ export function messagize( serder: Serder, sigers?: Array, - seal?: any, + seal?: Seal, wigers?: Array, cigars?: Array, pipelined: boolean = false @@ -525,13 +577,14 @@ interface InteractArgs { pre: string; dig: string; sn: number; - data: Array; + data: InteractEventSAD['a']; version: Version | undefined; kind: Serials | undefined; } -export function interact(args: InteractArgs): Serder { - let { pre, dig, sn, data, version, kind } = args; +export function interact(args: InteractArgs): Serder { + const { pre, dig, sn, version, kind } = args; + let { data } = args; const vs = versify(Protocols.KERI, version, kind, 0); const ilk = Ilks.ixn; const sner = new CesrNumber({}, sn); @@ -540,9 +593,9 @@ export function interact(args: InteractArgs): Serder { throw new Error(`Invalid sn = 0x${sner.numh} for ixn.`); } - data = data == undefined ? new Array() : data; + data = data == undefined ? new Array() : data; - let sad = { + let sad: InteractEventSAD = { v: vs, t: ilk, d: '', @@ -550,7 +603,7 @@ export function interact(args: InteractArgs): Serder { s: sner.numh, p: dig, a: data, - } as Dict; + }; [, sad] = Saider.saidify(sad); @@ -558,17 +611,17 @@ export function interact(args: InteractArgs): Serder { } export function reply( - route: string = '', - data: any | undefined, + route: '/end/role/add', + data: EndRoleAddAttributes | undefined, stamp: string | undefined, version: Version | undefined, kind: Serials = Serials.JSON ) { const vs = versify(Protocols.KERI, version, kind, 0); if (data == undefined) { - data = {}; + data = {} as EndRoleAddAttributes; } - const _sad = { + const _sad: ReplyEventSAD = { v: vs, t: Ilks.rpy, d: '', diff --git a/src/keri/core/httping.ts b/src/keri/core/httping.ts index b0a881c5..93344ca2 100644 --- a/src/keri/core/httping.ts +++ b/src/keri/core/httping.ts @@ -138,14 +138,14 @@ export class Unqualified { } export class Inputage { - public name: any; - public fields: any; - public created: any; - public expires: any; - public nonce: any; - public alg: any; - public keyid: any; - public context: any; + public name: string = ""; + public fields: Item[0][] = []; + public created?: Item[0]; + public expires?: Item[0]; + public nonce?: Item[0]; + public alg?: Item[0]; + public keyid?: Item[0]; + public context?: Item[0]; } export function desiginput(value: string): Array { @@ -155,9 +155,7 @@ export function desiginput(value: string): Array { sid.forEach((value, key) => { const siginput = new Inputage(); siginput.name = key; - let list: Item[]; - let params; - [list, params] = value as [Item[], Parameters]; + const [list, params] = value as [Item[], Parameters]; siginput.fields = list.map((item) => item[0]); if (!params.has('created')) { diff --git a/src/keri/core/keeping.ts b/src/keri/core/keeping.ts index f1f669b4..c902ed2a 100644 --- a/src/keri/core/keeping.ts +++ b/src/keri/core/keeping.ts @@ -1,22 +1,21 @@ -import { Salter } from './salter.ts'; -import { Algos, SaltyCreator, RandyCreator } from './manager.ts'; -import { MtrDex } from './matter.ts'; -import { Tier } from './salter.ts'; import { Encrypter } from '../core/encrypter.ts'; -import { Decrypter } from './decrypter.ts'; -import { b } from './core.ts'; import { Cipher } from './cipher.ts'; +import { b } from './core.ts'; +import { Decrypter } from './decrypter.ts'; import { Diger } from './diger.ts'; -import { Prefixer } from './prefixer.ts'; -import { Signer } from './signer.ts'; import { ExternState, GroupKeyState, HabState, + KeyState, RandyKeyState, SaltyKeyState, - KeyState, } from './keyState.ts'; +import { Algos, RandyCreator, SaltyCreator } from './manager.ts'; +import { MtrDex } from './matter.ts'; +import { Prefixer } from './prefixer.ts'; +import { Salter, Tier } from './salter.ts'; +import { Signer } from './signer.ts'; /** External module definition */ export interface ExternalModuleType { @@ -83,6 +82,33 @@ export interface IdentifierManager< ): Promise; } +export interface KArgs + extends IdentifierManagerParams, + Record { + pidx?: number; + kidx?: number; + tier?: Tier; + stem?: string | undefined; + transferable?: boolean; + code?: string; + count?: number; + icodes?: string[]; + ncode?: string; + ncount?: number; + ncodes?: string[]; + dcode?: string; + bran?: string | undefined; + sxlt?: string; + prxs?: string[] | undefined; + nxts?: string[] | undefined; + mhab?: HabState; + states?: KeyState[] | undefined; + rstates?: KeyState[] | undefined; + keys?: string[]; + ndigs?: string[]; + extern_type?: string; +} + /** * Creates IdentifierManager instances based on the algorithm and key indexes. */ @@ -112,7 +138,7 @@ export class IdentifierManagerFactory { * @param pidx * @param kargs */ - new(algo: Algos, pidx: number, kargs: any) { + new(algo: Algos, pidx: number, kargs: KArgs) { switch (algo) { case Algos.salty: return new SaltyIdentifierManager( @@ -141,7 +167,7 @@ export class IdentifierManagerFactory { kargs['transferable'], kargs['ncode'], kargs['ncount'], - kargs['ncodes'], + kargs['ncodes']!, kargs['dcode'], kargs['prxs'], kargs['nxts'] @@ -149,21 +175,24 @@ export class IdentifierManagerFactory { case Algos.group: return new GroupIdentifierManager( this, - kargs['mhab'], + kargs['mhab']!, kargs['states'], kargs['rstates'], kargs['keys'], kargs['ndigs'] ); case Algos.extern: { - const ModuleConstructor = this.modules[kargs.extern_type]; + const ModuleConstructor = this.modules[kargs.extern_type!]; if (!ModuleConstructor) { throw new Error( `unsupported external module type ${kargs.extern_type}` ); } - return new ModuleConstructor(pidx, kargs); + return new ModuleConstructor( + pidx, + kargs as IdentifierManagerParams + ); } default: throw new Error('Unknown algo'); @@ -177,19 +206,25 @@ export class IdentifierManagerFactory { * @returns IdentifierManager instance */ get(aid: HabState): IdentifierManager { - const algo = aid[Algos.salty] - ? Algos.salty - : aid[Algos.randy] - ? Algos.randy - : aid[Algos.group] - ? Algos.group - : aid[Algos.extern] - ? Algos.extern - : undefined; - if (!algo) { + let algo: Algos | undefined; + let kargs: any; + + if (Algos.salty in aid) { + algo = Algos.salty; + kargs = aid.salty; + } else if (Algos.randy in aid) { + algo = Algos.randy; + kargs = aid.randy; + } else if (Algos.group in aid) { + algo = Algos.group; + kargs = aid.group; + } else if (Algos.extern in aid) { + algo = Algos.extern; + kargs = aid.extern; + } else { throw new Error('No algo specified'); } - let kargs = aid[algo]; + if (!kargs) { throw new Error('No kargs found in HabState'); } @@ -557,12 +592,13 @@ export class RandyIdentifierManager implements IdentifierManager { this.creator = new RandyCreator(); - this.signers = this.prxs.map((prx) => - this.decrypter.decrypt( - new Cipher({ qb64: prx }).qb64b, - undefined, - this.transferable - ) + this.signers = this.prxs.map( + (prx) => + this.decrypter.decrypt( + new Cipher({ qb64: prx }).qb64b, + undefined, + this.transferable + ) as Signer ); } @@ -616,12 +652,13 @@ export class RandyIdentifierManager implements IdentifierManager { this.transferable = transferable; this.prxs = this.nxts; - const signers = this.nxts!.map((nxt) => - this.decrypter.decrypt( - undefined, - new Cipher({ qb64: nxt }), - this.transferable - ) + const signers = this.nxts!.map( + (nxt) => + this.decrypter.decrypt( + undefined, + new Cipher({ qb64: nxt }), + this.transferable + ) as Signer ); const verfers = signers.map((signer) => signer.verfer.qb64); const nsigners = this.creator.create( @@ -649,12 +686,13 @@ export class RandyIdentifierManager implements IdentifierManager { indices: number[] | undefined = undefined, ondices: number[] | undefined = undefined ): Promise { - const signers = this.prxs!.map((prx) => - this.decrypter.decrypt( - new Cipher({ qb64: prx }).qb64b, - undefined, - this.transferable - ) + const signers = this.prxs!.map( + (prx) => + this.decrypter.decrypt( + new Cipher({ qb64: prx }).qb64b, + undefined, + this.transferable + ) as Signer ); if (indexed) { diff --git a/src/keri/core/keyState.ts b/src/keri/core/keyState.ts index f94e5a94..aa232c47 100644 --- a/src/keri/core/keyState.ts +++ b/src/keri/core/keyState.ts @@ -1,30 +1,9 @@ -import { Algos } from './manager.ts'; -import { Tier } from './salter.ts'; +import { components } from '../../types/keria-api-schema.ts'; -export interface KeyState { - vn: [number, number]; - i: string; - s: string; - p?: string; - d: string; - f: string; - dt: string; - et: string; - kt: string | string[]; - k: string[]; - nt: string | string[]; - n: string[]; - bt: string; - b: string[]; - c: string[]; - ee: EstablishmentState; - di?: string; -} -export interface EstablishmentState { - d: string; - s: string; -} +export type KeyState = components['schemas']['KeyStateRecord']; + +export type EstablishmentState = components['schemas']['StateEERecord']; /** * Marker interface for state configuring an IdentifierManager. @@ -33,61 +12,38 @@ export interface EstablishmentState { export interface IdentifierManagerState {} /** - * Interface defining configuration parameters for a specified, deterministic salt of an IdentifierManager. + * Defining configuration parameters for a specified, deterministic salt of an IdentifierManager. */ -export interface SaltyKeyState extends IdentifierManagerState { - /** - * Encrypted - */ - sxlt: string; - pidx: number; - kidx: number; - stem: string; - tier: Tier; - dcode: string; - icodes: string[]; - ncodes: string[]; - transferable: boolean; -} +export type SaltyKeyState = components['schemas']['SaltyState']; /** - * Interface defining configuration parameters for a random seed identifier manager. + * Defining configuration parameters for a random seed identifier manager. */ -export interface RandyKeyState extends IdentifierManagerState { - prxs: string[]; - nxts: string[]; -} +export type RandyKeyState = components['schemas']['RandyKeyState']; /** - * Interface defining properties a multi-signature group identifier manager. + * Defining properties a multi-signature group identifier manager. */ -export interface GroupKeyState extends IdentifierManagerState { - mhab: HabState; - keys: string[]; - ndigs: string[]; -} +export type GroupKeyState = components['schemas']['GroupKeyState']; /** - * Interface defining properties for an external module identifier manager that uses externally managed keys such as in an HSM or a KMS system. + * Defining properties for an external module identifier manager that uses externally managed keys such as in an HSM or a KMS system. */ -export interface ExternState extends IdentifierManagerState { - extern_type: string; - pidx: number; - [key: string]: unknown; -} +export type ExternState = components['schemas']['ExternState']; /** - * Interface defining properties of an identifier habitat, know as a Hab in KERIpy. + * Defining properties of an identifier habitat, know as a Hab in KERIpy. */ -export interface HabState { - name: string; - prefix: string; - transferable: boolean; - state: KeyState; - windexes: unknown[]; - icp_dt: string; - [Algos.salty]?: SaltyKeyState; - [Algos.randy]?: RandyKeyState; - [Algos.group]?: GroupKeyState; - [Algos.extern]?: ExternState; -} +// export type HabState = components['schemas']['Identifier']; + +export type HabStateBase = components['schemas']['HabState']; +export type SaltyHabState = HabStateBase & SaltyKeyState; +export type RandyHabState = HabStateBase & RandyKeyState; +export type GroupHabState = HabStateBase & GroupKeyState; +export type ExternHabState = HabStateBase & ExternState; +export type HabState = + | SaltyHabState + | RandyHabState + | GroupHabState + | ExternHabState; + diff --git a/src/keri/core/manager.ts b/src/keri/core/manager.ts index 59ccd440..0503093b 100644 --- a/src/keri/core/manager.ts +++ b/src/keri/core/manager.ts @@ -1,13 +1,13 @@ -import { Encrypter } from './encrypter.ts'; +import { Cigar } from './cigar.ts'; +import { b } from './core.ts'; import { Decrypter } from './decrypter.ts'; +import { Diger } from './diger.ts'; +import { Encrypter } from './encrypter.ts'; +import { MtrDex } from './matter.ts'; import { Salter, Tier } from './salter.ts'; +import { Siger } from './siger.ts'; import { Signer } from './signer.ts'; import { Verfer } from './verfer.ts'; -import { MtrDex } from './matter.ts'; -import { Diger } from './diger.ts'; -import { Cigar } from './cigar.ts'; -import { Siger } from './siger.ts'; -import { b } from './core.ts'; /** * Kinds of key pair generation algorithms. @@ -310,7 +310,11 @@ export class SaltyCreator implements Creator { } export class Creatory { - private readonly _make: any; + private readonly _make: ( + salt?: string, + tier?: Tier, + stem?: string + ) => Creator; constructor(algo: Algos = Algos.salty) { switch (algo) { case Algos.randy: @@ -324,16 +328,16 @@ export class Creatory { } } - make(...args: any[]): Creator { - return this._make(...args); + make(salt?: string, tier?: string, stem?: string): Creator { + return this._make(salt, tier as Tier, stem); } _makeRandy(): Creator { return new RandyCreator(); } - _makeSalty(...args: any[]): Creator { - return new SaltyCreator(...args); + _makeSalty(salt?: string, tier?: Tier, stem?: string): Creator { + return new SaltyCreator(salt, tier, stem); } } @@ -373,10 +377,10 @@ export interface ManagerArgs { } export interface ManagerInceptArgs { - icodes?: any | undefined; + icodes?: string[] | undefined; icount?: number; icode?: string; - ncodes?: any | undefined; + ncodes?: string[] | undefined; ncount?: number; ncode?: string; dcode?: string; @@ -391,7 +395,7 @@ export interface ManagerInceptArgs { interface RotateArgs { pre: string; - ncodes?: any | undefined; + ncodes?: string[] | undefined; ncount?: number; ncode?: string; dcode?: string; @@ -564,7 +568,7 @@ export class Manager { data.salt = this._encrypter == undefined ? salter.qb64 - : this._encrypter.encrypt(null, salter); + : this._encrypter.encrypt(null, salter).qb64; this.ks.pinPrms(keys, data); } } @@ -1218,7 +1222,7 @@ class Keeper implements KeyStore { const out = new Array<[string, Signer]>(); this._pris.forEach(function (val, pubKey) { const verfer = new Verfer({ qb64: pubKey }); - const signer = decrypter.decrypt(val, null, verfer.transferable); + const signer = decrypter.decrypt(val, null, verfer.transferable) as Signer; out.push([pubKey, signer]); }); return out; @@ -1245,7 +1249,7 @@ class Keeper implements KeyStore { } const verfer = new Verfer({ qb64: pubKey }); - return decrypter.decrypt(val, null, verfer.transferable); + return decrypter.decrypt(val, null, verfer.transferable) as Signer; } pinPths(pubKey: string, val: PubPath): boolean { diff --git a/src/keri/core/pather.ts b/src/keri/core/pather.ts index 7bd2d4e3..91d0693b 100644 --- a/src/keri/core/pather.ts +++ b/src/keri/core/pather.ts @@ -76,7 +76,7 @@ export class Pather extends Bexter { } } - static _bextify(path: any[]): string { + static _bextify(path: (number | string)[]): string { const vath = []; for (const p of path) { let sp = ''; diff --git a/src/keri/core/prefixer.ts b/src/keri/core/prefixer.ts index 27abd039..a2a9d219 100644 --- a/src/keri/core/prefixer.ts +++ b/src/keri/core/prefixer.ts @@ -1,19 +1,31 @@ -import { Matter, MatterArgs, MtrDex } from './matter.ts'; +import { blake3 } from '@noble/hashes/blake3'; +import { Ilks } from './core.ts'; import { EmptyMaterialError } from './kering.ts'; -import { Dict, Ilks } from './core.ts'; +import { Matter, MatterArgs, MtrDex } from './matter.ts'; +import { BaseSAD } from './saider.ts'; import { sizeify } from './serder.ts'; import { Verfer } from './verfer.ts'; -import { blake3 } from '@noble/hashes/blake3'; const Dummy: string = '#'; -export class Prefixer extends Matter { +export interface PrefixerSAD extends Omit { + d?: string; + t?: string; + v: string; + k?: string[]; + n?: string | string[]; + b?: string[]; + a?: unknown; + i?: string; +} + +export class Prefixer extends Matter { // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type private readonly _derive: Function | undefined; // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type private readonly _verify: Function | undefined; - constructor({ raw, code, qb64b, qb64, qb2 }: MatterArgs, ked?: Dict) { + constructor({ raw, code, qb64b, qb64, qb2 }: MatterArgs, ked?: T) { try { super({ raw, code, qb64b, qb64, qb2 }); } catch (e) { @@ -57,7 +69,7 @@ export class Prefixer extends Matter { } } - derive(sad: Dict): [Uint8Array, string] { + derive(sad: BaseSAD): [Uint8Array, string] { if (sad['i'] != Ilks.icp) { throw new Error( `Non-incepting ilk ${sad['i']} for prefix derivation` @@ -66,7 +78,7 @@ export class Prefixer extends Matter { return this._derive!(sad); } - verify(sad: Dict, prefixed: boolean = false): boolean { + verify(sad: BaseSAD, prefixed: boolean = false): boolean { if (sad['i'] != Ilks.icp) { throw new Error( `Non-incepting ilk ${sad['i']} for prefix derivation` @@ -75,12 +87,12 @@ export class Prefixer extends Matter { return this._verify!(sad, this.qb64, prefixed); } - static _derive_ed25519N(sad: Dict): [Uint8Array, string] { + static _derive_ed25519N(sad: PrefixerSAD): [Uint8Array, string] { let verfer; const keys = sad['k']; - if (keys.length != 1) { + if (keys?.length != 1) { throw new Error( - `Basic derivation needs at most 1 key got ${keys.length} keys instead` + `Basic derivation needs at most 1 key got ${keys?.length} keys instead` ); } try { @@ -93,21 +105,22 @@ export class Prefixer extends Matter { throw new Error(`Mismatch derivation code = ${verfer.code}`); } - const next = 'n' in sad ? sad['n'] : []; + const next = 'n' in sad && sad['n'] ? sad['n'] : []; if (verfer.code == MtrDex.Ed25519N && next.length > 0) { throw new Error( `Non-empty nxt = ${next} for non-transferable code = ${verfer.code}` ); } - const backers = 'b' in sad ? sad['b'] : []; + const backers = 'b' in sad && sad['b'] ? sad['b'] : []; if (verfer.code == MtrDex.Ed25519N && backers.length > 0) { throw new Error( `Non-empty b =${backers} for non-transferable code = ${verfer.code}` ); } - const anchor = 'a' in sad ? sad['a'] : []; + const anchor = + 'a' in sad && sad['a'] && Array.isArray(sad['a']) ? sad['a'] : []; if (verfer.code == MtrDex.Ed25519N && anchor.length > 0) { throw new Error( `Non-empty a = ${verfer.code} for non-transferable code = ${verfer.code}` @@ -117,12 +130,12 @@ export class Prefixer extends Matter { return [verfer.raw, verfer.code]; } - static _derive_ed25519(sad: Dict): [Uint8Array, string] { + static _derive_ed25519(sad: PrefixerSAD): [Uint8Array, string] { let verfer; const keys = sad['k']; - if (keys.length != 1) { + if (keys?.length != 1) { throw new Error( - `Basic derivation needs at most 1 key got ${keys.length} keys instead` + `Basic derivation needs at most 1 key got ${keys?.length} keys instead` ); } @@ -139,27 +152,23 @@ export class Prefixer extends Matter { return [verfer.raw, verfer.code]; } - static _derive_blake3_256(sad: Dict): [Uint8Array, string] { + static _derive_blake3_256(sad: PrefixerSAD): [Uint8Array, string] { const ilk = sad['t']; - if (![Ilks.icp, Ilks.dip, Ilks.vcp, Ilks.dip].includes(ilk)) { + if (!ilk || ![Ilks.icp, Ilks.dip, Ilks.vcp, Ilks.dip].includes(ilk)) { throw new Error(`Invalid ilk = ${ilk} to derive pre.`); } sad['i'] = ''.padStart(Matter.Sizes.get(MtrDex.Blake3_256)!.fs!, Dummy); sad['d'] = sad['i']; - const [raw] = sizeify(sad); + const [raw] = sizeify(sad as BaseSAD); const dig = blake3.create({ dkLen: 32 }).update(raw).digest(); return [dig, MtrDex.Blake3_256]; } - _verify_ed25519N( - sad: Dict, - pre: string, - prefixed: boolean = false - ): boolean { + _verify_ed25519N(sad: T, pre: string, prefixed: boolean = false): boolean { try { const keys = sad['k']; - if (keys.length != 1) { + if (keys?.length != 1) { return false; } @@ -171,7 +180,7 @@ export class Prefixer extends Matter { return false; } - const next = 'n' in sad ? sad['n'] : []; + const next = 'n' in sad && sad['n'] ? sad['n'] : []; if (next.length > 0) { // must be empty return false; @@ -183,14 +192,10 @@ export class Prefixer extends Matter { return true; } - _verify_ed25519( - sad: Dict, - pre: string, - prefixed: boolean = false - ): boolean { + _verify_ed25519(sad: T, pre: string, prefixed: boolean = false): boolean { try { const keys = sad['k']; - if (keys.length != 1) { + if (keys?.length != 1) { return false; } @@ -209,7 +214,7 @@ export class Prefixer extends Matter { } _verify_blake3_256( - sad: Dict, + sad: T, pre: string, prefixed: boolean = false ): boolean { diff --git a/src/keri/core/saider.ts b/src/keri/core/saider.ts index 479d6b5b..71bc0987 100644 --- a/src/keri/core/saider.ts +++ b/src/keri/core/saider.ts @@ -1,8 +1,8 @@ -import { DigiDex, Matter, MatterArgs, MtrDex } from './matter.ts'; -import { deversify, Dict, Serials } from './core.ts'; +import { blake3 } from '@noble/hashes/blake3'; +import { deversify, Serials } from './core.ts'; import { EmptyMaterialError } from './kering.ts'; +import { DigiDex, Matter, MatterArgs, MtrDex } from './matter.ts'; import { dumps, sizeify } from './serder.ts'; -import { blake3 } from '@noble/hashes/blake3'; const Dummy = '#'; @@ -10,10 +10,16 @@ export enum Ids { d = 'd', } -export class Saider extends Matter { +export interface BaseSAD extends Record { + d: string; + v?: string; + t?: string; +} + +export class Saider extends Matter { constructor( { raw, code, qb64b, qb64, qb2 }: MatterArgs, - sad?: Dict, + sad?: T, kind?: Serials, label: string = Ids.d ) { @@ -27,7 +33,7 @@ export class Saider extends Matter { if (code == undefined) { if (sad[label] != '') { - super({ qb64: sad[label], code: code }); + super({ qb64: String(sad[label]), code: code }); code = this.code; } else { code = MtrDex.Blake3_256; @@ -51,11 +57,11 @@ export class Saider extends Matter { } private static _derive( - sad: Dict, + sad: BaseSAD, code: string, kind: Serials | undefined, label: string - ): [Uint8Array, Dict] { + ): [Uint8Array, BaseSAD] { if (!DigiDex.has(code)) { throw new Error(`Unsupported digest code = ${code}.`); } @@ -79,17 +85,17 @@ export class Saider extends Matter { } public derive( - sad: Dict, + sad: BaseSAD, code: string, kind: Serials | undefined, label: string - ): [Uint8Array, Dict] { + ): [Uint8Array, BaseSAD] { code = code != undefined ? code : this.code; return Saider._derive(sad, code, kind, label); } public verify( - sad: Dict, + sad: BaseSAD, prefixed: boolean = false, versioned: boolean = false, kind?: Serials, @@ -118,10 +124,10 @@ export class Saider extends Matter { return true; } - private static _serialze(sad: Dict, kind?: Serials): string { + private static _serialze(sad: BaseSAD, kind?: Serials): string { let knd = Serials.JSON; if ('v' in sad) { - [, knd] = deversify(sad['v']); + [, knd] = deversify(sad['v']!); } if (kind == undefined) { @@ -131,24 +137,24 @@ export class Saider extends Matter { return dumps(sad, kind); } - public static saidify( - sad: Dict, + public static saidify( + sad: T, code: string = MtrDex.Blake3_256, kind: Serials = Serials.JSON, label: string = Ids.d - ): [Saider, Dict] { + ): [Saider, T] { if (!(label in sad)) { throw new Error(`Missing id field labeled=${label} in sad.`); } - let raw; - [raw, sad] = Saider._derive(sad, code, kind, label); + + const [raw, derivedSad] = Saider._derive(sad, code, kind, label); const saider = new Saider( { raw: raw, code: code }, undefined, kind, label ); - sad[label] = saider.qb64; - return [saider, sad]; + derivedSad[label] = saider.qb64; + return [saider, derivedSad as T]; } } diff --git a/src/keri/core/salter.ts b/src/keri/core/salter.ts index 46134d2d..bfb563a1 100644 --- a/src/keri/core/salter.ts +++ b/src/keri/core/salter.ts @@ -3,15 +3,10 @@ import { Signer } from './signer.ts'; import { Matter, MtrDex } from './matter.ts'; import { EmptyMaterialError } from './kering.ts'; import libsodium from 'libsodium-wrappers-sumo'; +import { Tier } from '../../types/keria-api-schema.ts'; -/** - * Secret derivation security tier. - */ -export enum Tier { - low = 'low', - med = 'med', - high = 'high', -} + +export { Tier } from '../../types/keria-api-schema.ts'; interface SalterArgs { raw?: Uint8Array | undefined; diff --git a/src/keri/core/serder.ts b/src/keri/core/serder.ts index d5995aa5..40c704c4 100644 --- a/src/keri/core/serder.ts +++ b/src/keri/core/serder.ts @@ -1,21 +1,28 @@ -import { MtrDex } from './matter.ts'; import { deversify, - Dict, Protocols, Serials, versify, Version, Vrsn_1_0, } from './core.ts'; -import { Verfer } from './verfer.ts'; import { Diger } from './diger.ts'; +import { MtrDex } from './matter.ts'; import { CesrNumber } from './number.ts'; +import { BaseSAD } from './saider.ts'; +import { Verfer } from './verfer.ts'; + +export interface SerderSAD extends BaseSAD { + i?: string; + k?: string[]; + n?: string[] | string; + s?: string | number; +} -export class Serder { +export class Serder { private _kind: Serials; private _raw: string = ''; - private _sad: Dict = {}; + private _sad: T; private _proto: Protocols = Protocols.KERI; private _size: number = 0; private _version: Version = Vrsn_1_0; @@ -28,7 +35,7 @@ export class Serder { * @param code derivation code for the prefix */ constructor( - sad: Dict, + sad: T, kind: Serials = Serials.JSON, code: string = MtrDex.Blake3_256 ) { @@ -42,11 +49,11 @@ export class Serder { this._size = raw.length; } - get sad(): Dict { + get sad(): T { return this._sad; } - get pre(): string { + get pre(): T['i'] { return this._sad['i']; } @@ -58,7 +65,7 @@ export class Serder { return this._raw; } - get said(): string { + get said(): T["d"] { return this._sad['d']; } @@ -82,9 +89,9 @@ export class Serder { * @private */ private _exhale( - sad: Dict, + sad: T, kind: Serials - ): [string, Protocols, Serials, Dict, Version] { + ): [string, Protocols, Serials, T, Version] { return sizeify(sad, kind); } @@ -100,10 +107,10 @@ export class Serder { return this._version; } get verfers(): Verfer[] { - let keys: any = []; + let keys: string[] = []; if ('k' in this._sad) { // establishment event - keys = this._sad['k']; + keys = this._sad['k'] || []; } else { // non-establishment event keys = []; @@ -117,10 +124,10 @@ export class Serder { } get digers(): Diger[] { - let keys: any = []; + let keys: string[] | string = []; if ('n' in this._sad) { // establishment event - keys = this._sad['n']; + keys = this._sad['n'] || []; } else { // non-establishment event keys = []; @@ -146,10 +153,10 @@ export function dumps(sad: object, kind: Serials.JSON): string { } } -export function sizeify( - ked: Dict, +export function sizeify( + ked: T, kind?: Serials -): [string, Protocols, Serials, Dict, Version] { +): [string, Protocols, Serials, T, Version] { if (!('v' in ked)) { throw new Error('Missing or empty version string'); } diff --git a/src/keri/core/tholder.ts b/src/keri/core/tholder.ts index 745ea915..3a4ff330 100644 --- a/src/keri/core/tholder.ts +++ b/src/keri/core/tholder.ts @@ -1,17 +1,23 @@ +import { Fraction, format, fraction, sum } from 'mathjs'; import { BexDex, Matter, NumDex } from './matter.ts'; import { CesrNumber } from './number.ts'; -import { Fraction, format, sum, fraction } from 'mathjs'; + +interface Thold { + thold?: number | Array>; + limen?: string; + sith?: number | string | string[] | (string | string[])[]; +} export class Tholder { private _weighted: boolean = false; - private _thold: any = undefined; + private _thold: number | Array> = 0; private _size: number = 0; private _number: CesrNumber | undefined = undefined; - private _satisfy: any = undefined; + private _satisfy: ((indices: number[]) => boolean) | undefined = undefined; // private _bexter: any - constructor(kargs: { thold?: any; limen?: any; sith?: any }) { + constructor(kargs: Thold) { if (kargs.thold !== undefined) { this._processThold(kargs.thold); } else if (kargs.limen != undefined) { @@ -27,7 +33,7 @@ export class Tholder { return this._weighted; } - get thold(): any { + get thold(): number | Array> { return this._thold; } @@ -35,13 +41,13 @@ export class Tholder { return this._size; } - get limen(): any { + get limen() { return this._number?.qb64b; } - get sith(): string { - if (this.weighted) { - let sith = this.thold.map((clause: Fraction[]) => { + get sith(): string | string[] | string[][] { + if (this.weighted && Array.isArray(this.thold)) { + const sith = this.thold.map((clause: Fraction[]) => { return clause.map((c) => { if (0 < Number(c) && Number(c) < 1) { return format(c, { fraction: 'ratio' }); @@ -50,11 +56,8 @@ export class Tholder { } }); }); - if (sith.length == 1) { - sith = sith[0]; - } - return sith; + return sith.length == 1 ? sith[0] : sith; } else { return this.thold.toString(16); } @@ -65,7 +68,7 @@ export class Tholder { } get num(): number | undefined { - return this._weighted ? undefined : this._thold; + return this._weighted ? undefined : (this._thold as number); } private _processThold(thold: number | Array>) { @@ -91,31 +94,34 @@ export class Tholder { } } - private _processSith(sith: string | number | Array) { + private _processSith( + sith: string | number | Array | (string | string[])[] + ) { if (typeof sith == 'number') { this._processUnweighted(sith); } else if (typeof sith == 'string' && sith.indexOf('[') == -1) { this._processUnweighted(parseInt(sith, 16)); } else { - let _sith: any = sith; + let _sith: string | string[] | string[][] | (string | string[])[] = + sith; if (typeof sith == 'string') { _sith = JSON.parse(sith); } - if (_sith.length == 0) { + if (!Array.isArray(_sith) || _sith.length == 0) { throw new Error('Empty weight list'); } - const mask = _sith.map((x: any) => { + const mask = _sith.map((x) => { return typeof x !== 'string'; }); if (mask.length > 0 && !mask.every((x: boolean) => x)) { - _sith = [_sith]; + _sith = [_sith] as string[][]; } - for (const c of _sith) { - const mask = c.map((x: any) => { + for (const c of _sith as string[][]) { + const mask = c.map((x) => { return typeof x === 'string'; }); if (mask.length > 0 && !mask.every((x: boolean) => x)) { @@ -127,7 +133,7 @@ export class Tholder { } } - const thold = this._processClauses(_sith); + const thold = this._processClauses(_sith as string[][]); this._processWeighted(thold); } } @@ -180,11 +186,14 @@ export class Tholder { return fraction(w); } - private _satisfy_numeric(indices: any[]) { - return this.thold > 0 && indices.length >= this.thold; // at least one + private _satisfy_numeric(indices: number[]) { + return ( + (this.thold as number) > 0 && + indices.length >= (this.thold as number) + ); // at least one } - private _satisfy_weighted(indices: any) { + private _satisfy_weighted(indices: number[]) { if (indices.length === 0) { return false; } @@ -195,7 +204,7 @@ export class Tholder { sats[idx] = true; } let wio = 0; - for (const clause of this.thold) { + for (const clause of this.thold as Array>) { let cw = 0; for (const w of clause) { if (sats[wio]) { @@ -211,7 +220,7 @@ export class Tholder { return true; } - public satisfy(indices: any): boolean { - return this._satisfy(indices); + public satisfy(indices: number[]): boolean { + return !!this._satisfy?.(indices); } } diff --git a/src/keri/core/utils.ts b/src/keri/core/utils.ts index 6e1cf980..4f10669f 100644 --- a/src/keri/core/utils.ts +++ b/src/keri/core/utils.ts @@ -3,9 +3,8 @@ import { Seqner } from './seqner.ts'; import { Prefixer } from './prefixer.ts'; import { Saider } from './saider.ts'; import { Serder } from './serder.ts'; -import { b } from './core.ts'; -export function pad(n: any, width = 3, z = 0) { +export function pad(n: string, width = 3, z = 0) { return (String(z).repeat(width) + String(n)).slice(String(n).length); } @@ -16,8 +15,8 @@ export function pad(n: any, width = 3, z = 0) { * @param {*} ked ked is key event dict * @param {*} labels labels is list of element labels in ked from which to extract values */ -export function extractValues(ked: any, labels: any) { - let values = []; +export function extractValues(ked: Record, labels: string[]) { + let values: unknown[] = []; for (const label of labels) { values = extractElementValues(ked[label], values); } @@ -41,7 +40,7 @@ export function arrayEquals(ar1: Uint8Array, ar2: Uint8Array) { * @param {*} values */ -function extractElementValues(element: any, values: any) { +function extractElementValues(element: unknown, values: unknown[]) { let data = []; try { diff --git a/src/keri/core/vdring.ts b/src/keri/core/vdring.ts index 8ce5836a..9ba74abd 100644 --- a/src/keri/core/vdring.ts +++ b/src/keri/core/vdring.ts @@ -11,6 +11,7 @@ import { import { ample } from './eventing.ts'; import { MtrDex } from './matter.ts'; import { Prefixer } from './prefixer.ts'; +import { BaseSAD } from './saider.ts'; import { Serder } from './serder.ts'; namespace vdr { @@ -25,6 +26,19 @@ namespace vdr { code?: string; } + export interface VDRInceptSAD extends BaseSAD { + v: string; + t: string; + d: string; + i: string; + ii: string; + s: string; + c: string[]; + bt: string; + b: string[]; + n: string; + } + export function incept({ pre, toad, @@ -70,7 +84,7 @@ namespace vdr { } } - const sad = { + const sad: VDRInceptSAD = { v: vs, t: ilk, d: '', diff --git a/src/types/keria-api-schema.ts b/src/types/keria-api-schema.ts new file mode 100644 index 00000000..ef63c4f4 --- /dev/null +++ b/src/types/keria-api-schema.ts @@ -0,0 +1,945 @@ +// AUTO-GENERATED: Only components and enums retained from OpenAPI schema + +export enum IssEvtT { + iss = "iss", + bis = "bis" +} + +export enum CredentialStateIssOrRevEt { + iss = "iss", + rev = "rev" +} + +export enum CredentialStateBisOrBrvEt { + bis = "bis", + brv = "brv" +} + +export enum Tier { + low = "low", + med = "med", + high = "high" +} + +export enum OOBIRole { + controller = "controller", + witness = "witness", + registrar = "registrar", + watcher = "watcher", + judge = "judge", + juror = "juror", + peer = "peer", + mailbox = "mailbox", + agent = "agent" +} + +export interface components { + schemas: { + ACDCAttributes: { + dt?: string; + i?: string; + u?: string; + } & { + [key: string]: unknown; + }; + ACDC: { + v: string; + d: string; + i: string; + s: string; + ri?: string; + a?: components["schemas"]["ACDCAttributes"]; + u?: string; + e?: unknown[]; + r?: unknown[]; + }; + IssEvt: { + v: string; + /** @enum {unknown} */ + t: IssEvtT; + d: string; + i: string; + s: string; + ri: string; + dt: string; + }; + Schema: { + $id: string; + $schema: string; + title: string; + description: string; + type: string; + credentialType: string; + version: string; + properties: { + [key: string]: unknown; + }; + additionalProperties: boolean; + required: string[]; + }; + StatusAnchor: { + s: number; + d: string; + }; + CredentialStatus: { + vn: number[]; + i: string; + s: string; + d: string; + ri: string; + ra: { + [key: string]: unknown; + }; + a: components["schemas"]["StatusAnchor"]; + dt: string; + et: string; + }; + Anchor: { + pre: string; + sn: number; + d: string; + }; + Seal: { + s: string; + d: string; + i?: string; + }; + ANC: { + v: string; + t: string; + d: string; + i: string; + s: string; + p: string; + di?: string; + a?: components["schemas"]["Seal"][]; + }; + Credential: { + sad: components["schemas"]["ACDC"]; + atc: string; + iss: components["schemas"]["IssEvt"]; + issatc: string; + pre: string; + schema: components["schemas"]["Schema"]; + chains: { + [key: string]: unknown; + }[]; + status: components["schemas"]["CredentialState"]; + anchor: components["schemas"]["Anchor"]; + anc: components["schemas"]["ANC"]; + ancatc: string; + }; + OperationStatus: { + code: number; + message: string; + details?: { + [key: string]: unknown; + } | null; + }; + OperationBase: { + name: string; + error?: components["schemas"]["OperationStatus"]; + done?: boolean; + }; + EmptyDict: Record; + CredentialStateIssOrRev: { + vn: unknown; + i: string; + s: string; + d: string; + ri: string; + a: components["schemas"]["Seal"]; + dt: string; + /** @enum {unknown} */ + et: CredentialStateIssOrRevEt; + ra: components["schemas"]["EmptyDict"]; + }; + RaFields: { + i: string; + s: string; + d: string; + }; + CredentialStateBisOrBrv: { + vn: unknown; + i: string; + s: string; + d: string; + ri: string; + a: components["schemas"]["Seal"]; + dt: string; + /** @enum {unknown} */ + et: CredentialStateBisOrBrvEt; + ra: components["schemas"]["RaFields"]; + }; + CredentialState: components["schemas"]["CredentialStateIssOrRev"] | components["schemas"]["CredentialStateBisOrBrv"]; + Operation: components["schemas"]["OperationBase"] & { + metadata?: Record; + response?: Record; + }; + Registry: { + name: string; + regk: string; + pre: string; + state: components["schemas"]["CredentialState"]; + }; + IcpV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default 0 */ + kt: string; + k?: string[]; + /** @default 0 */ + nt: string; + n?: string[]; + /** @default 0 */ + bt: string; + b?: string[]; + c?: string[]; + a?: unknown; + }; + RotV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + p: string; + /** @default 0 */ + kt: string; + k?: string[]; + /** @default 0 */ + nt: string; + n?: string[]; + /** @default 0 */ + bt: string; + br?: string[]; + ba?: string[]; + a?: unknown; + }; + DipV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default 0 */ + kt: string; + k?: string[]; + /** @default 0 */ + nt: string; + n?: string[]; + /** @default 0 */ + bt: string; + b?: string[]; + c?: string[]; + a?: unknown; + /** @default */ + di: string; + }; + DrtV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + p: string; + /** @default 0 */ + kt: string; + k?: string[]; + /** @default 0 */ + nt: string; + n?: string[]; + /** @default 0 */ + bt: string; + br?: string[]; + ba?: string[]; + a?: unknown; + }; + VcpV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + ii: string; + /** @default 0 */ + s: string; + c?: string[]; + /** @default 0 */ + bt: string; + b?: string[]; + /** @default */ + n: string; + }; + VrtV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + p: string; + /** @default 0 */ + s: string; + /** @default 0 */ + bt: string; + br?: string[]; + ba?: string[]; + }; + IxnV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + p: string; + a?: unknown; + }; + RctV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + }; + QryV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + dt: string; + /** @default */ + r: string; + /** @default */ + rr: string; + q?: { + [key: string]: unknown; + }; + }; + RpyV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + dt: string; + /** @default */ + r: string; + a?: unknown; + }; + ProV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + dt: string; + /** @default */ + r: string; + /** @default */ + rr: string; + q?: { + [key: string]: unknown; + }; + }; + BarV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + dt: string; + /** @default */ + r: string; + a?: unknown; + }; + ExnV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + rp: string; + /** @default */ + p: string; + /** @default */ + dt: string; + /** @default */ + r: string; + q?: { + [key: string]: unknown; + }; + a?: unknown; + e?: { + [key: string]: unknown; + }; + }; + IssV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + ri: string; + /** @default */ + dt: string; + }; + RevV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + ri: string; + /** @default */ + p: string; + /** @default */ + dt: string; + }; + BisV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + ii: string; + /** @default 0 */ + s: string; + ra?: { + [key: string]: unknown; + }; + /** @default */ + dt: string; + }; + BrvV1: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + p: string; + ra?: { + [key: string]: unknown; + }; + /** @default */ + dt: string; + }; + IcpV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default 0 */ + kt: number | string | string[] | string[][]; + k?: string[]; + /** @default 0 */ + nt: number | string | string[] | string[][]; + n?: string[]; + /** @default 0 */ + bt: number | string; + b?: string[]; + c?: string[]; + a?: unknown; + }; + RotV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + p: string; + /** @default 0 */ + kt: string; + k?: string[]; + /** @default 0 */ + nt: string; + n?: string[]; + /** @default 0 */ + bt: string; + br?: string[]; + ba?: string[]; + c?: string[]; + a?: unknown; + }; + DipV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default 0 */ + kt: string; + k?: string[]; + /** @default 0 */ + nt: string; + n?: string[]; + /** @default 0 */ + bt: string; + b?: string[]; + c?: string[]; + a?: unknown; + /** @default */ + di: string; + }; + DrtV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + p: string; + /** @default 0 */ + kt: string; + k?: string[]; + /** @default 0 */ + nt: string; + n?: string[]; + /** @default 0 */ + bt: string; + br?: string[]; + ba?: string[]; + c?: string[]; + a?: unknown; + }; + IxnV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + p: string; + a?: unknown; + }; + RctV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default 0 */ + s: string; + }; + QryV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + dt: string; + /** @default */ + r: string; + /** @default */ + rr: string; + q?: { + [key: string]: unknown; + }; + }; + RpyV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + dt: string; + /** @default */ + r: string; + a?: unknown; + }; + ProV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + dt: string; + /** @default */ + r: string; + /** @default */ + rr: string; + q?: { + [key: string]: unknown; + }; + }; + BarV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + dt: string; + /** @default */ + r: string; + a?: unknown; + }; + XipV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + dt: string; + /** @default */ + r: string; + q?: { + [key: string]: unknown; + }; + a?: unknown; + }; + ExnV2: { + /** @default */ + v: string; + /** @default */ + t: string; + /** @default */ + d: string; + /** @default */ + i: string; + /** @default */ + x: string; + /** @default */ + p: string; + /** @default */ + dt: string; + /** @default */ + r: string; + q?: { + [key: string]: unknown; + }; + a?: unknown; + }; + StateEERecord: { + /** @default 0 */ + s: string; + /** @default */ + d: string; + br?: unknown[]; + ba?: unknown[]; + }; + KeyStateRecord: { + vn?: number[]; + /** @default */ + i: string; + /** @default 0 */ + s: string; + /** @default */ + p: string; + /** @default */ + d: string; + /** @default 0 */ + f: string; + /** @default */ + dt: string; + /** @default */ + et: string; + /** @default 0 */ + kt: string; + k: string[]; + /** @default 0 */ + nt: string; + n: string[]; + /** @default 0 */ + bt: string; + b: string[]; + c: string[]; + ee: components["schemas"]["StateEERecord"]; + /** @default */ + di: string; + }; + Controller: { + state: components["schemas"]["KeyStateRecord"]; + ee: components["schemas"]["IcpV1"] | components["schemas"]["IcpV2"] | components["schemas"]["RotV1"] | components["schemas"]["RotV2"] | components["schemas"]["DipV1"] | components["schemas"]["DipV2"] | components["schemas"]["DrtV1"] | components["schemas"]["DrtV2"] | components["schemas"]["VcpV1"] | components["schemas"]["VrtV1"]; + }; + AgentResourceResult: { + agent: components["schemas"]["KeyStateRecord"]; + controller: components["schemas"]["Controller"]; + pidx: number; + /** @default null */ + ridx: number | null; + /** @default null */ + sxlt: string | null; + }; + SaltyState: { + tier: components["schemas"]["Tier"]; + /** @default */ + sxlt: string; + /** @default 0 */ + pidx: number; + /** @default 0 */ + kidx: number; + /** @default */ + stem: string; + /** @default */ + dcode: string; + icodes: string[]; + ncodes: string[]; + /** @default false */ + transferable: boolean; + }; + RandyKeyState: { + prxs: string[]; + nxts: string[]; + }; + HabState: { + name: string; + prefix: string; + icp_dt: string; + state: components["schemas"]["KeyStateRecord"]; + /** @default null */ + transferable: boolean | null; + /** @default null */ + windexes: string[] | null; + }; + GroupKeyState: { + mhab: components["schemas"]["Identifier"]; + keys: string[]; + ndigs: string[]; + }; + ExternState: { + extern_type: string; + pidx: number; + } & { + [key: string]: unknown; + }; + Identifier: { + name: string; + prefix: string; + icp_dt: string; + state: components["schemas"]["KeyStateRecord"]; + /** @default null */ + transferable: boolean | null; + /** @default null */ + windexes: string[] | null; + } & ({ + salty: components["schemas"]["SaltyState"]; + } | { + randy: components["schemas"]["RandyKeyState"]; + } | { + group: components["schemas"]["GroupKeyState"]; + } | { + extern: components["schemas"]["ExternState"]; + }); + /** + * @description Tier of key material + * @enum {string} + */ + Tier: Tier; + OOBI: { + /** @enum {string} */ + role: OOBIRole; + oobis: string[]; + }; + EndRole: { + cid: string; + role: string; + eid: string; + }; + Rpy: components["schemas"]["RpyV1"] | components["schemas"]["RpyV2"]; + Challenge: { + words: string[]; + dt?: string; + said?: string; + authenticated?: boolean; + }; + MemberEnds: { + agent: { + [key: string]: string; + }; + /** @default null */ + controller: { + [key: string]: string; + } | null; + /** @default null */ + witness: { + [key: string]: string; + } | null; + /** @default null */ + registrar: { + [key: string]: string; + } | null; + /** @default null */ + watcher: { + [key: string]: string; + } | null; + /** @default null */ + judge: { + [key: string]: string; + } | null; + /** @default null */ + juror: { + [key: string]: string; + } | null; + /** @default null */ + peer: { + [key: string]: string; + } | null; + /** @default null */ + mailbox: { + [key: string]: string; + } | null; + }; + WellKnown: { + url: string; + dt: string; + }; + Contact: { + id: string; + alias: string; + oobi: string; + end?: components["schemas"]["MemberEnds"]; + challenges?: components["schemas"]["Challenge"][]; + wellKnowns?: components["schemas"]["WellKnown"][]; + } & { + [key: string]: unknown; + }; + AidRecord: { + aid: string; + ends: components["schemas"]["MemberEnds"]; + }; + GroupMember: { + signing: components["schemas"]["AidRecord"][]; + rotation: components["schemas"]["AidRecord"][]; + }; + KeyEventRecord: { + ked: components["schemas"]["IcpV1"] | components["schemas"]["RotV1"] | components["schemas"]["IxnV1"] | components["schemas"]["DipV1"] | components["schemas"]["DrtV1"] | components["schemas"]["RctV1"] | components["schemas"]["QryV1"] | components["schemas"]["RpyV1"] | components["schemas"]["ProV1"] | components["schemas"]["BarV1"] | components["schemas"]["ExnV1"] | components["schemas"]["VcpV1"] | components["schemas"]["VrtV1"] | components["schemas"]["IssV1"] | components["schemas"]["RevV1"] | components["schemas"]["BisV1"] | components["schemas"]["BrvV1"] | components["schemas"]["IcpV2"] | components["schemas"]["RotV2"] | components["schemas"]["IxnV2"] | components["schemas"]["DipV2"] | components["schemas"]["DrtV2"] | components["schemas"]["RctV2"] | components["schemas"]["QryV2"] | components["schemas"]["RpyV2"] | components["schemas"]["ProV2"] | components["schemas"]["BarV2"] | components["schemas"]["XipV2"] | components["schemas"]["ExnV2"]; + atc: string; + }; + AgentConfig: { + iurls?: string[]; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} diff --git a/test-integration/challenge.test.ts b/test-integration/challenge.test.ts index e065a1f8..cf8380f6 100644 --- a/test-integration/challenge.test.ts +++ b/test-integration/challenge.test.ts @@ -1,5 +1,5 @@ import { assert, test } from 'vitest'; -import signify, { Serder } from 'signify-ts'; +import signify, { Serder, SerderSAD } from 'signify-ts'; import { resolveEnvironment } from './utils/resolve-env.ts'; import { assertOperations, @@ -115,11 +115,11 @@ test('challenge', async () => { //Alice mark response as accepted const verifyResponse = verifyOperation.response as { - exn: Record; + exn: SerderSAD; }; - const exn = new Serder(verifyResponse.exn); + const exn = new Serder(verifyResponse.exn as SerderSAD); - await client1.challenges().responded(aid2.i, exn.sad.d); + await client1.challenges().responded(aid2.i, exn.sad.d!); console.log('Alice marked challenge response as accepted'); // Check Bob's challenge in conctats diff --git a/test-integration/credentials.test.ts b/test-integration/credentials.test.ts index 42e5d04e..80f3697f 100644 --- a/test-integration/credentials.test.ts +++ b/test-integration/credentials.test.ts @@ -15,7 +15,7 @@ import { import { retry } from './utils/retry.ts'; import { randomUUID } from 'node:crypto'; import { step } from './utils/test-step.ts'; - +import { CredentialResult } from '../src/keri/app/credentialing.ts'; const { vleiServerUrl } = resolveEnvironment(); const QVI_SCHEMA_SAID = 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao'; @@ -168,6 +168,7 @@ test('single signature credentials', { timeout: 90000 }, async () => { await step('issuer list credentials', async () => { const issuerCredentials = await issuerClient.credentials().list(); + assertLength(issuerCredentials, 1); assert(issuerCredentials.length >= 1); assert.equal(issuerCredentials[0].sad.s, QVI_SCHEMA_SAID); assert.equal(issuerCredentials[0].sad.i, issuerAid.prefix); @@ -226,9 +227,10 @@ test('single signature credentials', { timeout: 90000 }, async () => { }); await step('issuer get credential by id', async () => { - const issuerCredential = await issuerClient + const issuerCredential = (await issuerClient .credentials() - .get(qviCredentialId); + .get(qviCredentialId)); + assert(issuerCredential !== undefined); assert.equal(issuerCredential.sad.s, QVI_SCHEMA_SAID); assert.equal(issuerCredential.sad.i, issuerAid.prefix); assert.equal(issuerCredential.status.s, '0'); @@ -236,9 +238,9 @@ test('single signature credentials', { timeout: 90000 }, async () => { await step('issuer IPEX grant', async () => { const dt = createTimestamp(); - const issuerCredential = await issuerClient + const issuerCredential = (await issuerClient .credentials() - .get(qviCredentialId); + .get(qviCredentialId)); assert(issuerCredential !== undefined); const [grant, gsigs, gend] = await issuerClient.ipex().grant({ @@ -246,7 +248,7 @@ test('single signature credentials', { timeout: 90000 }, async () => { acdc: new Serder(issuerCredential.sad), anc: new Serder(issuerCredential.anc), iss: new Serder(issuerCredential.iss), - ancAttachment: issuerCredential.ancAttachment, + ancAttachment: issuerCredential.ancatc, recipient: holderAid.prefix, datetime: dt, }); @@ -303,9 +305,9 @@ test('single signature credentials', { timeout: 90000 }, async () => { await step('holder has credential', async () => { const holderCredential = await retry(async () => { - const result = await holderClient + const result = (await holderClient .credentials() - .get(qviCredentialId); + .get(qviCredentialId)); assert(result !== undefined); return result; }); @@ -416,9 +418,9 @@ test('single signature credentials', { timeout: 90000 }, async () => { await markAndRemoveNotification(holderClient, holderAgreeNote); - const holderCredential = await holderClient + const holderCredential = (await holderClient .credentials() - .get(qviCredentialId); + .get(qviCredentialId)); const [grant2, gsigs2, gend2] = await holderClient.ipex().grant({ senderName: holderAid.name, @@ -428,7 +430,7 @@ test('single signature credentials', { timeout: 90000 }, async () => { iss: new Serder(holderCredential.iss), acdcAttachment: holderCredential.atc, ancAttachment: holderCredential.ancatc, - issAttachment: holderCredential.issAtc, + issAttachment: holderCredential.issatc, agreeSaid: agreeSaid, datetime: createTimestamp(), }); @@ -470,9 +472,9 @@ test('single signature credentials', { timeout: 90000 }, async () => { await markAndRemoveNotification(verifierClient, verifierGrantNote); - const verifierCredential = await retry(async () => + const verifierCredential = (await retry(async () => verifierClient.credentials().get(qviCredentialId) - ); + )); assert.equal(verifierCredential.sad.s, QVI_SCHEMA_SAID); assert.equal(verifierCredential.sad.i, issuerAid.prefix); @@ -508,9 +510,9 @@ test('single signature credentials', { timeout: 90000 }, async () => { const leCredentialId = await step( 'holder create LE (chained) credential', async () => { - const qviCredential = await holderClient + const qviCredential = (await holderClient .credentials() - .get(qviCredentialId); + .get(qviCredentialId)); const result = await holderClient .credentials() @@ -540,15 +542,15 @@ test('single signature credentials', { timeout: 90000 }, async () => { }); await waitOperation(holderClient, result.op); - return result.acdc.sad.d; + return result.acdc.sad.d!; } ); await step('LE credential IPEX grant', async () => { const dt = createTimestamp(); - const leCredential = await holderClient + const leCredential = (await holderClient .credentials() - .get(leCredentialId); + .get(leCredentialId)); assert(leCredential !== undefined); const [grant, gsigs, gend] = await holderClient.ipex().grant({ @@ -556,7 +558,7 @@ test('single signature credentials', { timeout: 90000 }, async () => { acdc: new Serder(leCredential.sad), anc: new Serder(leCredential.anc), iss: new Serder(leCredential.iss), - ancAttachment: leCredential.ancAttachment, + ancAttachment: leCredential.ancatc, recipient: legalEntityAid.prefix, datetime: dt, }); @@ -603,15 +605,22 @@ test('single signature credentials', { timeout: 90000 }, async () => { }); await step('Legal Entity has chained credential', async () => { - const legalEntityCredential = await retry(async () => + const legalEntityCredential = (await retry(async () => legalEntityClient.credentials().get(leCredentialId) - ); - + )); assert.equal(legalEntityCredential.sad.s, LE_SCHEMA_SAID); assert.equal(legalEntityCredential.sad.i, holderAid.prefix); - assert.equal(legalEntityCredential.sad.a.i, legalEntityAid.prefix); + assert.equal(legalEntityCredential.sad.a !== undefined, true); + if (legalEntityCredential.sad.a) { + assert.equal(legalEntityCredential.sad.a.i, legalEntityAid.prefix); + } assert.equal(legalEntityCredential.status.s, '0'); - assert.equal(legalEntityCredential.chains[0].sad.d, qviCredentialId); + assert(Array.isArray(legalEntityCredential.chains)); + assert(legalEntityCredential.chains.length > 0); + const firstChain = legalEntityCredential.chains[0] as { + sad: { d: string }; + }; + assert.equal(firstChain.sad.d, qviCredentialId); assert(legalEntityCredential.atc !== undefined); }); @@ -621,9 +630,9 @@ test('single signature credentials', { timeout: 90000 }, async () => { .revoke(issuerAid.name, qviCredentialId); await waitOperation(issuerClient, revokeOperation.op); - const issuerCredential = await issuerClient + const issuerCredential = (await issuerClient .credentials() - .get(qviCredentialId); + .get(qviCredentialId)); assert.equal(issuerCredential.status.s, '1'); }); diff --git a/test-integration/delegation.test.ts b/test-integration/delegation.test.ts index 726b9910..b15717f0 100644 --- a/test-integration/delegation.test.ts +++ b/test-integration/delegation.test.ts @@ -97,7 +97,9 @@ test('delegation', async () => { return apprDelRes; }); assert.equal( - JSON.stringify(result.serder.sad.a[0]), + JSON.stringify( + (result.serder.sad.a as Record[])[0] + ), JSON.stringify(anchor) ); }); diff --git a/test-integration/multisig-holder.test.ts b/test-integration/multisig-holder.test.ts index 46db7629..87186964 100644 --- a/test-integration/multisig-holder.test.ts +++ b/test-integration/multisig-holder.test.ts @@ -1,5 +1,10 @@ import { assert, test } from 'vitest'; -import signify, { SignifyClient, Operation, CredentialData } from 'signify-ts'; +import signify, { + SignifyClient, + Operation, + CredentialData, + Seal, +} from 'signify-ts'; import { resolveEnvironment } from './utils/resolve-env.ts'; import { assertOperations, @@ -145,7 +150,7 @@ test('multisig', async function run() { let rpy = endRoleRes.serder; let sigs = endRoleRes.sigs; let ghabState1 = ghab1['state']; - let seal = [ + let seal: Seal = [ 'SealEvent', { i: ghab1['prefix'], @@ -523,7 +528,7 @@ async function multisigAdmitCredential( .submitAdmit(groupName, admit, sigs, end, [issuerPrefix]); const mstate = gHab['state']; - const seal = [ + const seal: Seal = [ 'SealEvent', { i: gHab['prefix'], s: mstate['ee']['s'], d: mstate['ee']['d'] }, ]; diff --git a/test-integration/multisig-vlei-issuance.test.ts b/test-integration/multisig-vlei-issuance.test.ts index c1775279..662fea4f 100644 --- a/test-integration/multisig-vlei-issuance.test.ts +++ b/test-integration/multisig-vlei-issuance.test.ts @@ -609,6 +609,7 @@ test('multisig-vlei-issuance', async function run() { assert.equal(qviCredbyGAR1.sad.d, qviCredbyGAR2.sad.d); assert.equal(qviCredbyGAR1.sad.s, QVI_SCHEMA_SAID); assert.equal(qviCredbyGAR1.sad.i, aidGEDA.prefix); + assert(qviCredbyGAR1.sad.a !== undefined, "qviCredbyGAR1.sad.a is undefined"); assert.equal(qviCredbyGAR1.sad.a.i, aidQVI.prefix); assert.equal(qviCredbyGAR1.status.s, '0'); assert(qviCredbyGAR1.atc !== undefined); @@ -986,6 +987,7 @@ test('multisig-vlei-issuance', async function run() { assert.equal(leCredbyQAR1.sad.d, leCredbyQAR3.sad.d); assert.equal(leCredbyQAR1.sad.s, LE_SCHEMA_SAID); assert.equal(leCredbyQAR1.sad.i, aidQVI.prefix); + assert(leCredbyQAR1.sad.a !== undefined, "leCredbyQAR1.sad.a is undefined"); assert.equal(leCredbyQAR1.sad.a.i, aidLE.prefix); assert.equal(leCredbyQAR1.status.s, '0'); assert(leCredbyQAR1.atc !== undefined); @@ -1234,6 +1236,7 @@ test('multisig-vlei-issuance', async function run() { assert.equal(ecrCredbyLAR1.sad.d, ecrCredbyLAR3.sad.d); assert.equal(ecrCredbyLAR1.sad.s, ECR_SCHEMA_SAID); assert.equal(ecrCredbyLAR1.sad.i, aidLE.prefix); + assert(ecrCredbyLAR1.sad.a !== undefined, "ecrCredbyLAR1.sad.a is undefined"); assert.equal(ecrCredbyLAR1.sad.a.i, aidECR.prefix); assert.equal(ecrCredbyLAR1.status.s, '0'); assert(ecrCredbyLAR1.atc !== undefined); diff --git a/test-integration/multisig.test.ts b/test-integration/multisig.test.ts index 78d93bd5..dd6670d1 100644 --- a/test-integration/multisig.test.ts +++ b/test-integration/multisig.test.ts @@ -3,6 +3,7 @@ import signify, { SignifyClient, Serder, IssueCredentialResult, + Seal, } from 'signify-ts'; import { resolveEnvironment } from './utils/resolve-env.ts'; import { @@ -319,7 +320,7 @@ test('multisig', async function run() { let rpy = endRoleRes.serder; sigs = endRoleRes.sigs; let mstate = hab['state']; - let seal = [ + let seal: Seal = [ 'SealEvent', { i: hab['prefix'], s: mstate['ee']['s'], d: mstate['ee']['d'] }, ]; diff --git a/test-integration/singlesig-ixn.test.ts b/test-integration/singlesig-ixn.test.ts index aa7513c1..fbb2eb76 100644 --- a/test-integration/singlesig-ixn.test.ts +++ b/test-integration/singlesig-ixn.test.ts @@ -1,4 +1,4 @@ -import { EventResult, SignifyClient } from 'signify-ts'; +import signify, { EventResult, SignifyClient } from 'signify-ts'; import { assertOperations, getOrCreateClients, @@ -25,11 +25,6 @@ afterAll(async () => { await assertOperations(client1, client2); }); -interface KeyState { - i: string; - s: string; - [property: string]: any; -} describe('singlesig-ixn', () => { test('step1', async () => { @@ -46,9 +41,9 @@ describe('singlesig-ixn', () => { }); test('ixn1', async () => { // local keystate before ixn - const keystate0: KeyState = ( + const keystate0: signify.KeyState = ( await client1.keyStates().get(name1_id) - ).at(0); + ).at(0)!; expect(keystate0).not.toBeNull(); // ixn @@ -58,17 +53,17 @@ describe('singlesig-ixn', () => { await waitOperation(client1, await result.op()); // local keystate after ixn - const keystate1: KeyState = ( + const keystate1: signify.KeyState = ( await client1.keyStates().get(name1_id) - ).at(0); + ).at(0)!; expect(parseInt(keystate1.s)).toBeGreaterThan(0); // sequence has incremented assert.equal(parseInt(keystate1.s), parseInt(keystate0.s) + 1); // remote keystate after ixn - const keystate2: KeyState = ( + const keystate2: signify.KeyState = ( await client2.keyStates().get(contact1_id) - ).at(0); + ).at(0)!; // remote keystate is one behind assert.equal(parseInt(keystate2.s), parseInt(keystate1.s) - 1); @@ -77,7 +72,7 @@ describe('singlesig-ixn', () => { .keyStates() .query(contact1_id, keystate1.s, undefined); op = await waitOperation(client2, op); - const keystate3: KeyState = op.response; + const keystate3: signify.KeyState = op.response; // local and remote keystate match assert.equal(keystate3.s, keystate1.s); }); diff --git a/test-integration/singlesig-rot.test.ts b/test-integration/singlesig-rot.test.ts index cf07b070..4f439d88 100644 --- a/test-integration/singlesig-rot.test.ts +++ b/test-integration/singlesig-rot.test.ts @@ -1,5 +1,5 @@ import { afterAll, assert, beforeAll, describe, expect, test } from 'vitest'; -import { EventResult, RotateIdentifierArgs, SignifyClient } from 'signify-ts'; +import signify, { EventResult, RotateIdentifierArgs, SignifyClient } from 'signify-ts'; import { assertOperations, getOrCreateClients, @@ -25,14 +25,6 @@ afterAll(async () => { await assertOperations(client1, client2); }); -interface KeyState { - i: string; - s: string; - k: string[]; - n: string[]; - [property: string]: any; -} - describe('singlesig-rot', () => { test('step1', async () => { assert.equal(name1_id, contact1_id); @@ -48,9 +40,9 @@ describe('singlesig-rot', () => { }); test('rot1', async () => { // local keystate before rot - const keystate0: KeyState = ( + const keystate0: signify.KeyState = ( await client1.keyStates().get(name1_id) - ).at(0); + ).at(0)!; expect(keystate0).not.toBeNull(); assert.strictEqual(keystate0.k.length, 1); assert.strictEqual(keystate0.n.length, 1); @@ -63,9 +55,9 @@ describe('singlesig-rot', () => { await waitOperation(client1, await result.op()); // local keystate after rot - const keystate1: KeyState = ( + const keystate1: signify.KeyState = ( await client1.keyStates().get(name1_id) - ).at(0); + ).at(0)!; expect(parseInt(keystate1.s)).toBeGreaterThan(0); // sequence has incremented assert.equal(parseInt(keystate1.s), parseInt(keystate0.s) + 1); @@ -75,9 +67,9 @@ describe('singlesig-rot', () => { expect(keystate1.n[0]).not.toEqual(keystate0.n[0]); // remote keystate after rot - const keystate2: KeyState = ( + const keystate2: signify.KeyState = ( await client2.keyStates().get(contact1_id) - ).at(0); + ).at(0)!; // remote keystate is one behind assert.equal(parseInt(keystate2.s), parseInt(keystate1.s) - 1); @@ -86,7 +78,7 @@ describe('singlesig-rot', () => { .keyStates() .query(contact1_id, keystate1.s, undefined); op = await waitOperation(client2, op); - const keystate3: KeyState = op.response; + const keystate3: signify.KeyState = op.response; // local and remote keystate match assert.equal(keystate3.s, keystate1.s); assert.equal(keystate3.k[0], keystate1.k[0]); diff --git a/test-integration/utils/multisig-utils.ts b/test-integration/utils/multisig-utils.ts index fe3b1a6e..dc5563a6 100644 --- a/test-integration/utils/multisig-utils.ts +++ b/test-integration/utils/multisig-utils.ts @@ -1,16 +1,21 @@ +import assert from 'assert'; import signify, { Algos, CreateIdentiferArgs, CredentialData, + ExternHabState, + GroupHabState, + HabState, + RandyHabState, + SaltyHabState, + Seal, Serder, Siger, SignifyClient, d, messagize, - HabState, } from 'signify-ts'; import { getStates, waitAndMarkNotification } from './test-util.ts'; -import assert from 'assert'; export interface AcceptMultisigInceptArgs { groupName: string; @@ -85,7 +90,7 @@ export async function acceptMultisigIncept( export async function addEndRoleMultisig( client: SignifyClient, groupName: string, - aid: HabState, + aid: SaltyHabState | GroupHabState | ExternHabState | RandyHabState, otherMembersAIDs: HabState[], multisigAID: HabState, timestamp: string, @@ -108,7 +113,7 @@ export async function addEndRoleMultisig( const rpy = endRoleResult.serder; const sigs = endRoleResult.sigs; const ghabState1 = multisigAID.state; - const seal = [ + const seal: Seal = [ 'SealEvent', { i: multisigAID.prefix, @@ -170,7 +175,7 @@ export async function admitMultisig( .submitAdmit(multisigAID.name, admit, sigs, end, [recipientAID.prefix]); const mstate = multisigAID.state; - const seal = [ + const seal: Seal = [ 'SealEvent', { i: multisigAID.prefix, s: mstate['ee']['s'], d: mstate['ee']['d'] }, ]; @@ -311,7 +316,9 @@ export async function delegateMultisig( ); assert.equal( - JSON.stringify(delResult.serder.sad.a[0]), + JSON.stringify( + (delResult.serder.sad.a as Record[])[0] + ), JSON.stringify(anchor) ); @@ -375,7 +382,7 @@ export async function grantMultisig( .submitGrant(multisigAID.name, grant, sigs, end, [recipientAID.prefix]); const mstate = multisigAID.state; - const seal = [ + const seal: Seal = [ 'SealEvent', { i: multisigAID.prefix, s: mstate['ee']['s'], d: mstate['ee']['d'] }, ]; diff --git a/test-integration/utils/test-util.ts b/test-integration/utils/test-util.ts index 5178b158..f8e883d3 100644 --- a/test-integration/utils/test-util.ts +++ b/test-integration/utils/test-util.ts @@ -334,7 +334,7 @@ export async function getOrIssueCredential( await waitOperation(issuerClient, issResult.op); const credential = await issuerClient .credentials() - .get(issResult.acdc.sad.d); + .get(issResult.acdc.sad.d!); return credential; } diff --git a/test/app/aiding.test.ts b/test/app/aiding.test.ts index 4569c272..bcc7527b 100644 --- a/test/app/aiding.test.ts +++ b/test/app/aiding.test.ts @@ -11,8 +11,8 @@ import { Identifier, IdentifierDeps, IdentifierManagerFactory, - Tier, randomPasscode, + Tier, } from '../../src/index.ts'; import { createMockIdentifierState } from './test-utils.ts'; diff --git a/test/app/clienting.test.ts b/test/app/clienting.test.ts index b969ba7b..a7fc7af4 100644 --- a/test/app/clienting.test.ts +++ b/test/app/clienting.test.ts @@ -97,14 +97,17 @@ describe('SignifyClient', () => { assert.equal(client.controller.serder.sad.s, '1'); assert.equal(client.controller.serder.sad.t, 'ixn'); assert.equal( - client.controller.serder.sad.a[0].i, + (client.controller.serder.sad.a as Record[])[0].i, 'EEXekkGu9IAzav6pZVJhkLnjtjM5v3AcyA-pdKUcaGei' ); assert.equal( - client.controller.serder.sad.a[0].d, + (client.controller.serder.sad.a as Record[])[0].d, 'EEXekkGu9IAzav6pZVJhkLnjtjM5v3AcyA-pdKUcaGei' ); - assert.equal(client.controller.serder.sad.a[0].s, '0'); + assert.equal( + (client.controller.serder.sad.a as Record[])[0].s, + '0' + ); const data = client.data; assert(data[0], url); diff --git a/test/app/credentialing.test.ts b/test/app/credentialing.test.ts index e298fba2..c9a51621 100644 --- a/test/app/credentialing.test.ts +++ b/test/app/credentialing.test.ts @@ -14,6 +14,7 @@ import { serializeIssExnAttachment, Serials, versify, + SealSourceTriple, } from '../../src/index.ts'; import { createMockFetch, mockCredential } from './test-utils.ts'; @@ -169,7 +170,7 @@ describe('Ipex', () => { const anc = interact({ pre: mockCredential.sad.i, sn: 1, - data: [{}], + data: [{}] as SealSourceTriple[], dig: mockCredential.sad.d, version: undefined, kind: undefined, @@ -271,7 +272,7 @@ describe('Ipex', () => { const [admit, asigs, aend] = await ipex.admit({ senderName: 'holder', message: '', - grantSaid: grant.sad.d, + grantSaid: grant.sad.d!, recipient: holder, datetime: mockCredential.sad.a.dt, }); @@ -337,7 +338,7 @@ describe('Ipex', () => { const anc = interact({ pre: mockCredential.sad.i, sn: 1, - data: [{}], + data: [{}] as SealSourceTriple[], dig: mockCredential.sad.d, version: undefined, kind: undefined, @@ -445,7 +446,7 @@ describe('Ipex', () => { recipient: holder, message: 'OK!', datetime: mockCredential.sad.a.dt, - offerSaid: offer.sad.d, + offerSaid: offer.sad.d!, }); assert.deepStrictEqual(agree.sad, { @@ -576,7 +577,7 @@ describe('Ipex', () => { senderName: 'holder', message: '', recipient: holder, - grantSaid: grant.sad.d, + grantSaid: grant.sad.d!, datetime: mockCredential.sad.a.dt, }); diff --git a/test/app/delegating.test.ts b/test/app/delegating.test.ts index 48bff125..d306fc0f 100644 --- a/test/app/delegating.test.ts +++ b/test/app/delegating.test.ts @@ -1,5 +1,5 @@ import { assert, describe, it } from 'vitest'; -import { Tier } from '../../src/index.ts'; +import { Tier } from '../../src/keri/core/salter.ts'; import libsodium from 'libsodium-wrappers-sumo'; import { SignifyClient } from '../../src/keri/app/clienting.ts'; import { createMockFetch } from './test-utils.ts'; @@ -18,7 +18,12 @@ describe('delegate', () => { await client.connect(); const delegations = client.delegations(); await delegations.approve( - 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao' + 'EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao', + { + s: '', + i: '', + d: '', + } ); const lastCall = fetchMock.mock.calls[fetchMock.mock.calls.length - 1]!; assert.equal( @@ -29,16 +34,16 @@ describe('delegate', () => { assert.equal(lastCall[1]!.method, 'POST'); const expectedBody = { ixn: { - v: 'KERI10JSON0000cf_', + v: 'KERI10JSON0000e1_', t: 'ixn', - d: 'EBPt7hivibUQN-dlRyE9x_Y5LgFCGJ8QoNLSJrIkBYIg', + d: 'EPe2DWvz02_iuMWAZSoV380_EFi3yvdRuKU7xjEvRMkG', i: 'ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK', s: '1', p: 'ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK', - a: [null], + a: [{ s: '', i: '', d: '' }], }, sigs: [ - 'AAC4StAw-0IiV_LujceAXB3tnkaK011rPYPBKLgz-u6jI7hwfWGTCu5LDvBUsON4CqXbZAwPgIv6JqYjIusWKv0G', + 'AADY_50NnRkdv92XNzAYTdMVT7wLNVKuRfla9cgJK1xHlM6Ea-8pbTIjQ8k7Sn_j9AOOTUgVwqTOGBhagzmWAnkK', ], salty: { sxlt: '1AAHnNQTkD0yxOC9tSz_ukbB2e-qhDTStH18uCsi5PCwOyXLONDR3MeKwWv_AVJKGKGi6xiBQH25_R1RXLS2OuK3TN3ovoUKH7-A', diff --git a/test/app/registry.test.ts b/test/app/registry.test.ts index 32dd7d20..cff65027 100644 --- a/test/app/registry.test.ts +++ b/test/app/registry.test.ts @@ -67,14 +67,18 @@ describe('registry', () => { const mockedClient = mock(SignifyClient); const mockedIdentifiers = mock(Identifier); - const hab = { + const hab = ({ prefix: 'hab prefix', state: { s: 0, d: 'a digest', c: ['EO'] } as unknown as KeyState, name: 'a name', transferable: true, windexes: [], icp_dt: '2023-12-01T10:05:25.062609+00:00', - } as HabState; + randy: { + prxs: [], + nxts: [], + }, + } as unknown) as HabState; when(mockedIdentifiers.get('a name')).thenResolve(hab); when(mockedClient.identifiers()).thenReturn( diff --git a/test/app/test-utils.ts b/test/app/test-utils.ts index e1f1cf3a..93529c16 100644 --- a/test/app/test-utils.ts +++ b/test/app/test-utils.ts @@ -4,6 +4,7 @@ import { Authenticater, Controller, CreateIdentiferArgs, + DelegateInceptEventSAD, HEADER_SIG_TIME, IdentifierManagerFactory, MtrDex, @@ -96,33 +97,124 @@ export async function createMockIdentifierState( ...(delpre ? { delpre } : {}), }); - return { - name: name, - prefix: serder.pre, - [algo]: keeper.params(), - transferable, - windexes: [], - state: { - vn: [serder.version.major, serder.version.minor], - s: serder.sad.s, - d: serder.sad.d, - i: serder.pre, - ee: serder.sad as EstablishmentState, - kt: serder.sad.kt, - k: serder.sad.k, - nt: serder.sad.nt, - n: serder.sad.n, - bt: serder.sad.bt, - b: serder.sad.b, - p: serder.sad.p ?? '', - f: '', - dt: new Date().toISOString().replace('Z', '000+00:00'), - et: '', - c: [], - di: serder.sad.di ?? '', - } as KeyState, - icp_dt: '2023-12-01T10:05:25.062609+00:00', - }; + // Mock for each algo type + if (algo === Algos.salty) { + return { + name, + prefix: serder.pre, + salty: keeper.params(), + transferable, + windexes: [], + state: { + vn: [serder.version.major, serder.version.minor], + s: serder.sad.s, + d: serder.sad.d, + i: serder.pre, + ee: serder.sad as EstablishmentState, + kt: serder.sad.kt, + k: serder.sad.k, + nt: serder.sad.nt, + n: serder.sad.n, + bt: serder.sad.bt, + b: serder.sad.b, + p: ((serder.sad as Record).p as string) ?? '', + f: '', + dt: new Date().toISOString().replace('Z', '000+00:00'), + et: '', + c: [], + di: (serder.sad as DelegateInceptEventSAD).di ?? '', + } as KeyState, + icp_dt: '2023-12-01T10:05:25.062609+00:00', + } as unknown as HabState; + } else if (algo === Algos.randy) { + return { + name, + prefix: serder.pre, + randy: keeper.params(), + transferable, + windexes: [], + state: { + vn: [serder.version.major, serder.version.minor], + s: serder.sad.s, + d: serder.sad.d, + i: serder.pre, + ee: serder.sad as EstablishmentState, + kt: serder.sad.kt, + k: serder.sad.k, + nt: serder.sad.nt, + n: serder.sad.n, + bt: serder.sad.bt, + b: serder.sad.b, + p: ((serder.sad as Record).p as string) ?? '', + f: '', + dt: new Date().toISOString().replace('Z', '000+00:00'), + et: '', + c: [], + di: (serder.sad as DelegateInceptEventSAD).di ?? '', + } as KeyState, + icp_dt: '2023-12-01T10:05:25.062609+00:00', + } as unknown as HabState; + } else if (algo === Algos.group) { + return { + name, + prefix: serder.pre, + group: keeper.params(), + transferable, + windexes: [], + state: { + vn: [serder.version.major, serder.version.minor], + s: serder.sad.s, + d: serder.sad.d, + i: serder.pre, + ee: serder.sad as EstablishmentState, + kt: serder.sad.kt, + k: serder.sad.k, + nt: serder.sad.nt, + n: serder.sad.n, + bt: serder.sad.bt, + b: serder.sad.b, + p: ((serder.sad as Record).p as string) ?? '', + f: '', + dt: new Date().toISOString().replace('Z', '000+00:00'), + et: '', + c: [], + di: (serder.sad as DelegateInceptEventSAD).di ?? '', + } as KeyState, + icp_dt: '2023-12-01T10:05:25.062609+00:00', + } as unknown as HabState; + } else if (algo === Algos.extern) { + return { + name, + prefix: serder.pre, + extern: extern ?? {}, + extern_type: extern_type ?? 'mock', + pidx: 0, + transferable, + windexes: [], + state: { + vn: [serder.version.major, serder.version.minor], + s: serder.sad.s, + d: serder.sad.d, + i: serder.pre, + ee: serder.sad as EstablishmentState, + kt: serder.sad.kt, + k: serder.sad.k, + nt: serder.sad.nt, + n: serder.sad.n, + bt: serder.sad.bt, + b: serder.sad.b, + p: ((serder.sad as Record).p as string) ?? '', + f: '', + dt: new Date().toISOString().replace('Z', '000+00:00'), + et: '', + c: [], + di: (serder.sad as DelegateInceptEventSAD).di ?? '', + } as KeyState, + icp_dt: '2023-12-01T10:05:25.062609+00:00', + } as unknown as HabState; + } else { + throw new Error('Unknown algo type'); + } } export const mockConnect = { diff --git a/test/core/decrypter.test.ts b/test/core/decrypter.test.ts index ec4ea2a2..bedb32c9 100644 --- a/test/core/decrypter.test.ts +++ b/test/core/decrypter.test.ts @@ -99,7 +99,7 @@ describe('Decrypter', () => { seedcipher.qb64b, null, signer.verfer.transferable - ); + ) as Signer; assert.deepStrictEqual(designer.qb64b, seedqb64b); assert.equal(designer.code, MtrDex.Ed25519_Seed); assert.equal(designer.verfer.code, MtrDex.Ed25519); @@ -110,7 +110,7 @@ describe('Decrypter', () => { null, seedcipher, signer.verfer.transferable - ); + ) as Signer; assert.deepStrictEqual(designer.qb64b, seedqb64b); assert.equal(designer.code, MtrDex.Ed25519_Seed); assert.equal(designer.verfer.code, MtrDex.Ed25519); @@ -139,7 +139,7 @@ describe('Decrypter', () => { b(cipherseed), null, signer.verfer.transferable - ); + ) as Signer; assert.deepStrictEqual(designer.qb64b, seedqb64b); assert.equal(designer.code, MtrDex.Ed25519_Seed); assert.equal(designer.verfer.code, MtrDex.Ed25519); diff --git a/test/core/eventing.test.ts b/test/core/eventing.test.ts index 267ae080..def98431 100644 --- a/test/core/eventing.test.ts +++ b/test/core/eventing.test.ts @@ -2,7 +2,7 @@ import libsodium from 'libsodium-wrappers-sumo'; import { Signer } from '../../src/keri/core/signer.ts'; import { assert, describe, it } from 'vitest'; import { MtrDex } from '../../src/keri/core/matter.ts'; -import { incept, messagize, rotate } from '../../src/keri/core/eventing.ts'; +import { incept, messagize, rotate, Seal } from '../../src/keri/core/eventing.ts'; import { Saider } from '../../src/keri/core/saider.ts'; import { Diger } from '../../src/keri/core/diger.ts'; import { b, d, Ilks } from '../../src/keri/core/core.ts'; @@ -172,7 +172,7 @@ describe('key event function', () => { '"nt":1,"n":["EIf-ENw7PrM52w4H-S7NGU2qVIfraXVIlV9hEAaMHg7W"],"bt":0,"b":[],"c":[],"a":[]}' + '-AABAABB3MJGmBXxSEryNHw3YwZZLRl_6Ws4Me2WFq8PrQ6WlluSOpPqbwXuiG9RvNWZkqeW8A_0VRjokGMVRZ3m-c0I' ); - const seal = [ + const seal:Seal = [ 'SealEvent', { i: 'EIflL4H4134zYoRM6ls6Q086RLC_BhfNFh5uk-WxvhsL', diff --git a/test/core/manager.test.ts b/test/core/manager.test.ts index fef02f14..ca2fe32c 100644 --- a/test/core/manager.test.ts +++ b/test/core/manager.test.ts @@ -25,8 +25,9 @@ import { IdentifierManagerFactory, Prefixer, RandyIdentifierManager, + KArgs, } from '../../src/index.ts'; -import { RandyKeyState, KeyState } from '../../src/keri/core/keyState.ts'; +import { RandyKeyState, KeyState, RandyHabState, ExternHabState, HabState } from '../../src/keri/core/keyState.ts'; import { randomUUID } from 'node:crypto'; describe('RandyCreator', () => { @@ -714,7 +715,7 @@ describe('Manager', () => { const keeper0 = manager.new( Algos.randy, 0, - {} + {} as KArgs ) as RandyIdentifierManager; const [keys] = await keeper0.incept(false); const prefixes = new Prefixer({ qb64: keys[0] }); @@ -727,7 +728,7 @@ describe('Manager', () => { transferable: false, windexes: [], icp_dt: '2023-12-01T10:05:25.062609+00:00', - }); + } as unknown as RandyHabState); assert(keeper0 instanceof RandyIdentifierManager); assert(keeper1 instanceof RandyIdentifierManager); @@ -739,9 +740,9 @@ describe('Manager', () => { const manager = new IdentifierManagerFactory(salter, []); - expect(() => manager.new(randomUUID() as Algos, 0, {})).toThrow( - 'Unknown algo' - ); + expect(() => + manager.new(randomUUID() as Algos, 0, {} as KArgs) + ).toThrow('Unknown algo'); expect(() => manager.get({ prefix: '', @@ -750,7 +751,7 @@ describe('Manager', () => { transferable: false, windexes: [], icp_dt: '2023-12-01T10:05:25.062609+00:00', - }) + } as unknown as HabState) ).toThrow('No algo specified'); }); @@ -785,7 +786,7 @@ describe('Manager', () => { const keeper = manager.new(Algos.extern, 0, { extern_type: 'mock', param, - }); + } as KArgs); assert(keeper instanceof MockModule); expect(keeper.params()).toMatchObject({ param }); @@ -802,7 +803,7 @@ describe('Manager', () => { manager.new(Algos.extern, 0, { extern_type: 'mock', param, - }) + } as KArgs) ).toThrow('unsupported external module type mock'); }); @@ -828,7 +829,7 @@ describe('Manager', () => { }, transferable: true, icp_dt: '2023-12-01T10:05:25.062609+00:00', - }); + } as unknown as ExternHabState); assert(keeper instanceof MockModule); expect(keeper.params()).toMatchObject({ param, pidx: 3 }); @@ -855,7 +856,7 @@ describe('Manager', () => { }, transferable: true, icp_dt: '2023-12-01T10:05:25.062609+00:00', - }) + } as unknown as ExternHabState) ).toThrow('unsupported external module type mock'); }); }); diff --git a/test/core/vdring.test.ts b/test/core/vdring.test.ts index be83defb..cb19193c 100644 --- a/test/core/vdring.test.ts +++ b/test/core/vdring.test.ts @@ -9,7 +9,7 @@ describe('vdr', () => { pre: 'ECJIoBpEcCWMzvquk861dXP8JJZ-vbmJczlDR-NYcE3g', toad: 0, }); - assert.equal(actual.pre.length, 44); + assert.equal(actual.pre?.length, 44); actual = vdr.incept({ pre: 'ECJIoBpEcCWMzvquk861dXP8JJZ-vbmJczlDR-NYcE3g',