From 439244c0293db67bb4a8afdded0229660dd18aa4 Mon Sep 17 00:00:00 2001
From: Berend Sliedrecht <berend@animo.id>
Date: Fri, 2 Feb 2024 10:57:15 +0100
Subject: [PATCH] feat: use credo-ts

Signed-off-by: Berend Sliedrecht <berend@animo.id>
---
 apps/shared/src/events/credentialEvents.ts    |   2 +
 .../src/agent/agent.service.ts                |   4 +
 .../anoncredsCredentials.service.ts           |  18 +-
 .../src/agent/dids/dids.service.ts            |   2 +-
 .../test/revocation.e2e-spec.ts               | 155 +++++++++++++++++-
 5 files changed, 174 insertions(+), 7 deletions(-)

diff --git a/apps/shared/src/events/credentialEvents.ts b/apps/shared/src/events/credentialEvents.ts
index b71dd2c..49a495d 100644
--- a/apps/shared/src/events/credentialEvents.ts
+++ b/apps/shared/src/events/credentialEvents.ts
@@ -54,6 +54,8 @@ export type EventDidcommAnonCredsCredentialsOfferInput = BaseEventInput<{
   connectionId: string;
   credentialDefinitionId: string;
   attributes: Array<{ name: string; value: string; mimeType?: string }>;
+  revocationRegistryDefinitionId?: string;
+  revocationRegistryIndex?: number;
 }>;
 export class EventDidcommAnonCredsCredentialsOffer extends BaseEvent<CredentialExchangeRecord> {
   public static token = 'didcomm.anoncreds.credentials.offer';
diff --git a/apps/ssi-abstraction/src/agent/agent.service.ts b/apps/ssi-abstraction/src/agent/agent.service.ts
index d9792cb..9ac30b0 100644
--- a/apps/ssi-abstraction/src/agent/agent.service.ts
+++ b/apps/ssi-abstraction/src/agent/agent.service.ts
@@ -13,10 +13,12 @@ import {
 import { AskarModule } from '@credo-ts/askar';
 import {
   Agent,
+  CacheModule,
   ConnectionsModule,
   CredentialsModule,
   DidsModule,
   HttpOutboundTransport,
+  InMemoryLruCache,
   JwkDidRegistrar,
   JwkDidResolver,
   KeyDidRegistrar,
@@ -131,6 +133,8 @@ export class AgentService implements OnApplicationShutdown {
         ],
       }),
 
+      cache: new CacheModule({ cache: new InMemoryLruCache({ limit: 500 }) }),
+
       anoncreds: new AnonCredsModule({
         anoncreds,
         registries: [new IndyVdrAnonCredsRegistry()],
diff --git a/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.service.ts b/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.service.ts
index c994a5a..a00ce2c 100644
--- a/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.service.ts
+++ b/apps/ssi-abstraction/src/agent/anoncredsCredentials/anoncredsCredentials.service.ts
@@ -141,6 +141,8 @@ export class AnonCredsCredentialsService {
     connectionId,
     credentialDefinitionId,
     attributes,
+    revocationRegistryIndex,
+    revocationRegistryDefinitionId,
   }: EventDidcommAnonCredsCredentialsOfferInput): Promise<
     EventDidcommAnonCredsCredentialsOffer['data']
   > {
@@ -149,7 +151,12 @@ export class AnonCredsCredentialsService {
         protocolVersion: 'v2',
         connectionId,
         credentialFormats: {
-          anoncreds: { credentialDefinitionId, attributes },
+          anoncreds: {
+            credentialDefinitionId,
+            attributes,
+            revocationRegistryDefinitionId,
+            revocationRegistryIndex,
+          },
         },
       }),
     );
@@ -159,6 +166,8 @@ export class AnonCredsCredentialsService {
     tenantId,
     credentialDefinitionId,
     attributes,
+    revocationRegistryIndex,
+    revocationRegistryDefinitionId,
   }: EventDidcommAnonCredsCredentialsOfferToSelfInput): Promise<
     EventDidcommAnonCredsCredentialsOfferToSelf['data']
   > {
@@ -186,7 +195,12 @@ export class AnonCredsCredentialsService {
         autoAcceptCredential: AutoAcceptCredential.Always,
         connectionId: connection.id,
         credentialFormats: {
-          anoncreds: { credentialDefinitionId, attributes },
+          anoncreds: {
+            credentialDefinitionId,
+            attributes,
+            revocationRegistryDefinitionId,
+            revocationRegistryIndex,
+          },
         },
       });
     });
