From e865b95f2affb5c914a33cbdf617ce6eac09a03e Mon Sep 17 00:00:00 2001
From: Berend Sliedrecht <berend@animo.id>
Date: Mon, 4 Dec 2023 12:58:32 +0100
Subject: [PATCH] fix(ssi): do not register did by default but make it an event

Signed-off-by: Berend Sliedrecht <berend@animo.id>
---
 apps/shared/src/events/didEvents.ts           |  46 +++----
 .../src/agent/agent.service.ts                |  38 +-----
 .../dids/__tests__/dids.controller.spec.ts    |  16 +++
 .../src/agent/dids/dids.controller.ts         |  12 +-
 .../src/agent/dids/dids.module.ts             |   3 +-
 .../src/agent/dids/dids.service.ts            |  62 +++++----
 .../src/agent/ledger/register.ts              |   4 -
 .../src/agent/schemas/schemas.service.ts      |   2 +-
 apps/ssi-abstraction/src/app.module.ts        |   2 +
 .../src/config/__tests__/mockConfig.ts        |  10 +-
 apps/ssi-abstraction/test/dids.e2e-spec.ts    |  44 +++----
 apps/ssi-abstraction/test/schemas.e2e-spec.ts | 119 ++++++++++++++++++
 12 files changed, 224 insertions(+), 134 deletions(-)
 create mode 100644 apps/ssi-abstraction/test/schemas.e2e-spec.ts

diff --git a/apps/shared/src/events/didEvents.ts b/apps/shared/src/events/didEvents.ts
index 60f5c68..e300545 100644
--- a/apps/shared/src/events/didEvents.ts
+++ b/apps/shared/src/events/didEvents.ts
@@ -4,44 +4,36 @@ import { DidDocument, JsonTransformer } from '@aries-framework/core';
 
 import { BaseEvent } from './baseEvents.js';
 
