From 332471b6ebcb171263ece0acd65c105690a0bcc9 Mon Sep 17 00:00:00 2001 From: DaevMithran Date: Mon, 23 Sep 2024 13:23:14 +0530 Subject: [PATCH] feat: Add resource connector in credential issuance --- src/services/api/credentials.ts | 21 ++++++++++-- src/services/connectors/resource.ts | 51 +++++++++++++++++++++++++++++ src/types/credential.ts | 6 ++++ src/types/swagger-api-types.ts | 5 +++ 4 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 src/services/connectors/resource.ts diff --git a/src/services/api/credentials.ts b/src/services/api/credentials.ts index 794e3ceb..af7e1d15 100644 --- a/src/services/api/credentials.ts +++ b/src/services/api/credentials.ts @@ -1,12 +1,12 @@ import type { CredentialPayload, VerifiableCredential } from '@veramo/core'; - import { VC_CONTEXT, VC_TYPE } from '../../types/constants.js'; -import type { CredentialRequest } from '../../types/credential.js'; +import { CredentialConnectors, type CredentialRequest } from '../../types/credential.js'; import { IdentityServiceStrategySetup } from '../identity/index.js'; import { v4 } from 'uuid'; import * as dotenv from 'dotenv'; import type { CustomerEntity } from '../../database/entities/customer.entity.js'; import { VeridaDIDValidator } from '../../controllers/validator/did.js'; +import { ResourceConnector } from '../connectors/resource.js'; dotenv.config(); const { ENABLE_VERIDA_CONNECTOR } = process.env; @@ -27,6 +27,7 @@ export class Credentials { credentialStatus, '@context': context, format, + connector, ...additionalData } = request; @@ -54,7 +55,12 @@ export class Credentials { ).agent.createCredential(credential, format, statusOptions, customer); const isVeridaDid = new VeridaDIDValidator().validate(subjectDid); - if (ENABLE_VERIDA_CONNECTOR === 'true' && isVeridaDid.valid && isVeridaDid.namespace) { + if ( + ENABLE_VERIDA_CONNECTOR === 'true' && + connector === CredentialConnectors.Verida && + isVeridaDid.valid && + isVeridaDid.namespace + ) { if (!credentialSchema) throw new Error('Credential schema is required'); // dynamic import to avoid circular dependency @@ -69,6 +75,15 @@ export class Credentials { credentialSchema, credentialSummary ); + } else if (connector && connector === CredentialConnectors.Resource) { + await ResourceConnector.instance.sendCredential( + customer, + issuerDid, + verifiable_credential, + credentialName || v4(), + type ? type[0] : 'Verifiable Credential', + v4() + ); } return verifiable_credential; } diff --git a/src/services/connectors/resource.ts b/src/services/connectors/resource.ts new file mode 100644 index 00000000..993ed892 --- /dev/null +++ b/src/services/connectors/resource.ts @@ -0,0 +1,51 @@ +import * as dotenv from 'dotenv'; +import type { VerifiableCredential } from '@veramo/core'; +import { IdentityServiceStrategySetup } from '../identity'; +import type { AlternativeUri, MsgCreateResourcePayload } from '@cheqd/ts-proto/cheqd/resource/v2'; +import { v4 } from 'uuid'; +import { fromString } from 'uint8arrays'; +import type { CustomerEntity } from '../../database/entities/customer.entity'; +dotenv.config(); + +/** + * Helper class for the Verida protocol. + * + * Run the init method before running any other method. + */ +export class ResourceConnector { + static instance = new ResourceConnector(); + + /** + * Send a Verifiable Credential to a DID via the Verida protocol. + * + * @param recipientDid The DID of the recipient. + * @param messageSubject The subject of the message in which the Credential will be sent to the recipient (similar to an email subject). + * @param credential The credential itself. + * @param credentialName The name of the credential. For instance, will be displayed in the Verida Wallet UI. + * @param credentialSummary A summary of the credential. For instance, will be displayed in the Verida Wallet UI. + */ + async sendCredential( + customer: CustomerEntity, + recipientDid: string, + credential: VerifiableCredential, + credentialName: string, + resourceType: string, + resourceVersion: string, + alsoKnownAs?: AlternativeUri[] + ) { + // Get strategy e.g. postgres or local + const identityServiceStrategySetup = new IdentityServiceStrategySetup(customer.customerId); + + let resourcePayload: Partial = {}; + resourcePayload = { + collectionId: recipientDid.split(':').pop(), + id: v4(), + name: credentialName, + resourceType, + data: fromString(credential, 'utf-8'), + version: resourceVersion, + alsoKnownAs, + }; + await identityServiceStrategySetup.agent.createResource(recipientDid.split(':')[2], resourcePayload, customer); + } +} diff --git a/src/types/credential.ts b/src/types/credential.ts index 76dc5a0b..ce180b26 100644 --- a/src/types/credential.ts +++ b/src/types/credential.ts @@ -11,6 +11,11 @@ import type { } from '@cheqd/did-provider-cheqd'; import type { VerificationOptions } from './shared.js'; +export enum CredentialConnectors { + Verida, + Resource, +} + export interface CredentialRequest { subjectDid: string; attributes: Record; @@ -26,6 +31,7 @@ export interface CredentialRequest { termsOfUse?: AdditionalData | AdditionalData[]; refreshService?: AdditionalData | AdditionalData[]; evidence?: AdditionalData | AdditionalData[]; + connector?: CredentialConnectors; [x: string]: any; } diff --git a/src/types/swagger-api-types.ts b/src/types/swagger-api-types.ts index 95640e74..63bfae10 100644 --- a/src/types/swagger-api-types.ts +++ b/src/types/swagger-api-types.ts @@ -130,6 +130,11 @@ * documentPresence: Physical, * licenseNumber: 123AB4567 * } + * connector: + * type: string + * enum: + * - verida + * - resource * required: * - issuerDid * - subjectDid