diff --git a/apps/ssi-abstraction/src/agent/dids/dids.service.ts b/apps/ssi-abstraction/src/agent/dids/dids.service.ts
index a1888d5..ed1fb32 100644
--- a/apps/ssi-abstraction/src/agent/dids/dids.service.ts
+++ b/apps/ssi-abstraction/src/agent/dids/dids.service.ts
@@ -169,7 +169,7 @@ export class DidsService {
         }),
     );
 
-    const buffer = Hasher.hash(publicKey, 'sha2-256');
+    const buffer = Hasher.hash(publicKey, 'sha-256');
     const id = TypedArrayEncoder.toBase58(buffer.slice(0, 16));
     const verkey = publicKeyBase58;
 
diff --git a/apps/ssi-abstraction/test/revocation.e2e-spec.ts b/apps/ssi-abstraction/test/revocation.e2e-spec.ts
index 83b1767..1fdab05 100644
--- a/apps/ssi-abstraction/test/revocation.e2e-spec.ts
+++ b/apps/ssi-abstraction/test/revocation.e2e-spec.ts
@@ -1,10 +1,22 @@
 import type { INestApplication } from '@nestjs/common';
 import type { ClientProxy } from '@nestjs/microservices';
-import type { EventAnonCredsRevocationRegisterRevocationRegistryDefinitionInput } from '@ocm/shared';
+import type {
+  EventAnonCredsCredentialsGetAllInput,
+  EventAnonCredsRevocationRegisterRevocationRegistryDefinitionInput,
+  EventAnonCredsRevocationRegisterRevocationStatusListInput,
+  EventAnonCredsRevocationRevokeInput,
+  EventDidcommAnonCredsCredentialsOfferToSelfInput,
+} from '@ocm/shared';
 
 import { ClientsModule, Transport } from '@nestjs/microservices';
 import { Test } from '@nestjs/testing';
-import { EventAnonCredsRevocationRegisterRevocationRegistryDefinition } from '@ocm/shared';
+import {
+  EventAnonCredsCredentialsGetAll,
+  EventDidcommAnonCredsCredentialsOfferToSelf,
+  EventAnonCredsRevocationRegisterRevocationRegistryDefinition,
+  EventAnonCredsRevocationRegisterRevocationStatusList,
+  EventAnonCredsRevocationRevoke,
+} from '@ocm/shared';
 import { randomBytes } from 'crypto';
 import { firstValueFrom } from 'rxjs';
 
@@ -100,7 +112,7 @@ describe('Revocation', () => {
     client.close();
   });
 
