diff --git a/apps/shared/src/events/credentialEvents.ts b/apps/shared/src/events/credentialEvents.ts index 32ed92aaffc305cd5011a7be238647b62f3fb62f..5fbe8aa493f4ba9e0683224a9bf8ab6d1d0f4827 100644 --- a/apps/shared/src/events/credentialEvents.ts +++ b/apps/shared/src/events/credentialEvents.ts @@ -7,11 +7,11 @@ import { import { BaseEvent } from './baseEvents.js'; -export type EventDidcommAnonCredsCredentialsGetAllInput = BaseEventInput; -export class EventDidcommAnonCredsCredentialsGetAll extends BaseEvent< +export type EventAnonCredsCredentialsGetAllInput = BaseEventInput; +export class EventAnonCredsCredentialsGetAll extends BaseEvent< Array<CredentialExchangeRecord> > { - public static token = 'didcomm.anoncreds.credentials.getAll'; + public static token = 'anoncreds.credentials.getAll'; public get instance() { return this.data.map((d) => @@ -19,8 +19,8 @@ export class EventDidcommAnonCredsCredentialsGetAll extends BaseEvent< ); } - public static fromEvent(e: EventDidcommAnonCredsCredentialsGetAll) { - return new EventDidcommAnonCredsCredentialsGetAll( + public static fromEvent(e: EventAnonCredsCredentialsGetAll) { + return new EventAnonCredsCredentialsGetAll( e.data, e.tenantId, e.id, @@ -30,11 +30,11 @@ export class EventDidcommAnonCredsCredentialsGetAll extends BaseEvent< } } -export type EventDidcommAnonCredsCredentialsGetByIdInput = BaseEventInput<{ +export type EventAnonCredsCredentialsGetByIdInput = BaseEventInput<{ credentialRecordId: string; }>; -export class EventDidcommAnonCredsCredentialsGetById extends BaseEvent<CredentialExchangeRecord | null> { - public static token = 'didcomm.anoncreds.credentials.getById'; +export class EventAnonCredsCredentialsGetById extends BaseEvent<CredentialExchangeRecord | null> { + public static token = 'anoncreds.credentials.getById'; public get instance() { return this.data @@ -42,8 +42,8 @@ export class EventDidcommAnonCredsCredentialsGetById extends BaseEvent<Credentia : null; } - public static fromEvent(e: EventDidcommAnonCredsCredentialsGetById) { - return new EventDidcommAnonCredsCredentialsGetById( + public static fromEvent(e: EventAnonCredsCredentialsGetById) { + return new EventAnonCredsCredentialsGetById( e.data, e.tenantId, e.id, @@ -97,3 +97,20 @@ export class EventDidcommAnonCredsCredentialsOfferToSelf extends BaseEvent<Crede ); } } + +export type EventAnonCredsCredentialsDeleteByIdInput = BaseEventInput<{ + credentialRecordId: string; +}>; +export class EventAnonCredsCredentialsDeleteById extends BaseEvent { + public static token = 'anoncreds.credentials.offerToSelf.deleteById'; + + public static fromEvent(e: EventAnonCredsCredentialsDeleteById) { + return new EventAnonCredsCredentialsDeleteById( + e.data, + e.tenantId, + e.id, + e.type, + e.timestamp, + ); + } +} diff --git a/apps/shared/src/events/credentialOfferEvents.ts b/apps/shared/src/events/credentialOfferEvents.ts index da38971397df39dea1925d48c75c9fcf5e65e5e3..0735939c6bc3d82685beb704be49b9ef5d156095 100644 --- a/apps/shared/src/events/credentialOfferEvents.ts +++ b/apps/shared/src/events/credentialOfferEvents.ts @@ -1,5 +1,4 @@ import type { BaseEventInput } from './baseEvents.js'; -import type { AnonCredsCredentialOffer } from '@aries-framework/anoncreds'; import { CredentialExchangeRecord, @@ -11,7 +10,7 @@ import { BaseEvent } from './baseEvents.js'; export type EventAnonCredsCredentialOfferGetAllInput = BaseEventInput; export class EventAnonCredsCredentialOfferGetAll extends BaseEvent< - Array<AnonCredsCredentialOffer> + Array<CredentialExchangeRecord> > { public static token = 'anoncreds.credentialOffers.getAll'; @@ -36,7 +35,7 @@ export type EventAnonCredsCredentialOfferGetByIdInput = BaseEventInput & { credentialOfferId: string; }; -export class EventAnonCredsCredentialOfferGetById extends BaseEvent<AnonCredsCredentialOffer | null> { +export class EventAnonCredsCredentialOfferGetById extends BaseEvent<CredentialExchangeRecord | null> { public static token = 'anoncreds.credentialOffers.getById'; public get instance() { diff --git a/apps/shared/src/events/credentialRequestEvents.ts b/apps/shared/src/events/credentialRequestEvents.ts index f143033cf1e12a4cb4744e401e7062e03a60c404..4039e655ee09cb08db7a23f8bc617f72fe9e487a 100644 --- a/apps/shared/src/events/credentialRequestEvents.ts +++ b/apps/shared/src/events/credentialRequestEvents.ts @@ -1,5 +1,4 @@ import type { BaseEventInput } from './baseEvents.js'; -import type { AnonCredsCredentialRequest } from '@aries-framework/anoncreds'; import { CredentialExchangeRecord, @@ -11,7 +10,7 @@ import { BaseEvent } from './baseEvents.js'; export type EventAnonCredsCredentialRequestGetAllInput = BaseEventInput; export class EventAnonCredsCredentialRequestGetAll extends BaseEvent< - Array<AnonCredsCredentialRequest> + Array<CredentialExchangeRecord> > { public static token = 'anoncreds.credentialRequests.getAll'; @@ -36,7 +35,7 @@ export type EventAnonCredsCredentialRequestGetByIdInput = BaseEventInput & { credentialRequestId: string; }; -export class EventAnonCredsCredentialRequestGetById extends BaseEvent<AnonCredsCredentialRequest | null> { +export class EventAnonCredsCredentialRequestGetById extends BaseEvent<CredentialExchangeRecord | null> { public static token = 'anoncreds.credentialRequests.getById'; public get instance() { diff --git a/apps/ssi-abstraction/jest.config.js b/apps/ssi-abstraction/jest.config.js index 5ece9fcccb7e35c47222b8cd0db33663d595c5e9..b8e668f1276a964bf64564fc37c8a688e45a9a41 100644 --- a/apps/ssi-abstraction/jest.config.js +++ b/apps/ssi-abstraction/jest.config.js @@ -17,6 +17,7 @@ export default { }, ], }, + testPathIgnorePatterns: ['<rootDir>/dist'], extensionsToTreatAsEsm: ['.ts'], moduleNameMapper: { // ESM modules require `.js` extension to be specified, but Jest doesn't work with them diff --git a/apps/ssi-abstraction/src/agent/anoncredsCredentials/__tests__/anoncredsCredentials.controller.spec.ts b/apps/ssi-abstraction/src/agent/anoncredsCredentials/__tests__/anoncredsCredentials.controller.spec.ts index 4652f579ba2f4f2a7134aa3c9a0a3696c054ef24..89c6c841b045c0ce88a0d26c263eb88c79cf57d0 100644 --- a/apps/ssi-abstraction/src/agent/anoncredsCredentials/__tests__/anoncredsCredentials.controller.spec.ts +++ b/apps/ssi-abstraction/src/agent/anoncredsCredentials/__tests__/anoncredsCredentials.controller.spec.ts @@ -24,75 +24,101 @@ describe('AnonCredsCredentialsController', () => { credentialsController = moduleRef.get(AnonCredsCredentialsController); }); - describe('get all', () => { - it('should get all the credential records of the agent', async () => { - const result: Array<CredentialExchangeRecord> = []; - jest.spyOn(credentialsService, 'getAll').mockResolvedValue(result); + it('get all', async () => { + const result: Array<CredentialExchangeRecord> = []; + jest.spyOn(credentialsService, 'getAll').mockResolvedValue(result); - const event = await credentialsController.getAll({ - tenantId: 'some-id', - }); + const event = await credentialsController.getAll({ + tenantId: 'some-id', + }); + + expect(event.data).toStrictEqual(result); + }); - expect(event.data).toStrictEqual(result); + it('get all offers', async () => { + const result: Array<CredentialExchangeRecord> = []; + jest.spyOn(credentialsService, 'getAllOffers').mockResolvedValue(result); + + const event = await credentialsController.getAllOffers({ + tenantId: 'some-id', }); + + expect(event.data).toStrictEqual(result); }); - describe('get by id', () => { - it('should get a credential record by id', async () => { - const result: CredentialExchangeRecord | null = null; - jest.spyOn(credentialsService, 'getById').mockResolvedValue(result); + it('get all requests', async () => { + const result: Array<CredentialExchangeRecord> = []; + jest.spyOn(credentialsService, 'getAllRequests').mockResolvedValue(result); - const event = await credentialsController.getById({ - tenantId: 'some-id', - credentialRecordId: 'some-id', - }); + const event = await credentialsController.getAllRequests({ + tenantId: 'some-id', + }); + + expect(event.data).toStrictEqual(result); + }); - expect(event.data).toStrictEqual(result); + it('get by id', async () => { + const result: CredentialExchangeRecord | null = null; + jest.spyOn(credentialsService, 'getById').mockResolvedValue(result); + + const event = await credentialsController.getById({ + tenantId: 'some-id', + credentialRecordId: 'some-id', }); + + expect(event.data).toStrictEqual(result); }); - describe('offer', () => { - it('should offer a credential', async () => { - const result: CredentialExchangeRecord = new CredentialExchangeRecord({ - state: CredentialState.Done, - threadId: 'some-id', - protocolVersion: 'v2', - }); - jest.spyOn(credentialsService, 'offer').mockResolvedValue(result); - - const event = await credentialsController.offer({ - tenantId: 'some-id', - connectionId: 'some-id', - credentialDefinitionId: 'some-id', - attributes: [ - { name: 'Name', value: 'Berend', mimeType: 'application/text' }, - { name: 'Age', value: '25' }, - ], - }); - - expect(event.data).toStrictEqual(result); + it('delete by id', async () => { + const result = {}; + jest.spyOn(credentialsService, 'deleteById').mockResolvedValue(result); + + const event = await credentialsController.deleteById({ + tenantId: 'some-id', + credentialRecordId: 'some-id-that-does-not-exist', }); + + expect(event.data).toStrictEqual(result); }); - describe('offer to self', () => { - it('should offer a credential to self', async () => { - const result: CredentialExchangeRecord = new CredentialExchangeRecord({ - state: CredentialState.Done, - threadId: 'some-id', - protocolVersion: 'v2', - }); - jest.spyOn(credentialsService, 'offerToSelf').mockResolvedValue(result); - - const event = await credentialsController.offerToSelf({ - tenantId: 'some-id', - credentialDefinitionId: 'some-id', - attributes: [ - { name: 'Name', value: 'Berend', mimeType: 'application/text' }, - { name: 'Age', value: '25' }, - ], - }); - - expect(event.data).toStrictEqual(result); + it('offer', async () => { + const result: CredentialExchangeRecord = new CredentialExchangeRecord({ + state: CredentialState.Done, + threadId: 'some-id', + protocolVersion: 'v2', + }); + jest.spyOn(credentialsService, 'offer').mockResolvedValue(result); + + const event = await credentialsController.offer({ + tenantId: 'some-id', + connectionId: 'some-id', + credentialDefinitionId: 'some-id', + attributes: [ + { name: 'Name', value: 'Berend', mimeType: 'application/text' }, + { name: 'Age', value: '25' }, + ], }); + + expect(event.data).toStrictEqual(result); + }); + + it('offer to self', async () => { + const result: CredentialExchangeRecord = new CredentialExchangeRecord({ + state: CredentialState.Done, + threadId: 'some-id', + protocolVersion: 'v2', + }); + jest.spyOn(credentialsService, 'offerToSelf').mockResolvedValue(result); + + const event = await credentialsController.offerToSelf({ + tenantId: 'some-id', + credentialDefinitionId: 'some-id', + attributes: [ + { name: 'Name', value: 'Berend', mimeType: 'application/text' }, + { name: 'Age', value: '25' }, + ], + }); + + expect(event.data).toStrictEqual(result); }); }); diff --git a/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.controller.ts b/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.controller.ts index 11a6d93ec55d88eb5ef91aab973f8d67c0c7e2ff..af6a9933d3a77ff8a817ff679369b593e05dc9d9 100644 --- a/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.controller.ts +++ b/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.controller.ts @@ -1,14 +1,20 @@ import { Controller } from '@nestjs/common'; import { MessagePattern } from '@nestjs/microservices'; import { + EventAnonCredsCredentialOfferGetById, + EventAnonCredsCredentialOfferGetByIdInput, + EventAnonCredsCredentialRequestGetById, + EventAnonCredsCredentialRequestGetByIdInput, + EventAnonCredsCredentialsDeleteById, + EventAnonCredsCredentialsDeleteByIdInput, EventAnonCredsCredentialsGetAll, EventAnonCredsCredentialsGetAllInput, EventAnonCredsCredentialsGetById, EventAnonCredsCredentialsGetByIdInput, EventDidcommAnonCredsCredentialsOffer, EventDidcommAnonCredsCredentialsOfferInput, - EventDidcommAnonCredsCredentialsOfferToSelfInput, EventDidcommAnonCredsCredentialsOfferToSelf, + EventDidcommAnonCredsCredentialsOfferToSelfInput } from '@ocm/shared'; import { AnonCredsCredentialsService } from './anoncredsCredentials.service.js'; @@ -37,6 +43,36 @@ export class AnonCredsCredentialsController { ); } + @MessagePattern(EventAnonCredsCredentialOfferGetById.token) + public async getOfferById( + options: EventAnonCredsCredentialOfferGetByIdInput, + ): Promise<EventAnonCredsCredentialOfferGetById> { + return new EventAnonCredsCredentialOfferGetById( + await this.credentialsService.getOfferById(options), + options.tenantId, + ); + } + + @MessagePattern(EventAnonCredsCredentialRequestGetById.token) + public async getRequestById( + options: EventAnonCredsCredentialRequestGetByIdInput, + ): Promise<EventAnonCredsCredentialRequestGetById> { + return new EventAnonCredsCredentialRequestGetById( + await this.credentialsService.getRequestById(options), + options.tenantId, + ); + } + + @MessagePattern(EventAnonCredsCredentialsDeleteById.token) + public async deleteById( + options: EventAnonCredsCredentialsDeleteByIdInput, + ): Promise<EventAnonCredsCredentialsDeleteById> { + return new EventAnonCredsCredentialsDeleteById( + await this.credentialsService.deleteById(options), + options.tenantId, + ); + } + @MessagePattern(EventDidcommAnonCredsCredentialsOffer.token) public async offer( options: EventDidcommAnonCredsCredentialsOfferInput, diff --git a/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.service.ts b/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.service.ts index 6cb0cb773aa0dea8f4390dc3ae1adf0935ee0c11..94617f16d8574e662cbbc55699b4e07aaa2f0a8a 100644 --- a/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.service.ts +++ b/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.service.ts @@ -1,15 +1,26 @@ +import type { CredentialExchangeRecord} from '@aries-framework/core'; import type { + EventAnonCredsCredentialOfferGetAll, + EventAnonCredsCredentialOfferGetAllInput, + EventAnonCredsCredentialOfferGetById, + EventAnonCredsCredentialOfferGetByIdInput, + EventAnonCredsCredentialRequestGetAll, + EventAnonCredsCredentialRequestGetAllInput, + EventAnonCredsCredentialRequestGetById, + EventAnonCredsCredentialRequestGetByIdInput, + EventAnonCredsCredentialsDeleteById, + EventAnonCredsCredentialsDeleteByIdInput, EventAnonCredsCredentialsGetAllInput, EventAnonCredsCredentialsGetByIdInput, + EventDidcommAnonCredsCredentialsOffer, EventDidcommAnonCredsCredentialsOfferInput, - EventDidcommAnonCredsCredentialsOfferToSelfInput, + EventDidcommAnonCredsCredentialsOfferToSelf, + EventDidcommAnonCredsCredentialsOfferToSelfInput } from '@ocm/shared'; -import { - AutoAcceptCredential, - type CredentialExchangeRecord, -} from '@aries-framework/core'; +import { AutoAcceptCredential, CredentialState } from '@aries-framework/core'; import { Injectable } from '@nestjs/common'; +import { logger } from '@ocm/shared'; import { MetadataTokens } from '../../common/constants.js'; import { WithTenantService } from '../withTenantService.js'; @@ -28,6 +39,48 @@ export class AnonCredsCredentialsService { ); } + public async getAllOffers({ + tenantId, + }: EventAnonCredsCredentialOfferGetAllInput): Promise< + EventAnonCredsCredentialOfferGetAll['data'] + > { + return this.withTenantService.invoke(tenantId, (t) => + t.credentials.findAllByQuery({ + $or: [ + { state: CredentialState.OfferSent }, + { state: CredentialState.OfferReceived }, + ], + }), + ); + } + + public async getAllRequests({ + tenantId, + }: EventAnonCredsCredentialRequestGetAllInput): Promise< + EventAnonCredsCredentialRequestGetAll['data'] + > { + return this.withTenantService.invoke(tenantId, (t) => + t.credentials.findAllByQuery({ + $or: [ + { state: CredentialState.RequestSent }, + { state: CredentialState.RequestReceived }, + ], + }), + ); + } + + public async deleteById({ + tenantId, + credentialRecordId, + }: EventAnonCredsCredentialsDeleteByIdInput): Promise< + EventAnonCredsCredentialsDeleteById['data'] + > { + return this.withTenantService.invoke(tenantId, async (t) => { + await t.credentials.deleteById(credentialRecordId); + return {}; + }); + } + public async getById({ tenantId, credentialRecordId, @@ -37,12 +90,60 @@ export class AnonCredsCredentialsService { ); } + public async getOfferById({ + tenantId, + credentialOfferId, + }: EventAnonCredsCredentialOfferGetByIdInput): Promise< + EventAnonCredsCredentialOfferGetById['data'] + > { + return this.withTenantService.invoke(tenantId, async (t) => { + const credential = await t.credentials.findById(credentialOfferId); + + if ( + credential && + credential.state !== CredentialState.OfferSent && + credential.state !== CredentialState.OfferReceived + ) { + logger.warn( + `Credential '${credentialOfferId}' does exist, but is not in offer state. Actual state: ${credential.state}`, + ); + } + + return credential; + }); + } + + public async getRequestById({ + tenantId, + credentialRequestId, + }: EventAnonCredsCredentialRequestGetByIdInput): Promise< + EventAnonCredsCredentialRequestGetById['data'] + > { + return this.withTenantService.invoke(tenantId, async (t) => { + const credential = await t.credentials.findById(credentialRequestId); + + if ( + credential && + credential.state !== CredentialState.RequestSent && + credential.state !== CredentialState.RequestReceived + ) { + logger.warn( + `Credential '${credentialRequestId}' does exist, but is not in a request state. Actual state: ${credential.state}`, + ); + } + + return credential; + }); + } + public async offer({ tenantId, connectionId, credentialDefinitionId, attributes, - }: EventDidcommAnonCredsCredentialsOfferInput): Promise<CredentialExchangeRecord> { + }: EventDidcommAnonCredsCredentialsOfferInput): Promise< + EventDidcommAnonCredsCredentialsOffer['data'] + > { return this.withTenantService.invoke(tenantId, (t) => t.credentials.offerCredential({ protocolVersion: 'v2', @@ -58,7 +159,9 @@ export class AnonCredsCredentialsService { tenantId, credentialDefinitionId, attributes, - }: EventDidcommAnonCredsCredentialsOfferToSelfInput): Promise<CredentialExchangeRecord> { + }: EventDidcommAnonCredsCredentialsOfferToSelfInput): Promise< + EventDidcommAnonCredsCredentialsOfferToSelf['data'] + > { return this.withTenantService.invoke(tenantId, async (t) => { const connections = await t.connections.getAll(); const connection = connections.find((c) => { diff --git a/apps/ssi-abstraction/test/anoncredsCredentials.e2e-spec.ts b/apps/ssi-abstraction/test/anoncredsCredentials.e2e-spec.ts index 12250e66b47bdff7786577932365182282c60236..f63159f50f727b2ec2f98b6f9e0cb2093bca529e 100644 --- a/apps/ssi-abstraction/test/anoncredsCredentials.e2e-spec.ts +++ b/apps/ssi-abstraction/test/anoncredsCredentials.e2e-spec.ts @@ -1,17 +1,31 @@ import type { INestApplication } from '@nestjs/common'; import type { ClientProxy } from '@nestjs/microservices'; import type { - EventDidcommAnonCredsCredentialsGetAllInput, - EventDidcommAnonCredsCredentialsGetByIdInput, + EventAnonCredsCredentialRequestGetAllInput, + EventAnonCredsCredentialsGetAllInput, + EventAnonCredsCredentialsGetByIdInput, EventDidcommAnonCredsCredentialsOfferToSelfInput, + EventAnonCredsCredentialOfferGetAllInput, + EventAnonCredsCredentialOfferGetByIdInput, + EventAnonCredsCredentialRequestGetByIdInput, + EventAnonCredsCredentialsDeleteByIdInput, } from '@ocm/shared'; -import { AutoAcceptCredential } from '@aries-framework/core'; +import { + AutoAcceptCredential, + CredentialExchangeRecord, +} from '@aries-framework/core'; import { ClientsModule, Transport } from '@nestjs/microservices'; import { Test } from '@nestjs/testing'; import { - EventDidcommAnonCredsCredentialsGetAll, - EventDidcommAnonCredsCredentialsGetById, + EventAnonCredsCredentialsDeleteById, + EventAnonCredsCredentialOfferGetAll, + EventAnonCredsCredentialOfferGetById, + EventAnonCredsCredentialRequestGetAll, + EventAnonCredsCredentialRequestGetById, + EventAnonCredsCredentialsGetAll, + EventAnonCredsCredentialsGetById, + EventAnonCredsProofsDeleteById, EventDidcommAnonCredsCredentialsOfferToSelf, } from '@ocm/shared'; import { firstValueFrom } from 'rxjs'; @@ -104,29 +118,81 @@ describe('Credentials', () => { client.close(); }); - it(EventDidcommAnonCredsCredentialsGetAll.token, async () => { + it(EventAnonCredsCredentialsGetAll.token, async () => { + const response$ = client.send< + EventAnonCredsCredentialsGetAll, + EventAnonCredsCredentialsGetAllInput + >(EventAnonCredsCredentialsGetAll.token, { tenantId }); + const response = await firstValueFrom(response$); + const eventInstance = EventAnonCredsCredentialsGetAll.fromEvent(response); + + expect(eventInstance.instance).toEqual(expect.arrayContaining([])); + }); + + it(EventAnonCredsCredentialOfferGetAll.token, async () => { const response$ = client.send< - EventDidcommAnonCredsCredentialsGetAll, - EventDidcommAnonCredsCredentialsGetAllInput - >(EventDidcommAnonCredsCredentialsGetAll.token, { tenantId }); + EventAnonCredsCredentialOfferGetAll, + EventAnonCredsCredentialOfferGetAllInput + >(EventAnonCredsCredentialOfferGetAll.token, { tenantId }); const response = await firstValueFrom(response$); const eventInstance = - EventDidcommAnonCredsCredentialsGetAll.fromEvent(response); + EventAnonCredsCredentialOfferGetAll.fromEvent(response); expect(eventInstance.instance).toEqual(expect.arrayContaining([])); }); - it(EventDidcommAnonCredsCredentialsGetById.token, async () => { + it(EventAnonCredsCredentialOfferGetById.token, async () => { const response$ = client.send< - EventDidcommAnonCredsCredentialsGetById, - EventDidcommAnonCredsCredentialsGetByIdInput - >(EventDidcommAnonCredsCredentialsGetById.token, { + EventAnonCredsCredentialOfferGetById, + EventAnonCredsCredentialOfferGetByIdInput + >(EventAnonCredsCredentialOfferGetById.token, { tenantId, - credentialRecordId: 'some-id', + credentialOfferId: 'some-id-that-does-not-exist', + }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialOfferGetById.fromEvent(response); + + expect(eventInstance.instance).toBeNull(); + }); + + it(EventAnonCredsCredentialRequestGetAll.token, async () => { + const response$ = client.send< + EventAnonCredsCredentialRequestGetAll, + EventAnonCredsCredentialRequestGetAllInput + >(EventAnonCredsCredentialRequestGetAll.token, { tenantId }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialRequestGetAll.fromEvent(response); + + expect(eventInstance.instance).toEqual(expect.arrayContaining([])); + }); + + it(EventAnonCredsCredentialRequestGetById.token, async () => { + const response$ = client.send< + EventAnonCredsCredentialRequestGetById, + EventAnonCredsCredentialRequestGetByIdInput + >(EventAnonCredsCredentialRequestGetById.token, { + tenantId, + credentialRequestId: 'some-id-that-does-not-exist', }); const response = await firstValueFrom(response$); const eventInstance = - EventDidcommAnonCredsCredentialsGetById.fromEvent(response); + EventAnonCredsCredentialRequestGetById.fromEvent(response); + + expect(eventInstance.instance).toBeNull(); + }); + + it(EventAnonCredsCredentialsGetById.token, async () => { + const response$ = client.send< + EventAnonCredsCredentialsGetById, + EventAnonCredsCredentialsGetByIdInput + >(EventAnonCredsCredentialsGetById.token, { + tenantId, + credentialRecordId: 'some-id', + }); + const response = await firstValueFrom(response$); + const eventInstance = EventAnonCredsCredentialsGetById.fromEvent(response); expect(eventInstance.instance).toEqual(null); }); @@ -154,4 +220,97 @@ describe('Credentials', () => { autoAcceptCredential: AutoAcceptCredential.Always, }); }); + + it(EventAnonCredsProofsDeleteById.token, async () => { + let credentialExchangeRecord: CredentialExchangeRecord | undefined = + undefined; + + // GET ALL + { + const response$ = client.send< + EventAnonCredsCredentialsGetAll, + EventAnonCredsCredentialsGetAllInput + >(EventAnonCredsCredentialsGetAll.token, { tenantId }); + const response = await firstValueFrom(response$); + const eventInstance = EventAnonCredsCredentialsGetAll.fromEvent(response); + + expect(eventInstance.instance).toEqual(expect.arrayContaining([])); + } + + // Offer a credential + + { + const attributes = [ + { name: 'Name', value: 'Berend' }, + { name: 'Age', value: '25' }, + ]; + + const response$ = client.send< + EventDidcommAnonCredsCredentialsOfferToSelf, + EventDidcommAnonCredsCredentialsOfferToSelfInput + >(EventDidcommAnonCredsCredentialsOfferToSelf.token, { + tenantId, + credentialDefinitionId, + attributes, + }); + + const response = await firstValueFrom(response$); + const eventInstance = + EventDidcommAnonCredsCredentialsOfferToSelf.fromEvent(response); + + expect(eventInstance.instance).toMatchObject({ + autoAcceptCredential: AutoAcceptCredential.Always, + }); + + credentialExchangeRecord = eventInstance.instance; + } + + // GET THE CREDENTIAL BY ID + { + const response$ = client.send< + EventAnonCredsCredentialsGetById, + EventAnonCredsCredentialsGetByIdInput + >(EventAnonCredsCredentialsGetById.token, { + tenantId, + credentialRecordId: credentialExchangeRecord.id, + }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialsGetById.fromEvent(response); + + expect(eventInstance.instance).toBeInstanceOf(CredentialExchangeRecord); + } + + // DELETE THE CREDENTIAL + { + const response$ = client.send< + EventAnonCredsCredentialsDeleteById, + EventAnonCredsCredentialsDeleteByIdInput + >(EventAnonCredsCredentialsDeleteById.token, { + tenantId, + credentialRecordId: credentialExchangeRecord.id, + }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialsDeleteById.fromEvent(response); + + expect(eventInstance).toMatchObject({}); + } + + // GET THE CREDENTIAL BY ID + { + const response$ = client.send< + EventAnonCredsCredentialsGetById, + EventAnonCredsCredentialsGetByIdInput + >(EventAnonCredsCredentialsGetById.token, { + tenantId, + credentialRecordId: credentialExchangeRecord.id, + }); + const response = await firstValueFrom(response$); + const eventInstance = + EventAnonCredsCredentialsGetById.fromEvent(response); + + expect(eventInstance.instance).toBeNull(); + } + }); });