diff --git a/src/keri/app/contacting.ts b/src/keri/app/contacting.ts index 8ba731ca..cbe4a098 100644 --- a/src/keri/app/contacting.ts +++ b/src/keri/app/contacting.ts @@ -183,15 +183,23 @@ 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; + // Check for empty response + if (res.status === 204 || res.headers.get('content-length') === '0') { + return {} as Operation; + } + const text = await res.text(); + if (!text) { + return {} as Operation; + } + return JSON.parse(text) as Operation; } } diff --git a/src/keri/app/coring.ts b/src/keri/app/coring.ts index 0969de89..f0683999 100644 --- a/src/keri/app/coring.ts +++ b/src/keri/app/coring.ts @@ -5,6 +5,9 @@ import { Matter, MtrDex } from '../core/matter.ts'; import { components } from '../../types/keria-api-schema.ts'; 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); @@ -48,9 +51,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, @@ -85,10 +88,6 @@ export interface OperationsDeps { ): Promise; } -export interface AgentConfig { - iurls?: string[]; -} - /** * Operations * @remarks @@ -208,9 +207,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'; @@ -236,9 +235,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'; @@ -252,7 +251,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'; @@ -266,9 +265,13 @@ 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/core/keeping.ts b/src/keri/core/keeping.ts index 99eeffdc..fb520c4e 100644 --- a/src/keri/core/keeping.ts +++ b/src/keri/core/keeping.ts @@ -181,57 +181,82 @@ export class IdentifierManagerFactory { let kargs: any; if (Algos.salty in aid) { - return new SaltyIdentifierManager( - this.salter, - aid.salty.pidx, - aid.salty.kidx, - aid.salty.tier, - aid.salty.transferable, - aid.salty.stem, - undefined, - undefined, - aid.salty.icodes, - undefined, - undefined, - aid.salty.ncodes, - aid.salty.dcode, - undefined, - aid.salty.sxlt - ); + algo = Algos.salty; + kargs = aid.salty; } else if (Algos.randy in aid) { - return new RandyIdentifierManager( - this.salter, - undefined, - undefined, - undefined, - new Prefixer({ qb64: aid['prefix'] }).transferable, - undefined, - undefined, - [], - undefined, - aid.randy.prxs, - aid.randy.nxts - ); + algo = Algos.randy; + kargs = aid.randy; } else if (Algos.group in aid) { - return new GroupIdentifierManager( - this, - aid.group.mhab, - undefined, - undefined, - aid.group.keys, - aid.group.ndigs - ); + algo = Algos.group; + kargs = aid.group; } else if (Algos.extern in aid) { - const typ = aid.extern.extern_type; - if (typ in this.modules) { - const mod = new this.modules[typ](aid.extern.pidx, aid.extern); - return mod; - } else { - throw new Error(`unsupported external module type ${typ}`); - } + algo = Algos.extern; + kargs = aid.extern; } else { throw new Error('No algo specified'); } + + if (!kargs) { + throw new Error('No kargs found in HabState'); + } + switch (algo) { + case Algos.salty: + kargs = kargs as SaltyKeyState; + return new SaltyIdentifierManager( + this.salter, + kargs.pidx, + kargs.kidx, + kargs.tier, + kargs.transferable, + kargs.stem, + undefined, + undefined, + kargs.icodes, + undefined, + undefined, + kargs.ncodes, + kargs.dcode, + undefined, + kargs.sxlt + ); + case Algos.randy: + kargs = kargs as RandyKeyState; + return new RandyIdentifierManager( + this.salter, + undefined, + undefined, + undefined, + new Prefixer({ qb64: aid['prefix'] }).transferable, + undefined, + undefined, + [], + undefined, + kargs.prxs, + kargs.nxts + ); + case Algos.group: + kargs = kargs as GroupKeyState; + return new GroupIdentifierManager( + this, + kargs.mhab, + undefined, + undefined, + kargs.keys, + kargs.ndigs + ); + case Algos.extern: { + kargs = kargs as ExternState; + const typ = kargs.extern_type; + if (typ in this.modules) { + const mod = new this.modules[typ](kargs.pidx, kargs); + return mod; + } else { + throw new Error(`unsupported external module type ${typ}`); + } + } + default: + throw new Error('Algo not allowed yet'); + } } } diff --git a/src/keri/core/keyState.ts b/src/keri/core/keyState.ts index cf26dba4..924fe436 100644 --- a/src/keri/core/keyState.ts +++ b/src/keri/core/keyState.ts @@ -33,4 +33,15 @@ export type ExternState = components['schemas']['ExternState']; /** * Defining properties of an identifier habitat, know as a Hab in KERIpy. */ -export type HabState = components['schemas']['Identifier']; +// 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/salter.ts b/src/keri/core/salter.ts index 61fbe8d1..46064a9e 100644 --- a/src/keri/core/salter.ts +++ b/src/keri/core/salter.ts @@ -4,7 +4,6 @@ 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'; - export { Tier } from '../../types/keria-api-schema.ts'; interface SalterArgs { diff --git a/src/types/keria-api-schema.ts b/src/types/keria-api-schema.ts index 865d1a43..da01ab78 100644 --- a/src/types/keria-api-schema.ts +++ b/src/types/keria-api-schema.ts @@ -275,6 +275,169 @@ export interface components { r: string; a: unknown; }; + RCT_V_1: { + v: string; + t: string; + d: string; + i: string; + s: string; + }; + RCT_V_2: { + v: string; + t: string; + d: string; + i: string; + s: string; + }; + QRY_V_1: { + v: string; + t: string; + d: string; + dt: string; + r: string; + rr: string; + q: { + [key: string]: unknown; + }; + }; + QRY_V_2: { + v: string; + t: string; + d: string; + i: string; + dt: string; + r: string; + rr: string; + q: { + [key: string]: unknown; + }; + }; + PRO_V_1: { + v: string; + t: string; + d: string; + dt: string; + r: string; + rr: string; + q: { + [key: string]: unknown; + }; + }; + PRO_V_2: { + v: string; + t: string; + d: string; + i: string; + dt: string; + r: string; + rr: string; + q: { + [key: string]: unknown; + }; + }; + BAR_V_1: { + v: string; + t: string; + d: string; + dt: string; + r: string; + a: unknown; + }; + BAR_V_2: { + v: string; + t: string; + d: string; + i: string; + dt: string; + r: string; + a: unknown; + }; + XIP_V_2: { + v: string; + t: string; + d: string; + i: string; + dt: string; + r: string; + q: { + [key: string]: unknown; + }; + a: unknown; + }; + EXN_V_1: { + v: string; + t: string; + d: string; + i: string; + rp: string; + p: string; + dt: string; + r: string; + q: { + [key: string]: unknown; + }; + a: unknown; + e: { + [key: string]: unknown; + }; + }; + EXN_V_2: { + v: string; + t: string; + d: string; + i: string; + x: string; + p: string; + dt: string; + r: string; + q: { + [key: string]: unknown; + }; + a: unknown; + }; + ISS_V_1: { + v: string; + t: string; + d: string; + i: string; + s: string; + ri: string; + dt: string; + }; + REV_V_1: { + v: string; + t: string; + d: string; + i: string; + s: string; + ri: string; + p: string; + dt: string; + }; + BIS_V_1: { + v: string; + t: string; + d: string; + i: string; + ii: string; + s: string; + ra: { + [key: string]: unknown; + }; + dt: string; + }; + BRV_V_1: { + v: string; + t: string; + d: string; + i: string; + s: string; + p: string; + ra: { + [key: string]: unknown; + }; + dt: string; + }; Credential: { sad: | components['schemas']['ACDC_V_1'] @@ -565,6 +728,42 @@ export interface components { signing: components['schemas']['AidRecord'][]; rotation: components['schemas']['AidRecord'][]; }; + KeyEventRecord: { + ked: + | components['schemas']['ICP_V_1'] + | components['schemas']['ROT_V_1'] + | components['schemas']['IXN_V_1'] + | components['schemas']['DIP_V_1'] + | components['schemas']['DRT_V_1'] + | components['schemas']['RCT_V_1'] + | components['schemas']['QRY_V_1'] + | components['schemas']['RPY_V_1'] + | components['schemas']['PRO_V_1'] + | components['schemas']['BAR_V_1'] + | components['schemas']['EXN_V_1'] + | components['schemas']['VCP_V_1'] + | components['schemas']['VRT_V_1'] + | components['schemas']['ISS_V_1'] + | components['schemas']['REV_V_1'] + | components['schemas']['BIS_V_1'] + | components['schemas']['BRV_V_1'] + | components['schemas']['ICP_V_2'] + | components['schemas']['ROT_V_2'] + | components['schemas']['IXN_V_2'] + | components['schemas']['DIP_V_2'] + | components['schemas']['DRT_V_2'] + | components['schemas']['RCT_V_2'] + | components['schemas']['QRY_V_2'] + | components['schemas']['RPY_V_2'] + | components['schemas']['PRO_V_2'] + | components['schemas']['BAR_V_2'] + | components['schemas']['XIP_V_2'] + | components['schemas']['EXN_V_2']; + atc: string; + }; + AgentConfig: { + iurls?: string[]; + }; }; responses: never; parameters: never; diff --git a/test-integration/singlesig-ixn.test.ts b/test-integration/singlesig-ixn.test.ts index aa7513c1..0aca5f17 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,12 +25,6 @@ afterAll(async () => { await assertOperations(client1, client2); }); -interface KeyState { - i: string; - s: string; - [property: string]: any; -} - describe('singlesig-ixn', () => { test('step1', async () => { assert.equal(name1_id, contact1_id); @@ -46,9 +40,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 +52,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 +71,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..6364a666 100644 --- a/test-integration/singlesig-rot.test.ts +++ b/test-integration/singlesig-rot.test.ts @@ -1,5 +1,9 @@ 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 +29,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 +44,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 +59,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 +71,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 +82,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 ba76000e..5affccc6 100644 --- a/test-integration/utils/multisig-utils.ts +++ b/test-integration/utils/multisig-utils.ts @@ -8,6 +8,10 @@ import signify, { d, messagize, HabState, + SaltyHabState, + GroupHabState, + ExternHabState, + RandyHabState, } from 'signify-ts'; import { getStates, waitAndMarkNotification } from './test-util.ts'; import assert from 'assert'; @@ -85,7 +89,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, diff --git a/test-integration/utils/resolve-env.ts b/test-integration/utils/resolve-env.ts index d41ce4d1..767f24fd 100644 --- a/test-integration/utils/resolve-env.ts +++ b/test-integration/utils/resolve-env.ts @@ -16,7 +16,7 @@ const WES = 'BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX'; export function resolveEnvironment( input?: TestEnvironmentPreset ): TestEnvironment { - const preset = input ?? process.env.TEST_ENVIRONMENT ?? 'docker'; + const preset = input ?? process.env.TEST_ENVIRONMENT ?? 'local'; const url = 'http://127.0.0.1:3901'; const bootUrl = 'http://127.0.0.1:3903'; diff --git a/test/app/delegating.test.ts b/test/app/delegating.test.ts index 48bff125..db886b01 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'; diff --git a/test/app/registry.test.ts b/test/app/registry.test.ts index 6ddb07e2..44e26fcd 100644 --- a/test/app/registry.test.ts +++ b/test/app/registry.test.ts @@ -78,7 +78,7 @@ describe('registry', () => { prxs: [], nxts: [], }, - }; + } as unknown as HabState; when(mockedIdentifiers.get('a name')).thenResolve(hab); when(mockedClient.identifiers()).thenReturn( diff --git a/test/core/manager.test.ts b/test/core/manager.test.ts index 88985c47..8a646e49 100644 --- a/test/core/manager.test.ts +++ b/test/core/manager.test.ts @@ -30,6 +30,8 @@ import { RandyKeyState, KeyState, HabState, + RandyHabState, + ExternHabState, } from '../../src/keri/core/keyState.ts'; import { randomUUID } from 'node:crypto'; @@ -731,7 +733,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); @@ -832,7 +834,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 }); @@ -859,7 +861,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'); }); });