-  it(
+  xit(
     EventAnonCredsRevocationRegisterRevocationRegistryDefinition.token,
     async () => {
       const response$ = client.send<
@@ -121,9 +133,144 @@ describe('Revocation', () => {
 
       expect(
         eventInstance.instance.revocationRegistryDefinitionId.startsWith(
-          'did:indy:bcorvin:test:',
+          'did:indy:bcovrin:test:',
         ),
       ).toBeTruthy();
     },
   );
+
+  xit(EventAnonCredsRevocationRegisterRevocationStatusList.token, async () => {
+    let revRegDefId: string = '';
+    {
+      const response$ = client.send<
+        EventAnonCredsRevocationRegisterRevocationRegistryDefinition,
+        EventAnonCredsRevocationRegisterRevocationRegistryDefinitionInput
+      >(EventAnonCredsRevocationRegisterRevocationRegistryDefinition.token, {
+        tenantId,
+        tag: 'rev-tag-two',
+        issuerDid,
+        credentialDefinitionId,
+        maximumCredentialNumber: 100,
+      });
+      const response = await firstValueFrom(response$);
+      const eventInstance =
+        EventAnonCredsRevocationRegisterRevocationRegistryDefinition.fromEvent(
+          response,
+        );
+
+      revRegDefId = eventInstance.instance.revocationRegistryDefinitionId;
+    }
+
+    const response$ = client.send<
+      EventAnonCredsRevocationRegisterRevocationStatusList,
+      EventAnonCredsRevocationRegisterRevocationStatusListInput
+    >(EventAnonCredsRevocationRegisterRevocationStatusList.token, {
+      tenantId,
+      revocationRegistryDefinitionId: revRegDefId,
+      issuerDid,
+    });
+    const response = await firstValueFrom(response$);
+    const eventInstance =
+      EventAnonCredsRevocationRegisterRevocationStatusList.fromEvent(response);
+
+    expect(eventInstance.instance).toMatchObject({});
+  });
+
+  it(EventAnonCredsRevocationRevoke.token, async () => {
+    let revRegDefId: string = '';
+    let credentialId: string = '';
+
+    // Register the revocation registry definition
+    {
+      const response$ = client.send<
+        EventAnonCredsRevocationRegisterRevocationRegistryDefinition,
+        EventAnonCredsRevocationRegisterRevocationRegistryDefinitionInput
+      >(EventAnonCredsRevocationRegisterRevocationRegistryDefinition.token, {
+        tenantId,
+        tag: 'rev-tag-three',
+        issuerDid,
+        credentialDefinitionId,
+        maximumCredentialNumber: 100,
+      });
+      const response = await firstValueFrom(response$);
+      const eventInstance =
+        EventAnonCredsRevocationRegisterRevocationRegistryDefinition.fromEvent(
+          response,
+        );
+
+      revRegDefId = eventInstance.instance.revocationRegistryDefinitionId;
+    }
+
+    // Register the revocation Status List
+    {
+      const response$ = client.send<
+        EventAnonCredsRevocationRegisterRevocationStatusList,
+        EventAnonCredsRevocationRegisterRevocationStatusListInput
+      >(EventAnonCredsRevocationRegisterRevocationStatusList.token, {
+        tenantId,
+        revocationRegistryDefinitionId: revRegDefId,
+        issuerDid,
+      });
+      const response = await firstValueFrom(response$);
+      const eventInstance =
+        EventAnonCredsRevocationRegisterRevocationStatusList.fromEvent(
+          response,
+        );
+
+      expect(eventInstance.instance).toMatchObject({});
+    }
+
+    // Issue a credential
+    {
+      const response$ = client.send<
+        EventDidcommAnonCredsCredentialsOfferToSelf,
+        EventDidcommAnonCredsCredentialsOfferToSelfInput
+      >(EventDidcommAnonCredsCredentialsOfferToSelf.token, {
+        tenantId,
+        attributes: [
+          { name: 'Name', value: 'Berend' },
+          { name: 'Age', value: '30' },
+        ],
+        revocationRegistryDefinitionId: revRegDefId,
+        revocationRegistryIndex: 10,
+        credentialDefinitionId,
+      });
+      const response = await firstValueFrom(response$);
+      const eventInstance =
+        EventDidcommAnonCredsCredentialsOfferToSelf.fromEvent(response);
+
+      credentialId = eventInstance.instance.id;
+    }
+
+    // Revoke the credential
+    {
+      const response$ = client.send<
+        EventAnonCredsRevocationRevoke,
+        EventAnonCredsRevocationRevokeInput
+      >(EventAnonCredsRevocationRevoke.token, {
+        tenantId,
+        credentialId,
+      });
+      const response = await firstValueFrom(response$);
+      const eventInstance = EventAnonCredsRevocationRevoke.fromEvent(response);
+      expect(eventInstance.instance).toBeNull();
+    }
+
+    // Check the state
+    {
+      const response$ = client.send<
+        EventAnonCredsCredentialsGetAll,
+        EventAnonCredsCredentialsGetAllInput
+      >(EventAnonCredsCredentialsGetAll.token, {
+        tenantId,
+      });
+      const response = await firstValueFrom(response$);
+      const eventInstance = EventAnonCredsCredentialsGetAll.fromEvent(response);
+
+      const credRecord = eventInstance.instance.find(
+        (r) => r.id === credentialId,
+      );
+      // console.log(credRecord);
+    }
+  });
 });
-- 
GitLab