From aa5b102d2a28b75c9a01eeb621c2a57d98c841bd Mon Sep 17 00:00:00 2001 From: ashwin275 <110539449+ashwin275@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:55:00 +0530 Subject: [PATCH] Identity-service:Interface implemented --- services/identity-service/src/app.module.ts | 6 +- .../src/did/did.controller.spec.ts | 4 +- .../identity-service/src/did/did.module.ts | 7 ++- .../src/did/did.service.spec.ts | 5 +- .../identity-service/src/did/did.service.ts | 61 +++++++++++++++---- .../factories/blockchain-anchor.factory.ts | 38 ++++++++++++ .../implementations/anchor-cord.service.ts | 26 ++++++++ .../interfaces/blockchain_anchor.interface.ts | 9 +++ .../src/utils/cord.service.ts | 40 ------------ services/identity-service/src/vc/vc.module.ts | 7 ++- .../src/vc/vc.service.spec.ts | 5 +- 11 files changed, 141 insertions(+), 67 deletions(-) create mode 100644 services/identity-service/src/did/factories/blockchain-anchor.factory.ts create mode 100644 services/identity-service/src/did/implementations/anchor-cord.service.ts create mode 100644 services/identity-service/src/did/interfaces/blockchain_anchor.interface.ts delete mode 100644 services/identity-service/src/utils/cord.service.ts diff --git a/services/identity-service/src/app.module.ts b/services/identity-service/src/app.module.ts index 313f9ebba..9b7ba38e8 100644 --- a/services/identity-service/src/app.module.ts +++ b/services/identity-service/src/app.module.ts @@ -13,8 +13,8 @@ import { AuthGuard } from './auth/auth.guard'; import { TerminusModule } from '@nestjs/terminus'; import { PrismaHealthIndicator } from './utils/prisma.health'; import { VaultHealthIndicator } from './utils/vault.health'; -import { AnchorCordService } from './utils/cord.service'; - +import { AnchorCordService } from './did/implementations/anchor-cord.service'; +import { BlockchainAnchorFactory } from './did/factories/blockchain-anchor.factory'; @Module({ imports: [ DidModule, @@ -27,7 +27,7 @@ import { AnchorCordService } from './utils/cord.service'; ], controllers: [AppController, DidController], providers: [ - PrismaService, DidService, VaultService,AnchorCordService, + PrismaService, DidService, VaultService,BlockchainAnchorFactory,AnchorCordService, { provide: APP_GUARD, useClass: AuthGuard, diff --git a/services/identity-service/src/did/did.controller.spec.ts b/services/identity-service/src/did/did.controller.spec.ts index a80bd5fd3..02fc32f60 100644 --- a/services/identity-service/src/did/did.controller.spec.ts +++ b/services/identity-service/src/did/did.controller.spec.ts @@ -4,7 +4,6 @@ import { InternalServerErrorException } from '@nestjs/common'; import { DidService } from './did.service'; import { PrismaService } from '../utils/prisma.service'; import { VaultService } from '../utils/vault.service'; -import { AnchorCordService } from 'src/utils/cord.service'; import { ConfigService } from '@nestjs/config'; describe('DidController', () => { @@ -39,7 +38,8 @@ describe('DidController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [DidController], - providers: [DidService, PrismaService, ConfigService, VaultService,AnchorCordService] + // providers: [DidService, PrismaService, ConfigService, VaultService,AnchorCordService] + providers: [DidService, PrismaService, ConfigService, VaultService] }).compile(); controller = module.get(DidController); diff --git a/services/identity-service/src/did/did.module.ts b/services/identity-service/src/did/did.module.ts index 8c8fd9d09..d0d705233 100644 --- a/services/identity-service/src/did/did.module.ts +++ b/services/identity-service/src/did/did.module.ts @@ -5,8 +5,8 @@ import { PrismaService } from 'src/utils/prisma.service'; import { DidController } from './did.controller'; import { DidService } from './did.service'; import { VaultService } from '../utils/vault.service'; -import { AnchorCordService } from 'src/utils/cord.service'; - +import { BlockchainAnchorFactory } from './factories/blockchain-anchor.factory'; +import { AnchorCordService } from './implementations/anchor-cord.service'; @Module({ imports: [HttpModule], controllers: [DidController], @@ -14,7 +14,8 @@ import { AnchorCordService } from 'src/utils/cord.service'; DidService, PrismaService, VaultService, - AnchorCordService + AnchorCordService, + BlockchainAnchorFactory ], }) export class DidModule {} diff --git a/services/identity-service/src/did/did.service.spec.ts b/services/identity-service/src/did/did.service.spec.ts index 06dd00f43..db8ef10c9 100644 --- a/services/identity-service/src/did/did.service.spec.ts +++ b/services/identity-service/src/did/did.service.spec.ts @@ -2,7 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { DidService } from './did.service'; import { PrismaService } from '../utils/prisma.service'; import { VaultService } from '../utils/vault.service'; -import { AnchorCordService } from 'src/utils/cord.service'; +// import { AnchorCordService } from 'src/utils/cord.service'; import { GenerateDidDTO, VerificationKeyType } from './dtos/GenerateDidRequest.dto'; import { ConfigService } from '@nestjs/config'; @@ -33,7 +33,8 @@ describe('DidService', () => { beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [DidService, PrismaService, VaultService, ConfigService,AnchorCordService], + // providers: [DidService, PrismaService, VaultService, ConfigService,AnchorCordService], + providers: [DidService, PrismaService, VaultService, ConfigService], }).compile(); service = module.get(DidService); diff --git a/services/identity-service/src/did/did.service.ts b/services/identity-service/src/did/did.service.ts index 89233884f..a7f31d32d 100644 --- a/services/identity-service/src/did/did.service.ts +++ b/services/identity-service/src/did/did.service.ts @@ -5,7 +5,8 @@ import { VaultService } from '../utils/vault.service'; import { Identity } from '@prisma/client'; import { RSAKeyPair } from 'crypto-ld'; import { GenerateDidDTO } from './dtos/GenerateDidRequest.dto'; -import { AnchorCordService } from 'src/utils/cord.service'; +// import { AnchorCordService } from 'src/utils/cord.service'; +import { BlockchainAnchorFactory } from './factories/blockchain-anchor.factory'; const { DIDDocument } = require('did-resolver'); type DIDDocument = typeof DIDDocument; @@ -22,7 +23,7 @@ export class DidService { webDidPrefix: string; signingAlgorithm: string; didResolver: any; - constructor(private prisma: PrismaService, private vault: VaultService , private anchorcord:AnchorCordService) { + constructor(private prisma: PrismaService, private vault: VaultService , private blockchainFactory:BlockchainAnchorFactory) { let baseUrl: string = process.env.WEB_DID_BASE_URL; this.webDidPrefix = this.getDidPrefixForBaseUrl(baseUrl); this.signingAlgorithm = process.env.SIGNING_ALGORITHM; @@ -103,18 +104,22 @@ export class DidService { let document: DIDDocument; let privateKeys: object; let blockchainStatus: boolean = false; - - if (this.shouldAnchorToCord()) { + + // Check if anchoring to blockchain is enabled and get the method + const method = this.shouldAnchorToBlockchain(); + + if (method) { try { - if (doc.method !== 'cord') { - throw new BadRequestException('Invalid method: only "cord" is allowed for anchoring to Cord.'); - } - const response = await this.anchorcord.anchorDid(doc); - didUri = response.document.uri; - document = response.document; - - // store mnemonic and delegate keys in to vault - privateKeys = { + // Get the appropriate service from the factory + const anchorService = this.blockchainFactory.getAnchorService(method); + // Use the service to anchor the DID + const response = await anchorService.anchorDid(doc); + + didUri = response.document.uri; + document = response.document; + + // store mnemonic and delegate keys in to vault + privateKeys = { "mnemonic":response.mnemonic, "delegateKeys":response.delegateKeys }; @@ -250,4 +255,34 @@ export class DidService { process.env.ANCHOR_TO_CORD.toLowerCase().trim() === 'true' ); } + +/** + * Determines if anchoring to a blockchain is enabled based on environment variables. + * Checks for specific blockchain configurations and returns the appropriate method. + * @returns The blockchain method (e.g., 'cord', 'solana') if anchoring is enabled; otherwise, null. + */ +private shouldAnchorToBlockchain(): string | null { + // Check if the environment variable ANCHOR_TO_CORD is set to 'true' for the CORD blockchain + if ( + process.env.ANCHOR_TO_CORD && + process.env.ANCHOR_TO_CORD.toLowerCase().trim() === 'true' + ) { + return 'cord'; // Return 'cord' as the service method if CORD anchoring is enabled + } + + // Add additional checks here for other blockchains, e.g.,Solana, Ethereum, Polkadot + /* + if ( + process.env.ANCHOR_TO_SOLANA && + process.env.ANCHOR_TO_SOLANA.toLowerCase().trim() === 'true' + ) { + return 'solana'; // Return 'solana' if solana anchoring is enabled + } + */ + + return null; // Return null if no blockchain anchoring is required } + + +} + diff --git a/services/identity-service/src/did/factories/blockchain-anchor.factory.ts b/services/identity-service/src/did/factories/blockchain-anchor.factory.ts new file mode 100644 index 000000000..67d48cbff --- /dev/null +++ b/services/identity-service/src/did/factories/blockchain-anchor.factory.ts @@ -0,0 +1,38 @@ +import { Injectable, BadRequestException } from '@nestjs/common'; +import { AnchorCordService } from '../implementations/anchor-cord.service'; +import { BlockchainAnchor } from '../interfaces/blockchain_anchor.interface'; + +/** + * Factory class to dynamically resolve the appropriate BlockchainAnchor service. + * It uses the specified method to determine which implementation to return. + */ +@Injectable() +export class BlockchainAnchorFactory { + /** + * Constructor for the BlockchainAnchorFactory. + * @param cordService - An instance of AnchorCordService, which handles CORD-specific anchoring logic. + */ + constructor(private readonly cordService: AnchorCordService) {} + + /** + * Resolves the appropriate BlockchainAnchor service based on the provided method. + * @param method - The blockchain method (e.g., 'cord'). + * @returns The service instance corresponding to the specified method or null if no method is provided. + * @throws + */ + getAnchorService(method?: string): BlockchainAnchor | null { + // If no method is specified, return null to indicate no anchoring is required + if (!method) { + return null; + } + + // Determine the appropriate service implementation based on the method + switch (method) { + case 'cord': + // Return the CORD-specific implementation + return this.cordService; + default: + throw new BadRequestException(`Unsupported blockchain method: ${method}`); + } + } +} diff --git a/services/identity-service/src/did/implementations/anchor-cord.service.ts b/services/identity-service/src/did/implementations/anchor-cord.service.ts new file mode 100644 index 000000000..e6c4d221e --- /dev/null +++ b/services/identity-service/src/did/implementations/anchor-cord.service.ts @@ -0,0 +1,26 @@ +import { Injectable, Logger, InternalServerErrorException } from '@nestjs/common'; +import { HttpService } from '@nestjs/axios'; +import { BlockchainAnchor } from '../interfaces/blockchain_anchor.interface'; +import {BadRequestException} from '@nestjs/common'; +@Injectable() +export class AnchorCordService implements BlockchainAnchor { + private readonly logger = new Logger(AnchorCordService.name); + + constructor(private readonly httpService: HttpService) {} + + async anchorDid(body: any): Promise<{ document: any; mnemonic: string; delegateKeys: object }> { + try { + if (body.method !== 'cord') { + throw new BadRequestException('Invalid method: only "cord" is allowed for anchoring to Cord.'); + } + const response = await this.httpService.axiosRef.post( + `${process.env.ISSUER_AGENT_BASE_URL}/did/create/`, + body, + ); + return response.data.result; + } catch (err) { + this.logger.error('Error anchoring DID to CORD blockchain', err); + throw new InternalServerErrorException('Failed to anchor DID to CORD blockchain'); + } + } +} diff --git a/services/identity-service/src/did/interfaces/blockchain_anchor.interface.ts b/services/identity-service/src/did/interfaces/blockchain_anchor.interface.ts new file mode 100644 index 000000000..6e4d3998b --- /dev/null +++ b/services/identity-service/src/did/interfaces/blockchain_anchor.interface.ts @@ -0,0 +1,9 @@ +export interface BlockchainAnchor { + /** + * Anchors a DID document to the blockchain. + * @param body The request payload for anchoring. + * @returns The anchored DID document or related data. + */ + anchorDid(body: any): Promise; + } + \ No newline at end of file diff --git a/services/identity-service/src/utils/cord.service.ts b/services/identity-service/src/utils/cord.service.ts deleted file mode 100644 index ea20f244e..000000000 --- a/services/identity-service/src/utils/cord.service.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { HttpService } from '@nestjs/axios'; -import { - HttpException, - Injectable, - InternalServerErrorException, - Logger, -} from '@nestjs/common'; - -@Injectable() -export class AnchorCordService { - constructor(private readonly httpService: HttpService) {} - private logger = new Logger(AnchorCordService.name); - - async anchorDid(body: any): Promise { - try { - const response = await this.httpService.axiosRef.post( - `${process.env.ISSUER_AGENT_BASE_URL}/did/create/`, - body, - ); - return response.data; - } catch (err) { - const errorDetails = { - message: err.message, - status: err.response?.status, - statusText: err.response?.statusText, - data: err.response?.data, - headers: err.response?.headers, - request: err.config, - }; - - this.logger.error( - 'Error anchoring did to Cord blockchain', - errorDetails, - ); - throw new InternalServerErrorException( - 'Failed to anchor did to Cord blockchain', - ); - } - } -} diff --git a/services/identity-service/src/vc/vc.module.ts b/services/identity-service/src/vc/vc.module.ts index 42583550a..9e71d5686 100644 --- a/services/identity-service/src/vc/vc.module.ts +++ b/services/identity-service/src/vc/vc.module.ts @@ -5,11 +5,14 @@ import { VaultService } from 'src/utils/vault.service'; import { PrismaService } from 'src/utils/prisma.service'; import { VcController } from './vc.controller'; import VcService from './vc.service'; -import { AnchorCordService } from 'src/utils/cord.service'; +import { BlockchainAnchorFactory } from 'src/did/factories/blockchain-anchor.factory'; +import { AnchorCordService } from 'src/did/implementations/anchor-cord.service'; +// import { AnchorCordService } from 'src/utils/cord.service'; @Module({ imports: [HttpModule], controllers: [VcController], - providers: [VcService, PrismaService, DidService, VaultService,AnchorCordService], + providers: [VcService, PrismaService, DidService, VaultService,BlockchainAnchorFactory,AnchorCordService], + // providers: [VcService, PrismaService, DidService, VaultService,AnchorCordService], }) export class VcModule {} diff --git a/services/identity-service/src/vc/vc.service.spec.ts b/services/identity-service/src/vc/vc.service.spec.ts index 2b3c71b10..22e10f545 100644 --- a/services/identity-service/src/vc/vc.service.spec.ts +++ b/services/identity-service/src/vc/vc.service.spec.ts @@ -3,7 +3,7 @@ import VcService from './vc.service'; import { PrismaService } from '../utils/prisma.service'; import { DidService } from '../did/did.service'; import { VaultService } from '../utils/vault.service'; -import { AnchorCordService } from 'src/utils/cord.service'; +// import { AnchorCordService } from 'src/utils/cord.service'; describe('DidService', () => { let service: VcService; let didService: DidService; @@ -17,7 +17,8 @@ describe('DidService', () => { beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [VcService, PrismaService, DidService, VaultService,AnchorCordService], + providers: [VcService, PrismaService, DidService, VaultService], + // providers: [VcService, PrismaService, DidService, VaultService,AnchorCordService], }).compile(); service = module.get(VcService);