-/**
- *
- * @todo: this should be removed as it is a weird event that should not be needed
- *
- */
-export type EventDidsPublicDidInput = BaseEventInput;
-/**
- *
- * @todo: this should be removed as it is a weird event that should not be needed
- *
- */
-export class EventDidsPublicDid extends BaseEvent<DidDocument> {
-  public static token = 'dids.publicDid';
+export type EventDidsResolveInput = BaseEventInput<{ did: string }>;
+export class EventDidsResolve extends BaseEvent<DidDocument> {
+  public static token = 'dids.resolve';
 
   public get instance() {
     return JsonTransformer.fromJSON(this.data, DidDocument);
   }
 
-  public static fromEvent(e: EventDidsPublicDid) {
-    return new EventDidsPublicDid(
-      e.data,
-      e.tenantId,
-      e.id,
-      e.type,
-      e.timestamp,
-    );
+  public static fromEvent(e: EventDidsResolve) {
+    return new EventDidsResolve(e.data, e.tenantId, e.id, e.type, e.timestamp);
   }
 }
 
-export type EventDidsResolveInput = BaseEventInput<{ did: string }>;
-export class EventDidsResolve extends BaseEvent<DidDocument> {
-  public static token = 'dids.resolve';
+export type EventDidsRegisterIndyFromSeedInput = BaseEventInput<{
+  seed: string;
+}>;
+export class EventDidsRegisterIndyFromSeed extends BaseEvent<Array<string>> {
+  public static token = 'dids.register.indy.fromSeed';
 
   public get instance() {
-    return JsonTransformer.fromJSON(this.data, DidDocument);
+    return this.data;
   }
 
-  public static fromEvent(e: EventDidsResolve) {
-    return new EventDidsResolve(e.data, e.tenantId, e.id, e.type, e.timestamp);
+  public static fromEvent(e: EventDidsRegisterIndyFromSeed) {
+    return new EventDidsRegisterIndyFromSeed(
+      e.data,
+      e.tenantId,
+      e.id,
+      e.type,
+      e.timestamp,
+    );
   }
 }
diff --git a/apps/ssi-abstraction/src/agent/agent.service.ts b/apps/ssi-abstraction/src/agent/agent.service.ts
index 76b0bad..9df1a70 100644
--- a/apps/ssi-abstraction/src/agent/agent.service.ts
+++ b/apps/ssi-abstraction/src/agent/agent.service.ts
@@ -16,11 +16,9 @@ import {
   JwkDidResolver,
   KeyDidRegistrar,
   KeyDidResolver,
-  KeyType,
   LogLevel,
   PeerDidRegistrar,
   PeerDidResolver,
-  TypedArrayEncoder,
   WebDidResolver,
 } from '@aries-framework/core';
 import {
@@ -40,7 +38,6 @@ import { logger } from '@ocm/shared';
 
 import { LEDGERS } from '../config/ledger.js';
 
-import { registerPublicDids } from './ledger/register.js';
 import { AgentLogger } from './logger.js';
 
 export type AppAgent = Agent<AgentService['modules']>;
@@ -127,7 +124,7 @@ export class AgentService implements OnApplicationShutdown {
     };
   }
 
-  public get ledgers() {
+  private get ledgers() {
     const ledgerIds = this.configService.get('agent.ledgerIds');
 
     if (!ledgerIds || ledgerIds.length < 1 || ledgerIds[0] === '') {
@@ -153,41 +150,8 @@ export class AgentService implements OnApplicationShutdown {
     });
   }
 
-  private async registerPublicDid() {
-    const { publicDidSeed, ledgerIds } = this.configService.get('agent');
-
-    if (!publicDidSeed) {
-      logger.info('No public did seed provided, skipping registration');
-      return;
-    }
-
-    if (!ledgerIds || ledgerIds.length < 1 || ledgerIds[0] === '') {
-      return;
-    }
-
-    const registeredPublicDidResponses = await registerPublicDids({
-      alias: this.config.label,
-      ledgerIds,
-      seed: publicDidSeed,
-    });
-
-    for (const publicDidResponse of registeredPublicDidResponses) {
-      await this.agent.dids.import({
-        overwrite: true,
-        did: publicDidResponse.did,
-        privateKeys: [
-          {
-            keyType: KeyType.Ed25519,
-            privateKey: TypedArrayEncoder.fromString(publicDidSeed),
-          },
-        ],
-      });
-    }
-  }
-
   public async onModuleInit() {
     await this.agent.initialize();
-    await this.registerPublicDid();
     logger.info('Agent initialized');
   }
 
diff --git a/apps/ssi-abstraction/src/agent/dids/__tests__/dids.controller.spec.ts b/apps/ssi-abstraction/src/agent/dids/__tests__/dids.controller.spec.ts
index eb513d9..7bdb15e 100644
--- a/apps/ssi-abstraction/src/agent/dids/__tests__/dids.controller.spec.ts
+++ b/apps/ssi-abstraction/src/agent/dids/__tests__/dids.controller.spec.ts
@@ -34,4 +34,20 @@ describe('DidsController', () => {
       expect(event.data).toStrictEqual(result);
     });
   });
+
+  describe('register indy did from seed', () => {
+    it('should register an indy did from seed', async () => {
+      const result = ['did:indy:bcovrin:test:mock'];
+      jest
+        .spyOn(didsService, 'registerDidIndyFromSeed')
+        .mockResolvedValue(result);
+
+      const event = await didsController.registerFromSeed({
+        seed: 'random-secure-seed',
+        tenantId: 'some-id',
+      });
+
+      expect(event.data).toStrictEqual(result);
+    });
+  });
 });
diff --git a/apps/ssi-abstraction/src/agent/dids/dids.controller.ts b/apps/ssi-abstraction/src/agent/dids/dids.controller.ts
index c869d0d..688d688 100644
--- a/apps/ssi-abstraction/src/agent/dids/dids.controller.ts
+++ b/apps/ssi-abstraction/src/agent/dids/dids.controller.ts
@@ -1,8 +1,8 @@
 import { Controller } from '@nestjs/common';
 import { MessagePattern } from '@nestjs/microservices';
 import {
-  EventDidsPublicDid,
-  EventDidsPublicDidInput,
+  EventDidsRegisterIndyFromSeed,
+  EventDidsRegisterIndyFromSeedInput,
   EventDidsResolve,
   EventDidsResolveInput,
 } from '@ocm/shared';
@@ -13,10 +13,10 @@ import { DidsService } from './dids.service.js';
 export class DidsController {
   public constructor(private didsService: DidsService) {}
 
-  @MessagePattern(EventDidsPublicDid.token)
-  public async publicDid(options: EventDidsPublicDidInput) {
-    return new EventDidsPublicDid(
-      await this.didsService.getPublicDid(options),
+  @MessagePattern(EventDidsRegisterIndyFromSeed.token)
+  public async registerFromSeed(options: EventDidsRegisterIndyFromSeedInput) {
+    return new EventDidsRegisterIndyFromSeed(
+      await this.didsService.registerDidIndyFromSeed(options),
       options.tenantId,
     );
   }
diff --git a/apps/ssi-abstraction/src/agent/dids/dids.module.ts b/apps/ssi-abstraction/src/agent/dids/dids.module.ts
index 18668fe..d0a3f15 100644
--- a/apps/ssi-abstraction/src/agent/dids/dids.module.ts
+++ b/apps/ssi-abstraction/src/agent/dids/dids.module.ts
@@ -1,4 +1,5 @@
 import { Module } from '@nestjs/common';
+import { ConfigModule } from '@nestjs/config';
 
 import { AgentModule } from '../agent.module.js';
 
@@ -6,7 +7,7 @@ import { DidsController } from './dids.controller.js';
 import { DidsService } from './dids.service.js';
 
 @Module({
-  imports: [AgentModule ],
+  imports: [AgentModule, ConfigModule],
   providers: [DidsService],
   controllers: [DidsController],
 })
diff --git a/apps/ssi-abstraction/src/agent/dids/dids.service.ts b/apps/ssi-abstraction/src/agent/dids/dids.service.ts
index 2adf4c4..cf78072 100644
--- a/apps/ssi-abstraction/src/agent/dids/dids.service.ts
+++ b/apps/ssi-abstraction/src/agent/dids/dids.service.ts
@@ -1,18 +1,23 @@
-import type {
-  EventDidsPublicDidInput,
-  EventDidsResolveInput,
-} from '@ocm/shared';
+import type { EventDidsResolveInput } from '@ocm/shared';
 
+import { KeyType, TypedArrayEncoder } from '@aries-framework/core';
 import { Injectable } from '@nestjs/common';
+import { ConfigService } from '@nestjs/config';
 
+import { registerPublicDids } from '../ledger/register.js';
 import { WithTenantService } from '../withTenantService.js';
 
 @Injectable()
 export class DidsService {
-  public withTenantService: WithTenantService;
+  private withTenantService: WithTenantService;
+  private configService: ConfigService;
 
-  public constructor(withTenantService: WithTenantService) {
+  public constructor(
+    withTenantService: WithTenantService,
+    configService: ConfigService,
+  ) {
     this.withTenantService = withTenantService;
+    this.configService = configService;
   }
 
   public async resolve({ did, tenantId }: EventDidsResolveInput) {
@@ -34,26 +39,35 @@ export class DidsService {
     });
   }
 
-  public async getPublicDid({ tenantId }: EventDidsPublicDidInput) {
-    return this.withTenantService.invoke(tenantId, async (t) => {
-      const dids = await t.dids.getCreatedDids({ method: 'indy' });
-      if (dids.length === 0) {
-        throw new Error('No registered public DIDs');
-      }
+  public async registerDidIndyFromSeed({
+    tenantId,
+    seed,
+  }: {
+    tenantId: string;
+    seed: string;
+  }): Promise<Array<string>> {
+    const ledgerIds = this.configService.get('agent.ledgerIds');
 
-      if (dids.length > 1) {
-        throw new Error('Multiple public DIDs found');
-      }
+    const registeredPublicDidResponses = await registerPublicDids({
+      ledgerIds,
+      seed,
+    });
 
-      const didRecord = dids[0];
+    for (const publicDidResponse of registeredPublicDidResponses) {
+      await this.withTenantService.invoke(tenantId, (t) =>
+        t.dids.import({
+          overwrite: true,
+          did: publicDidResponse.did,
+          privateKeys: [
+            {
+              keyType: KeyType.Ed25519,
+              privateKey: TypedArrayEncoder.fromString(seed),
+            },
+          ],
+        }),
+      );
+    }
 
-      if (!didRecord.didDocument) {
-        throw new Error(
-          'A public DID was found, but did not include a DID Document',
-        );
-      }
-
-      return didRecord.didDocument;
-    });
+    return registeredPublicDidResponses.map((r) => r.did);
   }
 }
diff --git a/apps/ssi-abstraction/src/agent/ledger/register.ts b/apps/ssi-abstraction/src/agent/ledger/register.ts
index 1396428..8600a45 100644
--- a/apps/ssi-abstraction/src/agent/ledger/register.ts
+++ b/apps/ssi-abstraction/src/agent/ledger/register.ts
@@ -6,14 +6,12 @@ import axios from 'axios';
 import { LEDGERS } from '../../config/ledger.js';
 
 type RegisterPublicDidOptions = {
-  alias: string;
   ledgerIds: Array<LedgerIds>;
   seed: string;
 };
 
 type LedgerRegistrationBody = {
   role?: 'ENDORSER';
-  alias?: string;
   seed: string;
 };
 
@@ -25,7 +23,6 @@ type RegisterPublicDidResponse = {
 
 export const registerPublicDids = async ({
   ledgerIds,
-  alias,
   seed,
 }: RegisterPublicDidOptions): Promise<Array<RegisterPublicDidResponse>> => {
   const responses: Array<RegisterPublicDidResponse> = [];
@@ -36,7 +33,6 @@ export const registerPublicDids = async ({
 
       const body: LedgerRegistrationBody = {
         role: 'ENDORSER',
-        alias,
         seed,
       };
 
diff --git a/apps/ssi-abstraction/src/agent/schemas/schemas.service.ts b/apps/ssi-abstraction/src/agent/schemas/schemas.service.ts
index 5cb4222..da3a7dc 100644
--- a/apps/ssi-abstraction/src/agent/schemas/schemas.service.ts
+++ b/apps/ssi-abstraction/src/agent/schemas/schemas.service.ts
@@ -58,7 +58,7 @@ export class SchemasService {
           },
         });
 
-      if (schemaState.state !== 'finished') {
+      if (schemaState.state !== 'finished' && schemaState.state !== 'action') {
         throw new Error(
           `Error registering schema: ${
             schemaState.state === 'failed' ? schemaState.reason : 'Not Finished'
diff --git a/apps/ssi-abstraction/src/app.module.ts b/apps/ssi-abstraction/src/app.module.ts
index 44a25ae..52662f0 100644
--- a/apps/ssi-abstraction/src/app.module.ts
+++ b/apps/ssi-abstraction/src/app.module.ts
@@ -6,6 +6,7 @@ import { HealthController } from '@ocm/shared';
 
 import { AgentModule } from './agent/agent.module.js';
 import { ConnectionsModule } from './agent/connections/connections.module.js';
+import { SchemasModule } from './agent/schemas/schemas.module.js';
 import { TenantsModule } from './agent/tenants/tenants.module.js';
 import { config } from './config/config.js';
 import { validationSchema } from './config/validation.js';
@@ -21,6 +22,7 @@ import { validationSchema } from './config/validation.js';
     AgentModule,
     ConnectionsModule,
     DidsModule,
+    SchemasModule,
     TenantsModule,
   ],
   controllers: [HealthController],
diff --git a/apps/ssi-abstraction/src/config/__tests__/mockConfig.ts b/apps/ssi-abstraction/src/config/__tests__/mockConfig.ts
index 8a5eb2e..202a2b0 100644
--- a/apps/ssi-abstraction/src/config/__tests__/mockConfig.ts
+++ b/apps/ssi-abstraction/src/config/__tests__/mockConfig.ts
@@ -5,7 +5,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
 
 import { validationSchema } from '../validation.js';
 
-const mockConfig = (port: number = 3001): AppConfig => ({
+const mockConfig = (port: number = 3001, withLedger = false): AppConfig => ({
   agentHost: '',
   port: 3000,
   jwtSecret: '',
@@ -16,19 +16,19 @@ const mockConfig = (port: number = 3001): AppConfig => ({
     name: 'my-test-agent',
     walletId: utils.uuid(),
     walletKey: 'some-key',
-    ledgerIds: [],
+    ledgerIds: withLedger ? ['BCOVRIN_TEST'] : [],
     host: 'http://localhost',
     inboundPort: port,
     path: '',
-    publicDidSeed: '',
+    publicDidSeed: withLedger ? '12312367897123300000000000000000' : '',
     autoAcceptConnection: true,
     autoAcceptCredential: AutoAcceptCredential.ContentApproved,
   },
 });
 
-export const mockConfigModule = (port: number = 3000) =>
+export const mockConfigModule = (port: number = 3000, withLedger = false) =>
   ConfigModule.forRoot({
-    load: [() => mockConfig(port)],
+    load: [() => mockConfig(port, withLedger)],
     validationSchema,
   });
 
diff --git a/apps/ssi-abstraction/test/dids.e2e-spec.ts b/apps/ssi-abstraction/test/dids.e2e-spec.ts
index 8f3bafe..52c8a7b 100644
--- a/apps/ssi-abstraction/test/dids.e2e-spec.ts
+++ b/apps/ssi-abstraction/test/dids.e2e-spec.ts
@@ -1,37 +1,21 @@
 import type { INestApplication } from '@nestjs/common';
 import type { ClientProxy } from '@nestjs/microservices';
 import type {
+  EventDidsRegisterIndyFromSeedInput,
   EventDidsResolveInput,
-  EventDidsPublicDidInput,
 } from '@ocm/shared';
 
-import { DidDocument } from '@aries-framework/core';
 import { ClientsModule, Transport } from '@nestjs/microservices';
 import { Test } from '@nestjs/testing';
-import { EventDidsResolve, EventDidsPublicDid } from '@ocm/shared';
+import { EventDidsRegisterIndyFromSeed, EventDidsResolve } from '@ocm/shared';
 import { firstValueFrom } from 'rxjs';
 
 import { AgentModule } from '../src/agent/agent.module.js';
 import { DidsModule } from '../src/agent/dids/dids.module.js';
-import { DidsService } from '../src/agent/dids/dids.service.js';
 import { TenantsModule } from '../src/agent/tenants/tenants.module.js';
 import { TenantsService } from '../src/agent/tenants/tenants.service.js';
 import { mockConfigModule } from '../src/config/__tests__/mockConfig.js';
 
-const mockDidDocument = {
-  context: ['https://w3id.org/did/v1'],
-  id: 'did:indy:bcovrin:test:7KuDTpQh3GJ7Gp6kErpWvM',
-  verificationMethod: [
-    {
-      id: 'did:indy:bcovrin:test:7KuDTpQh3GJ7Gp6kErpWvM#verkey',
-      type: 'Ed25519VerificationKey2018',
-      controller: 'did:indy:bcovrin:test:7KuDTpQh3GJ7Gp6kErpWvM',
-      publicKeyBase58: '4SySYXQUtuK26zfC7RpQpWYMThfbXphUf8LWyXXmxyTX',
-    },
-  ],
-  authentication: ['did:indy:bcovrin:test:7KuDTpQh3GJ7Gp6kErpWvM#verkey'],
-};
-
 describe('Dids', () => {
   const TOKEN = 'DIDS_CLIENT_SERVICE';
   let app: INestApplication;
@@ -39,12 +23,9 @@ describe('Dids', () => {
   let tenantId: string;
 
   beforeAll(async () => {
-    jest
-      .spyOn(DidsService.prototype, 'getPublicDid')
-      .mockResolvedValue(new DidDocument(mockDidDocument));
     const moduleRef = await Test.createTestingModule({
       imports: [
-        mockConfigModule(3005),
+        mockConfigModule(3005, true),
         AgentModule,
         DidsModule,
         TenantsModule,
@@ -72,16 +53,21 @@ describe('Dids', () => {
     client.close();
   });
 
-  it(EventDidsPublicDid.token, async () => {
-    const response$ = client.send<EventDidsPublicDid, EventDidsPublicDidInput>(
-      EventDidsPublicDid.token,
-      { tenantId },
-    );
+  it(EventDidsRegisterIndyFromSeed.token, async () => {
+    const response$ = client.send<
+      EventDidsRegisterIndyFromSeed,
+      EventDidsRegisterIndyFromSeedInput
+    >(EventDidsRegisterIndyFromSeed.token, {
+      seed: '12312367897123300000000000000000',
+      tenantId,
+    });
 
     const response = await firstValueFrom(response$);
-    const eventInstance = EventDidsPublicDid.fromEvent(response);
+    const eventInstance = EventDidsRegisterIndyFromSeed.fromEvent(response);
 
-    expect(eventInstance.instance).toMatchObject(mockDidDocument);
+    expect(eventInstance.instance).toMatchObject(
+      expect.arrayContaining(['did:indy:bcovrin:test:9MMeff63VnCpogD2FWfKnJ']),
+    );
   });
 
   it(EventDidsResolve.token, async () => {
diff --git a/apps/ssi-abstraction/test/schemas.e2e-spec.ts b/apps/ssi-abstraction/test/schemas.e2e-spec.ts
new file mode 100644
index 0000000..acfe669
--- /dev/null
+++ b/apps/ssi-abstraction/test/schemas.e2e-spec.ts
@@ -0,0 +1,119 @@
+import type { INestApplication } from '@nestjs/common';
+import type { ClientProxy } from '@nestjs/microservices';
+import type {
+  EventAnonCredsSchemasGetAllInput,
+  EventAnonCredsSchemasGetByIdInput,
+  EventAnonCredsSchemasRegisterInput,
+} from '@ocm/shared';
+
+import { ClientsModule, Transport } from '@nestjs/microservices';
+import { Test } from '@nestjs/testing';
+import {
+  EventAnonCredsSchemasGetAll,
+  EventAnonCredsSchemasGetById,
+  EventAnonCredsSchemasRegister,
+} from '@ocm/shared';
+import { firstValueFrom } from 'rxjs';
+
+import { AgentModule } from '../src/agent/agent.module.js';
+import { DidsModule } from '../src/agent/dids/dids.module.js';
+import { DidsService } from '../src/agent/dids/dids.service.js';
+import { SchemasModule } from '../src/agent/schemas/schemas.module.js';
+import { TenantsModule } from '../src/agent/tenants/tenants.module.js';
+import { TenantsService } from '../src/agent/tenants/tenants.service.js';
+import { mockConfigModule } from '../src/config/__tests__/mockConfig.js';
+
+describe('Schemas', () => {
+  const TOKEN = 'SCHEMAS_CLIENT_SERVICE';
+  let app: INestApplication;
+  let client: ClientProxy;
+  let tenantId: string;
+  let issuerDid: string;
+
+  beforeAll(async () => {
+    const moduleRef = await Test.createTestingModule({
+      imports: [
+        mockConfigModule(3004, true),
+        AgentModule,
+        SchemasModule,
+        TenantsModule,
+        DidsModule,
+        ClientsModule.register([{ name: TOKEN, transport: Transport.NATS }]),
+      ],
+    }).compile();
+
+    app = moduleRef.createNestApplication();
+
+    app.connectMicroservice({ transport: Transport.NATS });
+
+    await app.startAllMicroservices();
+    await app.init();
+
+    client = app.get(TOKEN);
+    await client.connect();
+
+    const ts = app.get(TenantsService);
+    const { id } = await ts.create(TOKEN);
+    tenantId = id;
+
+    const ds = app.get(DidsService);
+    const [did] = await ds.registerDidIndyFromSeed({
+      tenantId,
+      seed: '12312367897123300000000000000000',
+    });
+    issuerDid = did;
+  });
+
+  afterAll(async () => {
+    await app.close();
+    client.close();
+  });
+
+  it(EventAnonCredsSchemasGetAll.token, async () => {
+    const response$ = client.send<
+      EventAnonCredsSchemasGetAll,
+      EventAnonCredsSchemasGetAllInput
+    >(EventAnonCredsSchemasGetAll.token, { tenantId });
+    const response = await firstValueFrom(response$);
+    const eventInstance = EventAnonCredsSchemasGetAll.fromEvent(response);
+
+    expect(eventInstance.instance).toEqual(expect.arrayContaining([]));
+  });
+
+  it(EventAnonCredsSchemasGetById.token, async () => {
+    const response$ = client.send<
+      EventAnonCredsSchemasGetById,
+      EventAnonCredsSchemasGetByIdInput
+    >(EventAnonCredsSchemasGetById.token, { tenantId, schemaId: 'some-id' });
+    const response = await firstValueFrom(response$);
+    const eventInstance = EventAnonCredsSchemasGetById.fromEvent(response);
+
+    expect(eventInstance.instance).toEqual(null);
+  });
+
+  it(EventAnonCredsSchemasRegister.token, async () => {
+    const version = new Date().getTime().toString();
+    const attributeNames = ['names', 'age'];
+    const name = 'my-schema';
+    const response$ = client.send<
+      EventAnonCredsSchemasRegister,
+      EventAnonCredsSchemasRegisterInput
+    >(EventAnonCredsSchemasRegister.token, {
+      tenantId,
+      name,
+      version,
+      issuerDid,
+      attributeNames,
+    });
+
+    const response = await firstValueFrom(response$);
+    const eventInstance = EventAnonCredsSchemasRegister.fromEvent(response);
+
+    expect(eventInstance.instance).toMatchObject({
+      attrNames: attributeNames,
+      issuerId: issuerDid,
+      name,
+      version,
+    });
+  });
+});
-- 
GitLab