diff --git a/src/keri/app/contacting.ts b/src/keri/app/contacting.ts index 62dd6ed4..29785668 100644 --- a/src/keri/app/contacting.ts +++ b/src/keri/app/contacting.ts @@ -1,6 +1,6 @@ import { SignifyClient } from './clienting.ts'; -import { Operation } from './coring.ts'; import { components } from '../../types/keria-api-schema.ts'; +import { ChallengeOperation } from '../core/keyState.ts'; import { Exn } from './exchanging.ts'; export type Contact = components['schemas']['Contact']; @@ -169,7 +169,7 @@ export class Challenges { * @param words List of challenge words to check for * @returns A promise to the long running operation */ - async verify(source: string, words: string[]): Promise> { + async verify(source: string, words: string[]): Promise { const path = `/challenges_verify/${source}`; const method = 'POST'; const data = { diff --git a/src/keri/app/coring.ts b/src/keri/app/coring.ts index 41fae8f4..fe732b1a 100644 --- a/src/keri/app/coring.ts +++ b/src/keri/app/coring.ts @@ -3,6 +3,37 @@ 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'; +import { + OOBIOperation, + QueryOperation, + EndRoleOperation, + WitnessOperation, + DelegationOperation, + RegistryOperation, + LocSchemeOperation, + ChallengeOperation, + ExchangeOperation, + SubmitOperation, + DoneOperation, + CredentialOperation, + GroupOperation, + DelegatorOperation, + CompletedOOBIOperation, + CompletedQueryOperation, + CompletedEndRoleOperation, + CompletedWitnessOperation, + CompletedDelegationOperation, + CompletedRegistryOperation, + CompletedLocSchemeOperation, + CompletedChallengeOperation, + CompletedExchangeOperation, + CompletedSubmitOperation, + CompletedDoneOperation, + CompletedCredentialOperation, + CompletedGroupOperation, + CompletedDelegatorOperation, + CompletedOperation, +} from '../core/keyState.ts'; type OOBI = components['schemas']['OOBI']; type KeyState = components['schemas']['KeyStateRecord']; @@ -51,9 +82,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, @@ -67,17 +98,21 @@ export class Oobis { } } -// TODO: the generic will be replaced by specific overrides like IpexOperation -export type Operation = Omit< - components['schemas']['Operation'], - 'response' | 'metadata' -> & { - response?: T; - metadata?: { - depends?: Operation; - [property: string]: any; - }; -}; +export type Operation = + | OOBIOperation + | QueryOperation + | EndRoleOperation + | WitnessOperation + | DelegationOperation + | RegistryOperation + | LocSchemeOperation + | ChallengeOperation + | ExchangeOperation + | SubmitOperation + | DoneOperation + | CredentialOperation + | GroupOperation + | DelegatorOperation; export interface OperationsDeps { fetch( @@ -103,13 +138,44 @@ export class Operations { this.client = client; } + private hasDepends(op: Operation): op is ( + | RegistryOperation + | CredentialOperation + | DelegatorOperation + ) & { + metadata: NonNullable< + ( + | RegistryOperation + | CredentialOperation + | DelegatorOperation + )['metadata'] + >; + } { + return op.metadata !== undefined && 'depends' in op.metadata; + } + + /** + * Check if operation failed and throw error with details + * @throws {Error} If operation has an error + */ + private throwIfFailed(op: Operation): asserts op is CompletedOperation { + if ('error' in op && op.error !== null) { + const details = op.error.details + ? ` Details: ${JSON.stringify(op.error.details)}` + : ''; + throw new Error( + `Operation '${op.name}' failed [Code ${op.error.code}]: ${op.error.message}${details}` + ); + } + } + /** * Get operation status * @async * @param {string} name Name of the operation * @returns {Promise} A promise to the status of the operation */ - async get(name: string): Promise> { + async get(name: string): Promise { const path = `/operations/${name}`; const data = null; const method = 'GET'; @@ -122,7 +188,7 @@ export class Operations { * @param {string} type Select operations by type * @returns {Promise} A list of operations */ - async list(type?: string): Promise[]> { + async list(type?: string): Promise { const params = new URLSearchParams(); if (type !== undefined) { params.append('type', type); @@ -148,42 +214,182 @@ export class Operations { /** * Poll for operation to become completed. */ - async wait( - op: Operation, + async wait( + op: OOBIOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: QueryOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: EndRoleOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: WitnessOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: DelegationOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: RegistryOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: LocSchemeOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: ChallengeOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: ExchangeOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: SubmitOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: DoneOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: CredentialOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: GroupOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: DelegatorOperation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: Operation, + options?: { + signal?: AbortSignal; + minSleep?: number; + maxSleep?: number; + increaseFactor?: number; + } + ): Promise; + async wait( + op: Operation, options: { signal?: AbortSignal; minSleep?: number; maxSleep?: number; increaseFactor?: number; } = {} - ): Promise> { + ): Promise { const minSleep = options.minSleep ?? 10; const maxSleep = options.maxSleep ?? 10000; const increaseFactor = options.increaseFactor ?? 50; - if (op.metadata?.depends?.done === false) { + if ( + this.hasDepends(op) && + op.metadata.depends && + !op.metadata.depends.done + ) { await this.wait(op.metadata.depends, options); } if (op.done === true) { + this.throwIfFailed(op); return op; } let retries = 0; - while (true) { op = await this.get(op.name); + if (op.done === true) { + this.throwIfFailed(op); + return op; + } + const delay = Math.max( minSleep, Math.min(maxSleep, 2 ** retries * increaseFactor) ); retries++; - if (op.done === true) { - return op; - } - await new Promise((resolve) => setTimeout(resolve, delay)); options.signal?.throwIfAborted(); } @@ -265,13 +471,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> { + ): Promise { const path = `/queries`; const data: any = { pre: pre, diff --git a/src/keri/app/credentialing.ts b/src/keri/app/credentialing.ts index f619ba5e..6cfb3125 100644 --- a/src/keri/app/credentialing.ts +++ b/src/keri/app/credentialing.ts @@ -19,8 +19,16 @@ import { serializeACDCAttachment, serializeIssExnAttachment, } from '../core/utils.ts'; -import { Operation } from './coring.ts'; -import { HabState } from '../core/keyState.ts'; +import { + ExchangeOperation, + CredentialOperation, + GroupOperation, + DelegationOperation, + WitnessOperation, + DoneOperation, + HabState, + RegistryOperation, +} from '../core/keyState.ts'; import { components } from '../../types/keria-api-schema.ts'; @@ -95,13 +103,13 @@ export interface IssueCredentialResult { acdc: Serder; anc: Serder; iss: Serder; - op: Operation; + op: CredentialOperation; } export interface RevokeCredentialResult { anc: Serder; rev: Serder; - op: Operation; + op: GroupOperation | DelegationOperation | WitnessOperation | DoneOperation; } export interface IpexApplyArgs { @@ -559,7 +567,7 @@ export class RegistryResult { return this._sigs; } - async op(): Promise { + async op(): Promise { const res = await this.promise; return await res.json(); } @@ -785,7 +793,7 @@ export class Ipex { exn: Serder, sigs: string[], recp: string[] - ): Promise> { + ): Promise { const body = { exn: exn.sad, sigs, @@ -829,7 +837,7 @@ export class Ipex { sigs: string[], atc: string, recp: string[] - ): Promise> { + ): Promise { const body = { exn: exn.sad, sigs, @@ -873,7 +881,7 @@ export class Ipex { exn: Serder, sigs: string[], recp: string[] - ): Promise> { + ): Promise { const body = { exn: exn.sad, sigs, @@ -941,7 +949,7 @@ export class Ipex { sigs: string[], atc: string, recp: string[] - ): Promise> { + ): Promise { const body = { exn: exn.sad, sigs: sigs, @@ -986,7 +994,7 @@ export class Ipex { sigs: string[], atc: string, recp: string[] - ): Promise> { + ): Promise { const body = { exn: exn.sad, sigs: sigs, diff --git a/src/keri/app/grouping.ts b/src/keri/app/grouping.ts index b5e09576..52203a1f 100644 --- a/src/keri/app/grouping.ts +++ b/src/keri/app/grouping.ts @@ -1,6 +1,6 @@ import { SignifyClient } from './clienting.ts'; import { Dict } from '../core/core.ts'; -import { Operation } from './coring.ts'; +import { GroupOperation } from '../core/keyState.ts'; import { ExnMultisig } from './exchanging.ts'; import { Exn } from './exchanging.ts'; @@ -67,7 +67,7 @@ export class Groups { * @param {string} [gid] prefix * @param {string[]} [smids] array of particpants * @param {string[]} [rmids] array of particpants - * @returns {Promise} A promise to the list of replay messages + * @returns {Promise} A promise to the list of replay messages */ async join( name: string, @@ -76,7 +76,7 @@ export class Groups { gid: string, smids: string[], rmids: string[] - ): Promise> { + ): Promise { const path = `/identifiers/${name}/multisig/join`; const method = 'POST'; const data = { diff --git a/src/keri/core/keyState.ts b/src/keri/core/keyState.ts index e6f4ba80..0ca59b23 100644 --- a/src/keri/core/keyState.ts +++ b/src/keri/core/keyState.ts @@ -45,5 +45,175 @@ export type ExnV1 = components['schemas']['EXN_V_1']; export type Dip = | components['schemas']['DIP_V_1'] | components['schemas']['DIP_V_2']; +export type Rot = + | components['schemas']['ROT_V_1'] + | components['schemas']['ROT_V_2']; export type ExnEmbeds = components['schemas']['ExnEmbeds']; export type MultisigRpyEmbeds = components['schemas']['MultisigRpyEmbeds']; + +/** + * Defining Operation types + */ +export type OOBIOperation = components['schemas']['OOBIOperation']; +export type QueryOperation = components['schemas']['QueryOperation']; +export type EndRoleOperation = components['schemas']['EndRoleOperation']; +export type WitnessOperation = components['schemas']['WitnessOperation']; +export type DelegationOperation = components['schemas']['DelegationOperation']; +export type RegistryOperation = components['schemas']['RegistryOperation']; +export type LocSchemeOperation = components['schemas']['LocSchemeOperation']; +export type ChallengeOperation = components['schemas']['ChallengeOperation']; +export type ExchangeOperation = components['schemas']['ExchangeOperation']; +export type SubmitOperation = components['schemas']['SubmitOperation']; +export type DoneOperation = components['schemas']['DoneOperation']; +export type CredentialOperation = components['schemas']['CredentialOperation']; +export type GroupOperation = components['schemas']['GroupOperation']; +export type DelegatorOperation = components['schemas']['DelegatorOperation']; + +export type PendingOOBIOperation = + components['schemas']['PendingOOBIOperation']; +export type PendingQueryOperation = + components['schemas']['PendingQueryOperation']; +export type PendingEndRoleOperation = + components['schemas']['PendingEndRoleOperation']; +export type PendingWitnessOperation = + components['schemas']['PendingWitnessOperation']; +export type PendingDelegationOperation = + components['schemas']['PendingDelegationOperation']; +export type PendingRegistryOperation = + components['schemas']['PendingRegistryOperation']; +export type PendingLocSchemeOperation = + components['schemas']['PendingLocSchemeOperation']; +export type PendingChallengeOperation = + components['schemas']['PendingChallengeOperation']; +export type PendingExchangeOperation = + components['schemas']['PendingExchangeOperation']; +export type PendingSubmitOperation = + components['schemas']['PendingSubmitOperation']; +export type PendingDoneOperation = + components['schemas']['PendingDoneOperation']; +export type PendingCredentialOperation = + components['schemas']['PendingCredentialOperation']; +export type PendingGroupOperation = + components['schemas']['PendingGroupOperation']; +export type PendingDelegatorOperation = + components['schemas']['PendingDelegatorOperation']; + +export type PendingOperation = + | PendingOOBIOperation + | PendingQueryOperation + | PendingEndRoleOperation + | PendingWitnessOperation + | PendingDelegationOperation + | PendingRegistryOperation + | PendingLocSchemeOperation + | PendingChallengeOperation + | PendingExchangeOperation + | PendingSubmitOperation + | PendingDoneOperation + | PendingCredentialOperation + | PendingGroupOperation + | PendingDelegatorOperation; + +export type CompletedWitnessOperation = + components['schemas']['CompletedWitnessOperation']; +export type CompletedEndRoleOperation = + components['schemas']['CompletedEndRoleOperation']; +export type CompletedOOBIOperation = + components['schemas']['CompletedOOBIOperation']; +export type CompletedDelegationOperation = + components['schemas']['CompletedDelegationOperation']; +export type CompletedRegistryOperation = + components['schemas']['CompletedRegistryOperation']; +export type CompletedLocSchemeOperation = + components['schemas']['CompletedLocSchemeOperation']; +export type CompletedChallengeOperation = + components['schemas']['CompletedChallengeOperation']; +export type CompletedExchangeOperation = + components['schemas']['CompletedExchangeOperation']; +export type CompletedSubmitOperation = + components['schemas']['CompletedSubmitOperation']; +export type CompletedDoneOperation = + components['schemas']['CompletedDoneOperation']; +export type CompletedCredentialOperation = + components['schemas']['CompletedCredentialOperation']; +export type CompletedGroupOperation = + components['schemas']['CompletedGroupOperation']; +export type CompletedDelegatorOperation = + components['schemas']['CompletedDelegatorOperation']; +export type CompletedQueryOperation = + components['schemas']['CompletedQueryOperation']; + +export type CompletedOperation = + | CompletedOOBIOperation + | CompletedEndRoleOperation + | CompletedWitnessOperation + | CompletedDelegationOperation + | CompletedRegistryOperation + | CompletedLocSchemeOperation + | CompletedChallengeOperation + | CompletedExchangeOperation + | CompletedSubmitOperation + | CompletedDoneOperation + | CompletedCredentialOperation + | CompletedGroupOperation + | CompletedDelegatorOperation + | CompletedQueryOperation; + +export type FailedOOBIOperation = components['schemas']['FailedOOBIOperation']; +export type FailedQueryOperation = + components['schemas']['FailedQueryOperation']; +export type FailedEndRoleOperation = + components['schemas']['FailedEndRoleOperation']; +export type FailedWitnessOperation = + components['schemas']['FailedWitnessOperation']; +export type FailedDelegationOperation = + components['schemas']['FailedDelegationOperation']; +export type FailedRegistryOperation = + components['schemas']['FailedRegistryOperation']; +export type FailedLocSchemeOperation = + components['schemas']['FailedLocSchemeOperation']; +export type FailedChallengeOperation = + components['schemas']['FailedChallengeOperation']; +export type FailedExchangeOperation = + components['schemas']['FailedExchangeOperation']; +export type FailedSubmitOperation = + components['schemas']['FailedSubmitOperation']; +export type FailedDoneOperation = components['schemas']['FailedDoneOperation']; +export type FailedCredentialOperation = + components['schemas']['FailedCredentialOperation']; +export type FailedGroupOperation = + components['schemas']['FailedGroupOperation']; +export type FailedDelegatorOperation = + components['schemas']['FailedDelegatorOperation']; + +export type FailedOperation = + | FailedOOBIOperation + | FailedQueryOperation + | FailedEndRoleOperation + | FailedWitnessOperation + | FailedDelegationOperation + | FailedRegistryOperation + | FailedLocSchemeOperation + | FailedChallengeOperation + | FailedExchangeOperation + | FailedSubmitOperation + | FailedDoneOperation + | FailedCredentialOperation + | FailedGroupOperation + | FailedDelegatorOperation; + +export type GenericOperation = + | OOBIOperation + | QueryOperation + | EndRoleOperation + | WitnessOperation + | DelegationOperation + | RegistryOperation + | LocSchemeOperation + | ChallengeOperation + | ExchangeOperation + | SubmitOperation + | DoneOperation + | CredentialOperation + | GroupOperation + | DelegatorOperation; diff --git a/src/types/keria-api-schema.ts b/src/types/keria-api-schema.ts index 3ac3dc7c..b67c2339 100644 --- a/src/types/keria-api-schema.ts +++ b/src/types/keria-api-schema.ts @@ -264,6 +264,25 @@ export interface components { b: string[]; n: string; }; + 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; + }; EXN_V_1: { v: string; t: string; @@ -322,20 +341,6 @@ export interface components { | components['schemas']['DRT_V_2']; ancatc: string; }; - OperationStatus: { - code: number; - message: string; - details?: { - [key: string]: unknown; - } | null; - }; - Operation: { - name: string; - error?: components['schemas']['OperationStatus']; - done?: boolean; - metadata?: Record; - response?: Record; - }; EmptyDict: Record; CredentialStateIssOrRev: { vn: unknown; @@ -518,9 +523,6 @@ export interface components { role: string; eid: string; }; - Rpy: - | components['schemas']['RPY_V_1'] - | components['schemas']['RPY_V_2']; Challenge: { words: string[]; dt?: string; @@ -618,6 +620,9 @@ export interface components { Ixn: | components['schemas']['IXN_V_1'] | components['schemas']['IXN_V_2']; + Rpy: + | components['schemas']['RPY_V_1'] + | components['schemas']['RPY_V_2']; NotificationData: { r?: string; d?: string; @@ -660,15 +665,6 @@ export interface components { | components['schemas']['DRT_V_1'] | components['schemas']['DRT_V_2']; }; - ISS_V_1: { - v: string; - t: string; - d: string; - i: string; - s: string; - ri: string; - dt: string; - }; MultisigIssueEmbeds: { acdc: | components['schemas']['ACDC_V_1'] @@ -686,16 +682,6 @@ export interface components { | components['schemas']['DRT_V_1'] | components['schemas']['DRT_V_2']; }; - REV_V_1: { - v: string; - t: string; - d: string; - i: string; - s: string; - ri: string; - p: string; - dt: string; - }; MultisigRevokeEmbeds: { rev: components['schemas']['REV_V_1']; anc: @@ -737,6 +723,602 @@ export interface components { memberName?: string; sender?: string; }; + OOBIMetadata: { + oobi: string; + }; + PendingOOBIOperation: { + name: string; + metadata?: components['schemas']['OOBIMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedOOBIOperation: { + name: string; + metadata?: components['schemas']['OOBIMetadata']; + response: components['schemas']['KeyStateRecord']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + OperationStatus: { + code: number; + message: string; + details?: { + [key: string]: unknown; + } | null; + }; + FailedOOBIOperation: { + name: string; + metadata?: components['schemas']['OOBIMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + OOBIOperation: + | components['schemas']['PendingOOBIOperation'] + | components['schemas']['CompletedOOBIOperation'] + | components['schemas']['FailedOOBIOperation']; + QueryMetadata: { + pre: string; + sn: number; + anchor?: components['schemas']['Anchor']; + }; + PendingQueryOperation: { + name: string; + metadata?: components['schemas']['QueryMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedQueryOperation: { + name: string; + metadata?: components['schemas']['QueryMetadata']; + response: components['schemas']['KeyStateRecord']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedQueryOperation: { + name: string; + metadata?: components['schemas']['QueryMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + QueryOperation: + | components['schemas']['PendingQueryOperation'] + | components['schemas']['CompletedQueryOperation'] + | components['schemas']['FailedQueryOperation']; + EndRoleMetadata: { + cid: string; + role: string; + eid: string; + }; + PendingEndRoleOperation: { + name: string; + metadata?: components['schemas']['EndRoleMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedEndRoleOperation: { + name: string; + metadata?: components['schemas']['EndRoleMetadata']; + response: + | components['schemas']['RPY_V_1'] + | components['schemas']['RPY_V_2']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedEndRoleOperation: { + name: string; + metadata?: components['schemas']['EndRoleMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + EndRoleOperation: + | components['schemas']['PendingEndRoleOperation'] + | components['schemas']['CompletedEndRoleOperation'] + | components['schemas']['FailedEndRoleOperation']; + WitnessMetadata: { + pre: string; + sn: number; + }; + PendingWitnessOperation: { + name: string; + metadata?: components['schemas']['WitnessMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedWitnessOperation: { + name: string; + metadata?: components['schemas']['WitnessMetadata']; + response: + | components['schemas']['ICP_V_1'] + | components['schemas']['ICP_V_2'] + | components['schemas']['ROT_V_1'] + | components['schemas']['ROT_V_2'] + | components['schemas']['IXN_V_1'] + | components['schemas']['IXN_V_2']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedWitnessOperation: { + name: string; + metadata?: components['schemas']['WitnessMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + WitnessOperation: + | components['schemas']['PendingWitnessOperation'] + | components['schemas']['CompletedWitnessOperation'] + | components['schemas']['FailedWitnessOperation']; + DelegationMetadata: { + pre: string; + sn: number; + }; + PendingDelegationOperation: { + name: string; + metadata?: components['schemas']['DelegationMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedDelegationOperation: { + name: string; + metadata?: components['schemas']['DelegationMetadata']; + response: + | components['schemas']['DIP_V_1'] + | components['schemas']['DIP_V_2'] + | components['schemas']['DRT_V_1'] + | components['schemas']['DRT_V_2']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedDelegationOperation: { + name: string; + metadata?: components['schemas']['DelegationMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + DelegationOperation: + | components['schemas']['PendingDelegationOperation'] + | components['schemas']['CompletedDelegationOperation'] + | components['schemas']['FailedDelegationOperation']; + RegistryOperationMetadata: { + pre: string; + depends?: components['schemas']['Operation']; + anchor: components['schemas']['Anchor']; + }; + PendingRegistryOperation: { + name: string; + metadata?: components['schemas']['RegistryOperationMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + RegistryOperationResponse: { + anchor: components['schemas']['Anchor']; + }; + CompletedRegistryOperation: { + name: string; + metadata?: components['schemas']['RegistryOperationMetadata']; + response: components['schemas']['RegistryOperationResponse']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedRegistryOperation: { + name: string; + metadata?: components['schemas']['RegistryOperationMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + RegistryOperation: + | components['schemas']['PendingRegistryOperation'] + | components['schemas']['CompletedRegistryOperation'] + | components['schemas']['FailedRegistryOperation']; + LocSchemeMetadata: { + eid: string; + scheme: string; + url: string; + }; + PendingLocSchemeOperation: { + name: string; + metadata?: components['schemas']['LocSchemeMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedLocSchemeOperation: { + name: string; + metadata?: components['schemas']['LocSchemeMetadata']; + response: components['schemas']['LocSchemeMetadata']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedLocSchemeOperation: { + name: string; + metadata?: components['schemas']['LocSchemeMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + LocSchemeOperation: + | components['schemas']['PendingLocSchemeOperation'] + | components['schemas']['CompletedLocSchemeOperation'] + | components['schemas']['FailedLocSchemeOperation']; + ChallengeOperationMetadata: { + words: string[]; + }; + PendingChallengeOperation: { + name: string; + metadata?: components['schemas']['ChallengeOperationMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + ChallengeOperationResponse: { + exn: + | components['schemas']['EXN_V_1'] + | components['schemas']['EXN_V_2']; + }; + CompletedChallengeOperation: { + name: string; + metadata?: components['schemas']['ChallengeOperationMetadata']; + response: components['schemas']['ChallengeOperationResponse']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedChallengeOperation: { + name: string; + metadata?: components['schemas']['ChallengeOperationMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + ChallengeOperation: + | components['schemas']['PendingChallengeOperation'] + | components['schemas']['CompletedChallengeOperation'] + | components['schemas']['FailedChallengeOperation']; + ExchangeOperationMetadata: { + said: string; + }; + PendingExchangeOperation: { + name: string; + metadata?: components['schemas']['ExchangeOperationMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedExchangeOperation: { + name: string; + metadata?: components['schemas']['ExchangeOperationMetadata']; + response: components['schemas']['ExchangeOperationMetadata']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedExchangeOperation: { + name: string; + metadata?: components['schemas']['ExchangeOperationMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + ExchangeOperation: + | components['schemas']['PendingExchangeOperation'] + | components['schemas']['CompletedExchangeOperation'] + | components['schemas']['FailedExchangeOperation']; + SubmitOperationMetadata: { + pre: string; + sn: number; + }; + PendingSubmitOperation: { + name: string; + metadata?: components['schemas']['SubmitOperationMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedSubmitOperation: { + name: string; + metadata?: components['schemas']['SubmitOperationMetadata']; + response: components['schemas']['KeyStateRecord']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedSubmitOperation: { + name: string; + metadata?: components['schemas']['SubmitOperationMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + SubmitOperation: + | components['schemas']['PendingSubmitOperation'] + | components['schemas']['CompletedSubmitOperation'] + | components['schemas']['FailedSubmitOperation']; + DoneOperationMetadata: { + response: + | components['schemas']['ICP_V_1'] + | components['schemas']['ICP_V_2'] + | components['schemas']['ROT_V_1'] + | components['schemas']['ROT_V_2'] + | components['schemas']['EXN_V_1'] + | components['schemas']['EXN_V_2']; + /** @default null */ + pre: string | null; + }; + PendingDoneOperation: { + name: string; + metadata?: components['schemas']['DoneOperationMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedDoneOperation: { + name: string; + metadata?: components['schemas']['DoneOperationMetadata']; + response: + | components['schemas']['ICP_V_1'] + | components['schemas']['ICP_V_2'] + | components['schemas']['ROT_V_1'] + | components['schemas']['ROT_V_2'] + | components['schemas']['EXN_V_1'] + | components['schemas']['EXN_V_2']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedDoneOperation: { + name: string; + metadata?: components['schemas']['DoneOperationMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + DoneOperation: + | components['schemas']['PendingDoneOperation'] + | components['schemas']['CompletedDoneOperation'] + | components['schemas']['FailedDoneOperation']; + CredentialOperationMetadata: { + ced: + | components['schemas']['ACDC_V_1'] + | components['schemas']['ACDC_V_2']; + depends?: components['schemas']['Operation']; + }; + CredentialOperationResponse: { + ced?: + | components['schemas']['ACDC_V_1'] + | components['schemas']['ACDC_V_2']; + }; + PendingCredentialOperation: { + name: string; + metadata?: components['schemas']['CredentialOperationMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedCredentialOperation: { + name: string; + metadata?: components['schemas']['CredentialOperationMetadata']; + response: components['schemas']['CredentialOperationResponse']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedCredentialOperation: { + name: string; + metadata?: components['schemas']['CredentialOperationMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + CredentialOperation: + | components['schemas']['PendingCredentialOperation'] + | components['schemas']['CompletedCredentialOperation'] + | components['schemas']['FailedCredentialOperation']; + GroupOperationMetadata: { + pre: string; + sn: number; + }; + PendingGroupOperation: { + name: string; + metadata?: components['schemas']['GroupOperationMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedGroupOperation: { + name: string; + metadata?: components['schemas']['GroupOperationMetadata']; + response: + | components['schemas']['IXN_V_1'] + | components['schemas']['IXN_V_2'] + | components['schemas']['ICP_V_1'] + | components['schemas']['ICP_V_2'] + | components['schemas']['ROT_V_1'] + | components['schemas']['ROT_V_2'] + | components['schemas']['DIP_V_1'] + | components['schemas']['DIP_V_2'] + | components['schemas']['DRT_V_1'] + | components['schemas']['DRT_V_2']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedGroupOperation: { + name: string; + metadata?: components['schemas']['GroupOperationMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + GroupOperation: + | components['schemas']['PendingGroupOperation'] + | components['schemas']['CompletedGroupOperation'] + | components['schemas']['FailedGroupOperation']; + DelegatorOperationMetadata: { + pre: string; + teepre: string; + anchor?: components['schemas']['Anchor']; + depends?: + | components['schemas']['GroupOperation'] + | components['schemas']['WitnessOperation'] + | components['schemas']['DoneOperation']; + }; + PendingDelegatorOperation: { + name: string; + metadata?: components['schemas']['DelegatorOperationMetadata']; + /** + * @default false + * @enum {unknown} + */ + done: false; + }; + CompletedDelegatorOperation: { + name: string; + metadata?: components['schemas']['DelegatorOperationMetadata']; + response: string; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + FailedDelegatorOperation: { + name: string; + metadata?: components['schemas']['DelegatorOperationMetadata']; + error: components['schemas']['OperationStatus']; + /** + * @default true + * @enum {unknown} + */ + done: true; + }; + DelegatorOperation: + | components['schemas']['PendingDelegatorOperation'] + | components['schemas']['CompletedDelegatorOperation'] + | components['schemas']['FailedDelegatorOperation']; + Operation: + | components['schemas']['OOBIOperation'] + | components['schemas']['QueryOperation'] + | components['schemas']['EndRoleOperation'] + | components['schemas']['WitnessOperation'] + | components['schemas']['DelegationOperation'] + | components['schemas']['RegistryOperation'] + | components['schemas']['LocSchemeOperation'] + | components['schemas']['ChallengeOperation'] + | components['schemas']['ExchangeOperation'] + | components['schemas']['SubmitOperation'] + | components['schemas']['DoneOperation'] + | components['schemas']['CredentialOperation'] + | components['schemas']['GroupOperation'] + | components['schemas']['DelegatorOperation']; }; responses: never; parameters: never; diff --git a/test-integration/multisig-holder.test.ts b/test-integration/multisig-holder.test.ts index 408524aa..4f55a1ef 100644 --- a/test-integration/multisig-holder.test.ts +++ b/test-integration/multisig-holder.test.ts @@ -391,7 +391,7 @@ test('multisig', async function run() { const exnRes = assertIpexGrant(await client1.exchanges().get(grantMsgSaid)); recp = [aid2['state']].map((state) => state['i']); - op1 = await multisigAdmitCredential( + const exOp1 = await multisigAdmitCredential( client1, 'holder', 'member1', @@ -416,7 +416,7 @@ test('multisig', async function run() { console.log(`Member2 /exn/ipex/grant msg : ` + JSON.stringify(exnRes2)); const recp2 = [aid1['state']].map((state) => state['i']); - op2 = await multisigAdmitCredential( + const exOp2 = await multisigAdmitCredential( client2, 'holder', 'member2', @@ -425,8 +425,8 @@ test('multisig', async function run() { recp2 ); - await waitOperation(client1, op1); - await waitOperation(client2, op2); + await waitOperation(client1, exOp1); + await waitOperation(client2, exOp2); let creds1 = await client1.credentials().list(); console.log(`Member1 has ${creds1.length} credential`); @@ -503,7 +503,7 @@ async function issueCredential( let op = await client .ipex() .submitGrant(name, grant, gsigs, end, [data.a.i]); - op = await waitOperation(client, op); + await waitOperation(client, op); } console.log('Grant message sent'); diff --git a/test-integration/multisig-join.test.ts b/test-integration/multisig-join.test.ts index a19ff4bc..9bb1693b 100644 --- a/test-integration/multisig-join.test.ts +++ b/test-integration/multisig-join.test.ts @@ -221,11 +221,8 @@ describe('multisig-join', () => { waitOperation(client3, updates[5]), ]); - const states = [ - aid1State.response as KeyState, - aid2State.response as KeyState, - ]; - const rstates = [...states, aid3State.response as KeyState]; + const states = [aid1State.response, aid2State.response]; + const rstates = [...states, aid3State.response]; const rotateOperation1 = await client1 .identifiers() .rotate(nameMultisig, { states, rstates }); @@ -311,9 +308,9 @@ describe('multisig-join', () => { ]); const states = [ - aid1State.response as KeyState, - aid2State.response as KeyState, - aid3State.response as KeyState, + aid1State.response, + aid2State.response, + aid3State.response, ]; const rotateOperation1 = await client1 .identifiers() @@ -392,9 +389,6 @@ describe('multisig-join', () => { client3, await endRoleOperation.op() ); - - assert.equal(endRoleResult.done, true); - assert.equal(endRoleResult.error, null); }); }); diff --git a/test-integration/multisig.test.ts b/test-integration/multisig.test.ts index 175b69e0..d24e7a58 100644 --- a/test-integration/multisig.test.ts +++ b/test-integration/multisig.test.ts @@ -3,7 +3,6 @@ import { SignifyClient, Serder, IssueCredentialResult, - KeyState, Algos, Siger, ready, @@ -65,44 +64,44 @@ test('multisig', async function run() { ]); let op1 = await client1.oobis().resolve(oobi2.oobis[0], 'member2'); - op1 = await waitOperation(client1, op1); + await waitOperation(client1, op1); op1 = await client1.oobis().resolve(oobi3.oobis[0], 'member3'); - op1 = await waitOperation(client1, op1); + await waitOperation(client1, op1); op1 = await client1.oobis().resolve(SCHEMA_OOBI, 'schema'); - op1 = await waitOperation(client1, op1); + await waitOperation(client1, op1); op1 = await client1.oobis().resolve(oobi4.oobis[0], 'holder'); - op1 = await waitOperation(client1, op1); + await waitOperation(client1, op1); console.log('Member1 resolved 4 OOBIs'); let op2 = await client2.oobis().resolve(oobi1.oobis[0], 'member1'); - op2 = await waitOperation(client2, op2); + await waitOperation(client2, op2); op2 = await client2.oobis().resolve(oobi3.oobis[0], 'member3'); - op2 = await waitOperation(client2, op2); + await waitOperation(client2, op2); op2 = await client2.oobis().resolve(SCHEMA_OOBI, 'schema'); - op2 = await waitOperation(client2, op2); + await waitOperation(client2, op2); op2 = await client2.oobis().resolve(oobi4.oobis[0], 'holder'); - op2 = await waitOperation(client2, op2); + await waitOperation(client2, op2); console.log('Member2 resolved 4 OOBIs'); let op3 = await client3.oobis().resolve(oobi1.oobis[0], 'member1'); - op3 = await waitOperation(client3, op3); + await waitOperation(client3, op3); op3 = await client3.oobis().resolve(oobi2.oobis[0], 'member2'); - op3 = await waitOperation(client3, op3); + await waitOperation(client3, op3); op3 = await client3.oobis().resolve(SCHEMA_OOBI, 'schema'); - op3 = await waitOperation(client3, op3); + await waitOperation(client3, op3); op3 = await client3.oobis().resolve(oobi4.oobis[0], 'holder'); - op3 = await waitOperation(client3, op3); + await waitOperation(client3, op3); console.log('Member3 resolved 4 OOBIs'); let op4 = await client4.oobis().resolve(oobi1.oobis[0], 'member1'); - op4 = await waitOperation(client4, op4); + await waitOperation(client4, op4); op4 = await client4.oobis().resolve(oobi2.oobis[0], 'member2'); - op4 = await waitOperation(client4, op4); + await waitOperation(client4, op4); op4 = await client4.oobis().resolve(oobi3.oobis[0], 'member3'); - op4 = await waitOperation(client4, op4); + await waitOperation(client4, op4); op4 = await client4.oobis().resolve(SCHEMA_OOBI, 'schema'); - op4 = await waitOperation(client4, op4); + await waitOperation(client4, op4); console.log('Holder resolved 4 OOBIs'); @@ -118,22 +117,26 @@ test('multisig', async function run() { await client3.challenges().respond('member3', aid1.prefix, words); console.log('Member3 responded challenge with signed words'); - op1 = await client1.challenges().verify(aid2.prefix, words); - op1 = await waitOperation(client1, op1); + let chOp1 = await client1.challenges().verify(aid2.prefix, words); + chOp1 = await waitOperation(client1, chOp1); console.log('Member1 verified challenge response from member2'); - let exnwords = new Serder((op1.response as any)?.exn); + const chOp1Response = chOp1.response; + let exnwords = new Serder(chOp1Response.exn); let res1 = await client1 .challenges() .responded(aid2.prefix, exnwords.sad.d); assert.equal(res1.status, 202); console.log('Member1 marked challenge response as accepted'); - op1 = await client1.challenges().verify(aid3.prefix, words); - op1 = await waitOperation(client1, op1); + let chOp2 = await client1.challenges().verify(aid3.prefix, words); + chOp2 = await waitOperation(client1, chOp2); console.log('Member1 verified challenge response from member3'); - exnwords = new Serder((op1.response as any)?.exn); - res1 = await client1.challenges().responded(aid3.prefix, exnwords.sad.d); - assert.equal(res1.status, 202); + const chOp2Response = chOp2.response; + exnwords = new Serder(chOp2Response.exn); + let res2 = await client1 + .challenges() + .responded(aid3.prefix, exnwords.sad.d); + assert.equal(res2.status, 202); console.log('Member1 marked challenge response as accepted'); // First member start the creation of a multisig identifier @@ -149,7 +152,7 @@ test('multisig', async function run() { states: states, rstates: rstates, }); - op1 = await icpResult1.op(); + const groupOp1 = await icpResult1.op(); let serder = icpResult1.serder; let sigs = icpResult1.sigs; @@ -197,7 +200,7 @@ test('multisig', async function run() { states: states, rstates: rstates, }); - op2 = await icpResult2.op(); + const groupOp2 = await icpResult2.op(); serder = icpResult2.serder; sigs = icpResult2.sigs; sigers = sigs.map((sig) => new Siger({ qb64: sig })); @@ -208,7 +211,7 @@ test('multisig', async function run() { icp: [serder, atc], }; - smids = exn.a.smids; + smids = (exn.a! as { smids: string[] }).smids; recp = [aid1['state'], aid3['state']].map((state) => state['i']); await client2 @@ -242,7 +245,7 @@ test('multisig', async function run() { states: states, rstates: rstates, }); - op3 = await icpResult3.op(); + const groupOp3 = await icpResult3.op(); serder = icpResult3.serder; sigs = icpResult3.sigs; sigers = sigs.map((sig) => new Siger({ qb64: sig })); @@ -253,7 +256,14 @@ test('multisig', async function run() { icp: [serder, atc], }; - smids = exn.a.smids; + smids = + exn.a && + typeof exn.a === 'object' && + exn.a !== null && + 'smids' in exn.a && + Array.isArray((exn.a as { smids: unknown }).smids) + ? (exn.a as { smids: string[] }).smids + : []; recp = [aid1['state'], aid2['state']].map((state) => state['i']); await client3 @@ -270,9 +280,9 @@ test('multisig', async function run() { console.log('Member3 joined, multisig waiting for others...'); // Check for completion - op1 = await waitOperation(client1, op1); - op2 = await waitOperation(client2, op2); - op3 = await waitOperation(client3, op3); + await waitOperation(client1, groupOp1); + await waitOperation(client2, groupOp2); + await waitOperation(client3, groupOp3); console.log('Multisig created!'); const identifiers1 = await client1.identifiers().list(); assert.equal(identifiers1.aids.length, 2); @@ -338,7 +348,7 @@ test('multisig', async function run() { let endRoleRes = await client1 .identifiers() .addEndRole('multisig', 'agent', eid1, stamp); - op1 = await endRoleRes.op(); + const endRole1 = await endRoleRes.op(); let rpy = endRoleRes.serder; sigs = endRoleRes.sigs; let mstate = hab['state']; @@ -386,7 +396,7 @@ test('multisig', async function run() { endRoleRes = await client2 .identifiers() .addEndRole('multisig', rpyrole, rpyeid, rpystamp); - op2 = await endRoleRes.op(); + const endRole2 = await endRoleRes.op(); rpy = endRoleRes.serder; sigs = endRoleRes.sigs; @@ -435,7 +445,7 @@ test('multisig', async function run() { endRoleRes = await client3 .identifiers() .addEndRole('multisig', rpyrole2, rpyeid2, rpystamp2); - op3 = await endRoleRes.op(); + const endRole3 = await endRoleRes.op(); rpy = endRoleRes.serder; sigs = endRoleRes.sigs; hab = await client3.identifiers().get('multisig'); @@ -467,15 +477,17 @@ test('multisig', async function run() { ); // Check for completion - op1 = await waitOperation(client1, op1); - op2 = await waitOperation(client2, op2); - op3 = await waitOperation(client3, op3); + await waitOperation(client1, endRole1); + await waitOperation(client2, endRole2); + await waitOperation(client3, endRole3); console.log(`End role authorization for agent ${eid1}completed!`); // Holder resolve multisig OOBI const oobimultisig = await client1.oobis().get('multisig', 'agent'); - op4 = await client4.oobis().resolve(oobimultisig.oobis[0], 'multisig'); - op4 = await waitOperation(client4, op4); + const oobiOp4 = await client4 + .oobis() + .resolve(oobimultisig.oobis[0], 'multisig'); + await waitOperation(client4, oobiOp4); console.log(`Holder resolved multisig OOBI`); // MultiSig Interaction @@ -487,7 +499,7 @@ test('multisig', async function run() { d: 'EBgew7O4yp8SBle0FU-wwN3GtnaroI0BQfBGAj33QiIG', }; let eventResponse1 = await client1.identifiers().interact('multisig', data); - op1 = await eventResponse1.op(); + const gOp1 = await eventResponse1.op(); serder = eventResponse1.serder; sigs = eventResponse1.sigs; sigers = sigs.map((sig) => new Siger({ qb64: sig })); @@ -529,7 +541,7 @@ test('multisig', async function run() { const multisigData = embeds1.ixn.a; icpResult2 = await client2.identifiers().interact('multisig', multisigData); - op2 = await icpResult2.op(); + const gOp2 = await icpResult2.op(); serder = icpResult2.serder; sigs = icpResult2.sigs; sigers = sigs.map((sig) => new Siger({ qb64: sig })); @@ -540,7 +552,10 @@ test('multisig', async function run() { ixn: [serder, atc], }; - smids = exn.a.smids; + if (!exn.a) { + throw new Error('exn.a is missing from the group interaction event'); + } + smids = (exn.a as { smids: string[] }).smids; recp = [aid1['state'], aid3['state']].map((state) => state['i']); await client2 @@ -571,7 +586,7 @@ test('multisig', async function run() { const interactData = ixn2.a; icpResult3 = await client3.identifiers().interact('multisig', interactData); - op3 = await icpResult3.op(); + const gOp3 = await icpResult3.op(); serder = icpResult3.serder; sigs = icpResult3.sigs; sigers = sigs.map((sig) => new Siger({ qb64: sig })); @@ -582,7 +597,7 @@ test('multisig', async function run() { ixn: [serder, atc], }; - smids = exn.a.smids; + smids = (exn.a as { smids: string[] }).smids; recp = [aid1['state'], aid2['state']].map((state) => state['i']); await client3 @@ -599,56 +614,55 @@ test('multisig', async function run() { console.log('Member3 joins interaction event, waiting for others...'); // Check for completion - op1 = await waitOperation(client1, op1); - op2 = await waitOperation(client2, op2); - op3 = await waitOperation(client3, op3); + await waitOperation(client1, gOp1); + await waitOperation(client2, gOp2); + await waitOperation(client3, gOp3); console.log('Multisig interaction completed!'); // Members agree out of band to rotate keys console.log('Members agree out of band to rotate keys'); icpResult1 = await client1.identifiers().rotate('member1'); - op1 = await icpResult1.op(); - op1 = await waitOperation(client1, op1); + const rotOp1 = await icpResult1.op(); + await waitOperation(client1, rotOp1); aid1 = await client1.identifiers().get('member1'); console.log('Member1 rotated keys'); icpResult2 = await client2.identifiers().rotate('member2'); - op2 = await icpResult2.op(); - op2 = await waitOperation(client2, op2); + const rotOp2 = await icpResult2.op(); + await waitOperation(client2, rotOp2); aid2 = await client2.identifiers().get('member2'); console.log('Member2 rotated keys'); icpResult3 = await client3.identifiers().rotate('member3'); - op3 = await icpResult3.op(); - op3 = await waitOperation(client3, op3); + const rotOp3 = await icpResult3.op(); + await waitOperation(client3, rotOp3); aid3 = await client3.identifiers().get('member3'); console.log('Member3 rotated keys'); // Update new key states - op1 = await client1.keyStates().query(aid2.prefix, '1'); - op1 = await waitOperation(client1, op1); - const aid2State = op1['response'] as KeyState; - op1 = await client1.keyStates().query(aid3.prefix, '1'); - op1 = await waitOperation(client1, op1); - const aid3State = op1['response'] as KeyState; - - op2 = await client2.keyStates().query(aid3.prefix, '1'); - op2 = await waitOperation(client2, op2); - op2 = await client2.keyStates().query(aid1.prefix, '1'); - op2 = await waitOperation(client2, op2); - const aid1State = op2['response'] as KeyState; - - op3 = await client3.keyStates().query(aid1.prefix, '1'); - op3 = await waitOperation(client3, op3); - op3 = await client3.keyStates().query(aid2.prefix, '1'); - op3 = await waitOperation(client3, op3); - - op4 = await client4.keyStates().query(aid1.prefix, '1'); - op4 = await waitOperation(client4, op4); - op4 = await client4.keyStates().query(aid2.prefix, '1'); - op4 = await waitOperation(client4, op4); - op4 = await client4.keyStates().query(aid3.prefix, '1'); - op4 = await waitOperation(client4, op4); - + let qOp1 = await client1.keyStates().query(aid2.prefix, '1'); + qOp1 = await waitOperation(client1, qOp1); + const aid2State = qOp1['response']; + qOp1 = await client1.keyStates().query(aid3.prefix, '1'); + qOp1 = await waitOperation(client1, qOp1); + const aid3State = qOp1['response']; + + let qOp2 = await client2.keyStates().query(aid3.prefix, '1'); + qOp2 = await waitOperation(client2, qOp2); + qOp2 = await client2.keyStates().query(aid1.prefix, '1'); + qOp2 = await waitOperation(client2, qOp2); + const aid1State = qOp2['response']; + + let qOp3 = await client3.keyStates().query(aid1.prefix, '1'); + qOp3 = await waitOperation(client3, qOp3); + qOp3 = await client3.keyStates().query(aid2.prefix, '1'); + qOp3 = await waitOperation(client3, qOp3); + + let qOp4 = await client4.keyStates().query(aid1.prefix, '1'); + qOp4 = await waitOperation(client4, qOp4); + qOp4 = await client4.keyStates().query(aid2.prefix, '1'); + qOp4 = await waitOperation(client4, qOp4); + qOp4 = await client4.keyStates().query(aid3.prefix, '1'); + qOp4 = await waitOperation(client4, qOp4); rstates = [aid1State, aid2State, aid3State]; states = rstates; @@ -658,7 +672,7 @@ test('multisig', async function run() { eventResponse1 = await client1 .identifiers() .rotate('multisig', { states: states, rstates: rstates }); - op1 = await eventResponse1.op(); + const groupRotOp1 = await eventResponse1.op(); serder = eventResponse1.serder; sigs = eventResponse1.sigs; sigers = sigs.map((sig) => new Siger({ qb64: sig })); @@ -699,7 +713,7 @@ test('multisig', async function run() { icpResult2 = await client2 .identifiers() .rotate('multisig', { states: states, rstates: rstates }); - op2 = await icpResult2.op(); + const groupRotOp2 = await icpResult2.op(); serder = icpResult2.serder; sigs = icpResult2.sigs; sigers = sigs.map((sig) => new Siger({ qb64: sig })); @@ -736,7 +750,7 @@ test('multisig', async function run() { icpResult3 = await client3 .identifiers() .rotate('multisig', { states: states, rstates: rstates }); - op3 = await icpResult3.op(); + const groupRotOp3 = await icpResult3.op(); serder = icpResult3.serder; sigs = icpResult3.sigs; sigers = sigs.map((sig) => new Siger({ qb64: sig })); @@ -764,9 +778,9 @@ test('multisig', async function run() { console.log('Member3 joins rotation event, waiting for others...'); // Check for completion - op1 = await waitOperation(client1, op1); - op2 = await waitOperation(client2, op2); - op3 = await waitOperation(client3, op3); + await waitOperation(client1, groupRotOp1); + await waitOperation(client2, groupRotOp2); + await waitOperation(client3, groupRotOp3); console.log('Multisig rotation completed!'); hab = await client1.identifiers().get('multisig'); @@ -784,7 +798,7 @@ test('multisig', async function run() { registryName: 'vLEI Registry', nonce: 'AHSNDV3ABI6U8OIgKaj3aky91ZpNL54I5_7-qwtC6q2s', }); - op1 = await vcpRes1.op(); + const regOp1 = await vcpRes1.op(); serder = vcpRes1.regser; const regk = serder.pre; let anc = vcpRes1.serder; @@ -826,7 +840,7 @@ test('multisig', async function run() { registryName: 'vLEI Registry', nonce: 'AHSNDV3ABI6U8OIgKaj3aky91ZpNL54I5_7-qwtC6q2s', }); - op2 = await vcpRes2.op(); + const regOp2 = await vcpRes2.op(); serder = vcpRes2.regser; anc = vcpRes2.serder; sigs = vcpRes2.sigs; @@ -867,7 +881,7 @@ test('multisig', async function run() { registryName: 'vLEI Registry', nonce: 'AHSNDV3ABI6U8OIgKaj3aky91ZpNL54I5_7-qwtC6q2s', }); - op3 = await vcpRes3.op(); + const regOp3 = await vcpRes3.op(); serder = vcpRes3.regser; anc = vcpRes3.serder; sigs = vcpRes3.sigs; @@ -895,9 +909,9 @@ test('multisig', async function run() { ); // Done - op1 = await waitOperation(client1, op1); - op2 = await waitOperation(client2, op2); - op3 = await waitOperation(client3, op3); + await waitOperation(client1, regOp1); + await waitOperation(client2, regOp2); + await waitOperation(client3, regOp3); console.log('Multisig create registry completed!'); //Create Credential @@ -918,7 +932,7 @@ test('multisig', async function run() { ...vcdata, }, }); - op1 = credRes.op; + const credOp1 = credRes.op; await multisigIssue(client1, 'member1', 'multisig', credRes); console.log( @@ -940,7 +954,7 @@ test('multisig', async function run() { .credentials() .issue('multisig', acdc as CredentialData); - op2 = credRes2.op; + const credOp2 = credRes2.op; await multisigIssue(client2, 'member2', 'multisig', credRes2); console.log('Member2 joins credential create event, waiting for others...'); @@ -957,27 +971,27 @@ test('multisig', async function run() { .credentials() .issue('multisig', issExn2.e.acdc as CredentialData); - op3 = credRes3.op; + const credOp3 = credRes3.op; await multisigIssue(client3, 'member3', 'multisig', credRes3); console.log('Member3 joins credential create event, waiting for others...'); // Check completion - op1 = await waitOperation(client1, op1); - op2 = await waitOperation(client2, op2); - op3 = await waitOperation(client3, op3); + await waitOperation(client1, credOp1); + await waitOperation(client2, credOp2); + await waitOperation(client3, credOp3); console.log('Multisig create credential completed!'); const m = await client1.identifiers().get('multisig'); // Update states - op1 = await client1.keyStates().query(m.prefix, '4'); - op1 = await waitOperation(client1, op1); - op2 = await client2.keyStates().query(m.prefix, '4'); - op2 = await waitOperation(client2, op2); - op3 = await client3.keyStates().query(m.prefix, '4'); - op3 = await waitOperation(client3, op3); - op4 = await client4.keyStates().query(m.prefix, '4'); - op4 = await waitOperation(client4, op4); + qOp1 = await client1.keyStates().query(m.prefix, '4'); + await waitOperation(client1, qOp1); + qOp2 = await client2.keyStates().query(m.prefix, '4'); + await waitOperation(client2, qOp2); + qOp3 = await client3.keyStates().query(m.prefix, '4'); + await waitOperation(client3, qOp3); + qOp4 = await client4.keyStates().query(m.prefix, '4'); + await waitOperation(client4, qOp4); // IPEX grant message console.log('Starting grant message'); @@ -992,7 +1006,7 @@ test('multisig', async function run() { datetime: stamp, }); - op1 = await client1 + const exOp1 = await client1 .ipex() .submitGrant('multisig', grant, gsigs, end, [holder]); @@ -1039,7 +1053,7 @@ test('multisig', async function run() { datetime: stamp, }); - op2 = await client2 + const exOp2 = await client2 .ipex() .submitGrant('multisig', grant2, gsigs2, end2, [holder]); @@ -1080,7 +1094,7 @@ test('multisig', async function run() { datetime: stamp, }); - op3 = await client3 + const exOp3 = await client3 .ipex() .submitGrant('multisig', grant3, gsigs3, end3, [holder]); @@ -1120,15 +1134,15 @@ test('multisig', async function run() { recipient: m['prefix'], }); - op4 = await client4 + const exOp4 = await client4 .ipex() .submitAdmit('holder', admit, asigs, aend, [m['prefix']]); await Promise.all([ - waitOperation(client1, op1), - waitOperation(client2, op2), - waitOperation(client3, op3), - waitOperation(client4, op4), + waitOperation(client1, exOp1), + waitOperation(client2, exOp2), + waitOperation(client3, exOp3), + waitOperation(client4, exOp4), ]); console.log('Holder creates and sends admit message'); @@ -1146,7 +1160,7 @@ test('multisig', async function run() { const revokeRes = await client1 .credentials() .revoke('multisig', credentialSaid, REVTIME); - op1 = revokeRes.op; + const revOp1 = revokeRes.op; await multisigRevoke( client1, @@ -1171,7 +1185,8 @@ test('multisig', async function run() { .credentials() .revoke('multisig', credentialSaid, REVTIME); - op2 = revokeRes2.op; + const revOp2 = revokeRes2.op; + await multisigRevoke( client2, 'member2', @@ -1192,7 +1207,7 @@ test('multisig', async function run() { .credentials() .revoke('multisig', credentialSaid, REVTIME); - op3 = revokeRes3.op; + const revOp3 = revokeRes3.op; await multisigRevoke( client3, @@ -1204,9 +1219,9 @@ test('multisig', async function run() { console.log('Member3 joins credential revoke event, waiting for others...'); // Check completion - op1 = await waitOperation(client1, op1); - op2 = await waitOperation(client2, op2); - op3 = await waitOperation(client3, op3); + await waitOperation(client1, revOp1); + await waitOperation(client2, revOp2); + await waitOperation(client3, revOp3); console.log('Multisig credential revocation completed!'); }, 400000); diff --git a/test-integration/randy.test.ts b/test-integration/randy.test.ts index 5d900e71..005db3a8 100644 --- a/test-integration/randy.test.ts +++ b/test-integration/randy.test.ts @@ -14,6 +14,7 @@ test('randy', async () => { .create('aid1', { algo: signify.Algos.randy }); let op = await waitOperation(client1, await icpResult.op()); assert.equal(op['done'], true); + assert.ok('response' in op); let aid = op['response']; const icp = new signify.Serder(aid); assert.equal(icp.verfers.length, 1); @@ -23,29 +24,29 @@ test('randy', async () => { let aids = await client1.identifiers().list(); assert.equal(aids.aids.length, 1); - aid = aids.aids[0]; - assert.equal(aid.name, 'aid1'); - assert.equal(aid.prefix, icp.pre); + let aid1_state = aids.aids[0]; + assert.equal(aid1_state.name, 'aid1'); + assert.equal(aid1_state.prefix, icp.pre); icpResult = await client1.identifiers().interact('aid1', [icp.pre]); - op = await waitOperation(client1, await icpResult.op()); - let ked = op['response']; + let doneOp = await waitOperation(client1, await icpResult.op()); + let ked = doneOp['response']; const ixn = new signify.Serder(ked); assert.equal(ixn.sad['s'], '1'); assert.deepEqual([...ixn.sad['a']], [icp.pre]); aids = await client1.identifiers().list(); assert.equal(aids.aids.length, 1); - aid = aids.aids[0]; + aid1_state = aids.aids[0]; const events = client1.keyEvents(); - let log = await events.get(aid['prefix']); + let log = await events.get(aid1_state.prefix); assert.equal(log.length, 2); icpResult = await client1.identifiers().rotate('aid1'); - op = await waitOperation(client1, await icpResult.op()); - ked = op['response']; - const rot = new signify.Serder(ked); + let rotOp = await waitOperation(client1, await icpResult.op()); + let rotKed = rotOp['response']; + const rot = new signify.Serder(rotKed); assert.equal(rot.sad['s'], '2'); assert.equal(rot.verfers.length, 1); assert.equal(rot.digers.length, 1); @@ -56,7 +57,7 @@ test('randy', async () => { rot.verfers[0].qb64b ); assert.equal(dig.qb64, icp.digers[0].qb64); - log = await events.get(aid['prefix']); + log = await events.get(aid1_state['prefix']); assert.equal(log.length, 3); await assertOperations(client1); diff --git a/test-integration/salty.test.ts b/test-integration/salty.test.ts index a560b9aa..7cae223e 100644 --- a/test-integration/salty.test.ts +++ b/test-integration/salty.test.ts @@ -105,8 +105,8 @@ test('salty', async () => { icpResult = await client1.identifiers().rotate('aid1'); op = await waitOperation(client1, await icpResult.op()); - let ked = op['response']; - const rot = new signify.Serder(ked); + let rotKed = op['response']; + const rot = new signify.Serder(rotKed); assert.equal(rot.sad['d'], 'EBQABdRgaxJONrSLcgrdtbASflkvLxJkiDO0H-XmuhGg'); assert.equal(rot.sad['s'], '1'); assert.equal(rot.verfers.length, 1); @@ -122,8 +122,8 @@ test('salty', async () => { icpResult = await client1.identifiers().interact('aid1', [icp.pre]); op = await waitOperation(client1, await icpResult.op()); - ked = op['response']; - const ixn = new signify.Serder(ked); + let ixnKed = op['response']; + const ixn = new signify.Serder(ixnKed); assert.equal(ixn.sad['d'], 'ENsmRAg_oM7Hl1S-GTRMA7s4y760lQMjzl0aqOQ2iTce'); assert.equal(ixn.sad['s'], '2'); assert.deepEqual([...ixn.sad['a']], [icp.pre]); diff --git a/test-integration/singlesig-ixn.test.ts b/test-integration/singlesig-ixn.test.ts index 5d06966d..cdc4fc3f 100644 --- a/test-integration/singlesig-ixn.test.ts +++ b/test-integration/singlesig-ixn.test.ts @@ -1,4 +1,4 @@ -import { EventResult, SignifyClient, KeyState } from 'signify-ts'; +import { SignifyClient } from 'signify-ts'; import { assertOperations, getOrCreateClients, @@ -40,29 +40,21 @@ describe('singlesig-ixn', () => { }); test('ixn1', async () => { // local keystate before ixn - const keystate0: KeyState = ( - await client1.keyStates().get(name1_id) - ).at(0)!; + const keystate0 = (await client1.keyStates().get(name1_id)).at(0)!; expect(keystate0).not.toBeNull(); // ixn - const result: EventResult = await client1 - .identifiers() - .interact('name1', {}); + const result = await client1.identifiers().interact('name1', {}); await waitOperation(client1, await result.op()); // local keystate after ixn - const keystate1: KeyState = ( - await client1.keyStates().get(name1_id) - ).at(0)!; + const keystate1 = (await client1.keyStates().get(name1_id)).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 = ( - await client2.keyStates().get(contact1_id) - ).at(0)!; + const keystate2 = (await client2.keyStates().get(contact1_id)).at(0)!; // remote keystate is one behind assert.equal(parseInt(keystate2.s), parseInt(keystate1.s) - 1); @@ -71,7 +63,7 @@ describe('singlesig-ixn', () => { .keyStates() .query(contact1_id, keystate1.s, undefined); op = await waitOperation(client2, op); - const keystate3: KeyState = op.response as KeyState; + const keystate3 = 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 8f73adc9..8e0a66b2 100644 --- a/test-integration/singlesig-rot.test.ts +++ b/test-integration/singlesig-rot.test.ts @@ -1,10 +1,5 @@ import { afterAll, assert, beforeAll, describe, expect, test } from 'vitest'; -import { - EventResult, - RotateIdentifierArgs, - SignifyClient, - KeyState, -} from 'signify-ts'; +import { EventResult, RotateIdentifierArgs, SignifyClient } from 'signify-ts'; import { assertOperations, getOrCreateClients, @@ -45,9 +40,7 @@ describe('singlesig-rot', () => { }); test('rot1', async () => { // local keystate before rot - const keystate0: KeyState = ( - await client1.keyStates().get(name1_id) - ).at(0)!; + const keystate0 = (await client1.keyStates().get(name1_id)).at(0)!; expect(keystate0).not.toBeNull(); assert.strictEqual(keystate0.k.length, 1); assert.strictEqual(keystate0.n.length, 1); @@ -60,9 +53,7 @@ describe('singlesig-rot', () => { await waitOperation(client1, await result.op()); // local keystate after rot - const keystate1: KeyState = ( - await client1.keyStates().get(name1_id) - ).at(0)!; + const keystate1 = (await client1.keyStates().get(name1_id)).at(0)!; expect(parseInt(keystate1.s)).toBeGreaterThan(0); // sequence has incremented assert.equal(parseInt(keystate1.s), parseInt(keystate0.s) + 1); @@ -72,9 +63,7 @@ describe('singlesig-rot', () => { expect(keystate1.n[0]).not.toEqual(keystate0.n[0]); // remote keystate after rot - const keystate2: KeyState = ( - await client2.keyStates().get(contact1_id) - ).at(0)!; + const keystate2 = (await client2.keyStates().get(contact1_id)).at(0)!; // remote keystate is one behind assert.equal(parseInt(keystate2.s), parseInt(keystate1.s) - 1); @@ -83,7 +72,7 @@ describe('singlesig-rot', () => { .keyStates() .query(contact1_id, keystate1.s, undefined); op = await waitOperation(client2, op); - const keystate3: KeyState = op.response as KeyState; + const keystate3 = 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/singlesig-vlei-issuance.test.ts b/test-integration/singlesig-vlei-issuance.test.ts index a9e9d7e4..83d3bf67 100644 --- a/test-integration/singlesig-vlei-issuance.test.ts +++ b/test-integration/singlesig-vlei-issuance.test.ts @@ -511,7 +511,7 @@ async function sendGrantMessage( let op = await senderClient .ipex() .submitGrant(senderAid.name, grant, gsigs, gend, [recipientAid.prefix]); - op = await waitOperation(senderClient, op); + await waitOperation(senderClient, op); } async function sendAdmitMessage( @@ -537,7 +537,7 @@ async function sendAdmitMessage( let op = await senderClient .ipex() .submitAdmit(senderAid.name, admit, sigs, aend, [recipientAid.prefix]); - op = await waitOperation(senderClient, op); + await waitOperation(senderClient, op); await markAndRemoveNotification(senderClient, grantNotification); } diff --git a/test-integration/utils/test-util.ts b/test-integration/utils/test-util.ts index ba30ed5c..e28dbd1f 100644 --- a/test-integration/utils/test-util.ts +++ b/test-integration/utils/test-util.ts @@ -2,6 +2,20 @@ import signify, { CreateIdentiferArgs, EventResult, Operation, + OOBIOperation, + QueryOperation, + EndRoleOperation, + WitnessOperation, + DelegationOperation, + RegistryOperation, + LocSchemeOperation, + ChallengeOperation, + ExchangeOperation, + SubmitOperation, + DoneOperation, + CredentialOperation, + GroupOperation, + DelegatorOperation, randomPasscode, ready, Salter, @@ -9,6 +23,20 @@ import signify, { Tier, HabState, ExternalModule, + CompletedOOBIOperation, + CompletedQueryOperation, + CompletedEndRoleOperation, + CompletedChallengeOperation, + CompletedWitnessOperation, + CompletedExchangeOperation, + CompletedLocSchemeOperation, + CompletedRegistryOperation, + CompletedDelegationOperation, + CompletedDelegatorOperation, + CompletedGroupOperation, + CompletedCredentialOperation, + CompletedDoneOperation, + CompletedSubmitOperation, } from 'signify-ts'; import { RetryOptions, retry } from './retry.ts'; import assert from 'assert'; @@ -248,9 +276,9 @@ export async function getOrCreateContact( return contact.id; } } - let op = await client.oobis().resolve(oobi, name); - op = await waitOperation(client, op); - const response = op.response as { i: string }; + const op: OOBIOperation = await client.oobis().resolve(oobi, name); + const completed_op = await waitOperation(client, op); + const response = completed_op.response; return response.i; } @@ -272,7 +300,7 @@ export async function getOrCreateIdentifier( let id: any = undefined; try { const identfier = await client.identifiers().get(name); - // console.log("identifiers.get", identfier); + // console.log('identifiers.get', identfier); id = identfier.prefix; } catch { const env = resolveEnvironment(); @@ -285,7 +313,7 @@ export async function getOrCreateIdentifier( .create(name, kargs); let op = await result.op(); op = await waitOperation(client, op); - // console.log("identifiers.create", op); + // console.log('identifiers.create', op); id = op.response.i; } const eid = client.agent?.pre!; @@ -393,11 +421,8 @@ export async function warnNotifications( expect(count).toBeGreaterThan(0); // replace warnNotifications with assertNotifications } -async function deleteOperations( - client: SignifyClient, - op: Operation -) { - if (op.metadata?.depends) { +async function deleteOperations(client: SignifyClient, op: Operation) { + if (op.metadata && 'depends' in op.metadata && op.metadata.depends) { await deleteOperations(client, op.metadata.depends); } @@ -512,11 +537,86 @@ export async function waitForNotifications( * Poll for operation to become completed. * Removes completed operation */ -export async function waitOperation( +export async function waitOperation( + client: SignifyClient, + op: OOBIOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: QueryOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: EndRoleOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: WitnessOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: DelegationOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: RegistryOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: LocSchemeOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: ChallengeOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: ExchangeOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: SubmitOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: DoneOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: CredentialOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: GroupOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: DelegatorOperation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( + client: SignifyClient, + op: Operation | string, + signal?: AbortSignal +): Promise; +export async function waitOperation( client: SignifyClient, - op: Operation | string, + op: Operation | string, signal?: AbortSignal -): Promise> { +): Promise { if (typeof op === 'string') { op = await client.operations().get(op); } diff --git a/test/app/coring.test.ts b/test/app/coring.test.ts index 53be7043..41eeed74 100644 --- a/test/app/coring.test.ts +++ b/test/app/coring.test.ts @@ -5,11 +5,13 @@ import { randomNonce, Operations, OperationsDeps, + Operation, } from '../../src/keri/app/coring.ts'; import { SignifyClient } from '../../src/keri/app/clienting.ts'; import { Tier } from '../../src/keri/core/salter.ts'; import { randomUUID } from 'node:crypto'; import { createMockFetch } from './test-utils.ts'; +import { RegistryOperation } from '../../src/keri/core/keyState.ts'; const url = 'http://127.0.0.1:3901'; const boot_url = 'http://127.0.0.1:3903'; @@ -224,7 +226,7 @@ describe('Operations', () => { }) ); - const op = { name, done: true }; + const op: Operation = { name, done: true, response: {} }; const result = await client.operations().wait(op); assert.equal(client.fetch.mock.calls.length, 0); assert.equal(op, result); @@ -238,7 +240,7 @@ describe('Operations', () => { }) ); - const op = { name, done: false }; + const op: Operation = { name, done: false }; await client.operations().wait(op); assert.equal(client.fetch.mock.calls.length, 1); }); @@ -257,7 +259,7 @@ describe('Operations', () => { }) ); - const op = { name, done: false }; + const op: Operation = { name, done: false }; await client.operations().wait(op, { maxSleep: 10 }); assert.equal(client.fetch.mock.calls.length, 2); }); @@ -271,7 +273,7 @@ describe('Operations', () => { }) ); - const op = { name, done: false }; + const op: Operation = { name, done: false }; const controller = new AbortController(); const promise = client @@ -290,11 +292,25 @@ describe('Operations', () => { it('returns when child operation is also done', async () => { const name = randomUUID(); const nestedName = randomUUID(); - const depends = { name: nestedName, done: false }; - const op = { name, done: false, depends }; + const depends: Operation = { name: nestedName, done: false }; + const op: RegistryOperation = { + name, + done: false, + metadata: { + pre: 'prefix', + anchor: { pre: 'prefix', sn: 0, d: 'd' }, + depends, + }, + }; + + client.fetch.mockResolvedValueOnce( + new Response(JSON.stringify({ ...depends, done: false }), { + status: 200, + }) + ); client.fetch.mockResolvedValueOnce( - new Response(JSON.stringify({ ...op, done: false }), { + new Response(JSON.stringify({ ...depends, done: true }), { status: 200, }) ); @@ -303,7 +319,10 @@ describe('Operations', () => { new Response( JSON.stringify({ ...op, - depends: { ...depends, done: true }, + metadata: { + ...op.metadata, + depends: { ...depends, done: true }, + }, }), { status: 200, @@ -316,7 +335,10 @@ describe('Operations', () => { JSON.stringify({ ...op, done: true, - depends: { ...depends, done: true }, + metadata: { + ...op.metadata, + depends: { ...depends, done: true }, + }, }), { status: 200, @@ -325,7 +347,7 @@ describe('Operations', () => { ); await client.operations().wait(op, { maxSleep: 10 }); - assert.equal(client.fetch.mock.calls.length, 3); + assert.equal(client.fetch.mock.calls.length, 4); }); }); });