From 13798a38de4c331f2af9b4c157eaef353addad09 Mon Sep 17 00:00:00 2001 From: Krishna Waske Date: Wed, 25 Mar 2026 15:11:04 +0530 Subject: [PATCH 1/6] fix: did and schema controller Signed-off-by: Krishna Waske --- samples/cliConfig.json | 5 +- src/cliAgent.ts | 5 +- .../anoncreds/schema/SchemaController.ts | 224 +++++------ src/controllers/did/DidController.ts | 82 ++-- src/controllers/types.ts | 21 +- src/enums/enum.ts | 6 +- src/routes/routes.ts | 169 ++++++++ src/routes/swagger.json | 363 ++++++++++++++++++ 8 files changed, 729 insertions(+), 146 deletions(-) diff --git a/samples/cliConfig.json b/samples/cliConfig.json index 105845d7..1af1bfad 100644 --- a/samples/cliConfig.json +++ b/samples/cliConfig.json @@ -12,14 +12,17 @@ "indyLedger": [ { "genesisTransactions": "https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis", + "isProduction": false, "indyNamespace": "indicio:testnet" }, { "genesisTransactions": "https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_demonet_genesis", + "isProduction": false, "indyNamespace": "indicio:demonet" }, { - "genesisTransactions": "https://raw.githubusercontent.com/bcgov/von-network/main/BCovrin/genesis_test", + "genesisTransactions": "https://test.bcovrin.vonx.io/genesis", + "isProduction": false, "indyNamespace": "bcovrin:testnet" } ], diff --git a/src/cliAgent.ts b/src/cliAgent.ts index 2b044cb7..25cecab8 100644 --- a/src/cliAgent.ts +++ b/src/cliAgent.ts @@ -1,6 +1,7 @@ // Note: For now we need to import askar-nodejs at the top to handle the undefined askar issue // Refer from: https://github.com/credebl/mobile-sdk/blob/main/packages/ssi/src/wallet/wallet.ts import '@openwallet-foundation/askar-nodejs' +import '@hyperledger/indy-vdr-nodejs' import type { AskarModuleConfigStoreOptions } from '@credo-ts/askar' import type { InitConfig } from '@credo-ts/core' import type { IndyVdrPoolConfig } from '@credo-ts/indy-vdr' @@ -193,10 +194,6 @@ const getModules = ( w3cCredentials: new W3cCredentialsModule(), didcomm: new DidCommModule({ processDidCommMessagesConcurrently: true, - anoncreds: new AnonCredsModule({ - registries: [new IndyVdrAnonCredsRegistry()], - anoncreds, - }), mediationRecipient: true, messagePickup: true, mediator: false, diff --git a/src/controllers/anoncreds/schema/SchemaController.ts b/src/controllers/anoncreds/schema/SchemaController.ts index 7a1e8577..716a2498 100644 --- a/src/controllers/anoncreds/schema/SchemaController.ts +++ b/src/controllers/anoncreds/schema/SchemaController.ts @@ -1,125 +1,127 @@ -// import { getUnqualifiedSchemaId, parseIndySchemaId } from '@credo-ts/anoncreds' -// import { Request as Req } from 'express' -// import { Example, Get, Post, Route, Tags, Security, Path, Body, Controller, Request } from 'tsoa' -// import { injectable } from 'tsyringe' +import { getUnqualifiedSchemaId, parseIndySchemaId, RegisterSchemaReturnStateFinished } from '@credo-ts/anoncreds' +import { Request as Req } from 'express' +import { Example, Get, Post, Route, Tags, Security, Path, Body, Controller, Request } from 'tsoa' +import { injectable } from 'tsyringe' -// import { CredentialEnum, EndorserMode, SchemaError, SCOPES } from '../../../enums' -// import ErrorHandlingService from '../../../errorHandlingService' -// import { ENDORSER_DID_NOT_PRESENT } from '../../../errorMessages' -// import { BadRequestError, InternalServerError, NotFoundError } from '../../../errors/errors' -// import { CreateSchemaSuccessful, SchemaExample, SchemaId } from '../../examples' -// import { CreateSchemaInput } from '../../types' +import { CredentialEnum, EndorserMode, SchemaError, SCOPES } from '../../../enums' +import ErrorHandlingService from '../../../errorHandlingService' +import { ENDORSER_DID_NOT_PRESENT } from '../../../errorMessages' +import { BadRequestError, InternalServerError, NotFoundError } from '../../../errors/errors' +import { CreateSchemaSuccessful, SchemaExample, SchemaId } from '../../examples' +import { CreateSchemaInput, RegisterSchemaReturn, SchemaResponseDTO } from '../../types' -// @Tags('Anoncreds - Schemas') -// @Route('/anoncreds/schemas') -// @Security('jwt', [SCOPES.TENANT_AGENT, SCOPES.DEDICATED_AGENT]) -// @injectable() -// export class SchemaController extends Controller { -// /** -// * Get schema by schemaId -// * @param schemaId -// * @param notFoundErrormessage -// * @param forbiddenError -// * @param badRequestError -// * @param internalServerError -// * @returns get schema by Id -// */ -// @Example(SchemaExample) -// @Get('/:schemaId') -// public async getSchemaById(@Request() request: Req, @Path('schemaId') schemaId: SchemaId) { -// try { -// const schemBySchemaId = await request.agent.modules.anoncreds.getSchema(schemaId) +@Tags('Anoncreds - Schemas') +@Route('/anoncreds/schemas') +@Security('jwt', [SCOPES.TENANT_AGENT, SCOPES.DEDICATED_AGENT]) +@injectable() +export class SchemaController extends Controller { + /** + * Get schema by schemaId + * @param schemaId + * @param notFoundErrormessage + * @param forbiddenError + * @param badRequestError + * @param internalServerError + * @returns get schema by Id + */ + @Example(SchemaExample) + @Get('/:schemaId') + public async getSchemaById(@Request() request: Req, @Path('schemaId') schemaId: SchemaId): Promise { + try { + const schemBySchemaId = await request.agent.modules.anoncreds.getSchema(schemaId) -// if ( -// (schemBySchemaId && -// schemBySchemaId?.resolutionMetadata && -// schemBySchemaId?.resolutionMetadata?.error === SchemaError.NotFound) || -// schemBySchemaId?.resolutionMetadata?.error === SchemaError.UnSupportedAnonCredsMethod -// ) { -// throw new NotFoundError( -// schemBySchemaId?.resolutionMetadata?.message || `schema details with schema id "${schemaId}" not found.`, -// ) -// } + if ( + (schemBySchemaId && + schemBySchemaId?.resolutionMetadata && + schemBySchemaId?.resolutionMetadata?.error === SchemaError.NotFound) || + schemBySchemaId?.resolutionMetadata?.error === SchemaError.UnSupportedAnonCredsMethod + ) { + throw new NotFoundError( + schemBySchemaId?.resolutionMetadata?.message || `schema details with schema id "${schemaId}" not found.`, + ) + } -// return schemBySchemaId -// } catch (error) { -// throw ErrorHandlingService.handle(error) -// } -// } + return schemBySchemaId + } catch (error) { + throw ErrorHandlingService.handle(error) + } + } -// /** -// * Create schema -// * @param schema -// * @param notFoundError -// * @param forbiddenError -// * @param badRequestError -// * @param internalServerError -// * @returns get schema -// */ -// @Post('/') -// @Example(CreateSchemaSuccessful) -// public async createSchema(@Request() request: Req, @Body() schema: CreateSchemaInput) { -// try { -// const { issuerId, name, version, attributes } = schema + /** + * Create schema + * @param schema + * @param notFoundError + * @param forbiddenError + * @param badRequestError + * @param internalServerError + * @returns get schema + */ + @Post('/') + @Example(CreateSchemaSuccessful) + public async createSchema(@Request() request: Req, @Body() schema: CreateSchemaInput): Promise { + try { + const { issuerId, name, version, attributes } = schema -// const schemaPayload = { -// issuerId, -// name, -// version, -// attrNames: attributes, -// } -// const createSchemaPayload = { -// schema: schemaPayload, -// options: { -// endorserMode: '', -// endorserDid: '', -// }, -// } + const schemaPayload = { + issuerId, + name, + version, + attrNames: attributes, + } + const createSchemaPayload = { + schema: schemaPayload, + options: { + endorserMode: '', + endorserDid: '', + }, + } -// if (!schema.endorse) { -// createSchemaPayload.options.endorserMode = EndorserMode.Internal -// createSchemaPayload.options.endorserDid = issuerId -// } else { -// if (!schema.endorserDid) { -// throw new BadRequestError(ENDORSER_DID_NOT_PRESENT) -// } -// createSchemaPayload.options.endorserMode = EndorserMode.External -// createSchemaPayload.options.endorserDid = schema.endorserDid -// } + if (!schema.endorse) { + createSchemaPayload.options.endorserMode = EndorserMode.Internal + createSchemaPayload.options.endorserDid = issuerId + } else { + if (!schema.endorserDid) { + throw new BadRequestError(ENDORSER_DID_NOT_PRESENT) + } + createSchemaPayload.options.endorserMode = EndorserMode.External + createSchemaPayload.options.endorserDid = schema.endorserDid + } -// const createSchemaTxResult = await request.agent.modules.anoncreds.registerSchema(createSchemaPayload) + const createSchemaTxResult = await request.agent.modules.anoncreds.registerSchema(createSchemaPayload) -// if (createSchemaTxResult.schemaState.state === CredentialEnum.Failed) { -// throw new InternalServerError(`Schema creation failed. Reason: ${createSchemaTxResult.schemaState.reason}`) -// } + if (createSchemaTxResult.schemaState.state === CredentialEnum.Failed) { + throw new InternalServerError(`Schema creation failed. Reason: ${createSchemaTxResult.schemaState.reason}`) + } -// if (createSchemaTxResult.schemaState.state === CredentialEnum.Wait) { -// this.setStatus(202) -// return createSchemaTxResult -// } + if (createSchemaTxResult.schemaState.state === CredentialEnum.Wait) { + this.setStatus(202) + return createSchemaTxResult + } -// if (createSchemaTxResult.schemaState.state === CredentialEnum.Action) { -// return createSchemaTxResult -// } + if (createSchemaTxResult.schemaState.state === CredentialEnum.Action) { + return createSchemaTxResult + } -// if (createSchemaTxResult.schemaState.state === CredentialEnum.Finished) { -// // TODO: Return uniform response for both Internally and Externally endorsed Schemas -// if (!schema.endorse) { -// const indySchemaId = parseIndySchemaId(createSchemaTxResult.schemaState.schemaId as string) + if (createSchemaTxResult.schemaState.state === CredentialEnum.Finished) { + // TODO: Return uniform response for both Internally and Externally endorsed Schemas + if (!schema.endorse) { + const indySchemaId = parseIndySchemaId(createSchemaTxResult.schemaState.schemaId as string) -// const getSchemaUnqualifiedId = await getUnqualifiedSchemaId( -// indySchemaId.namespaceIdentifier, -// indySchemaId.schemaName, -// indySchemaId.schemaVersion, -// ) + const getSchemaUnqualifiedId = await getUnqualifiedSchemaId( + indySchemaId.namespaceIdentifier, + indySchemaId.schemaName, + indySchemaId.schemaVersion, + ) -// createSchemaTxResult.schemaState.schemaId = getSchemaUnqualifiedId -// return createSchemaTxResult.schemaState -// } -// return createSchemaTxResult -// } -// } catch (error) { -// throw ErrorHandlingService.handle(error) -// } -// } -// } + createSchemaTxResult.schemaState.schemaId = getSchemaUnqualifiedId + return createSchemaTxResult.schemaState + } + return createSchemaTxResult + } + // If none of the above conditions are met, throw an error or return a default value + throw new InternalServerError('Unexpected schema creation state.') + } catch (error) { + throw ErrorHandlingService.handle(error) + } + } +} diff --git a/src/controllers/did/DidController.ts b/src/controllers/did/DidController.ts index 682c12bf..d46efe0f 100644 --- a/src/controllers/did/DidController.ts +++ b/src/controllers/did/DidController.ts @@ -200,7 +200,9 @@ export class DidController extends Controller { } if (createDidOptions?.role?.toLowerCase() === Role.Endorser) { if (createDidOptions.did) { - await this.importDid(agent, didMethod, createDidOptions.did, createDidOptions.seed) + // Hint: Bcovrin uses seed as private key when creating key. But seed is written as a NYM transaction + // Triage: Make sure what to use, seed or privateKey when accepting from API itself + await this.importDid(agent, didMethod, createDidOptions.did, "", createDidOptions.seed) const getDid = await agent.dids.getCreatedDids({ method: createDidOptions.method, did: `did:${createDidOptions.method}:${createDidOptions.network}:${createDidOptions.did}`, @@ -224,7 +226,7 @@ export class DidController extends Controller { seed: createDidOptions.seed, }) const { did } = res?.data || {} - await this.importDid(agent, didMethod, did, createDidOptions.seed) + await this.importDid(agent, didMethod, did, "", createDidOptions.seed) const didRecord = await agent.dids.getCreatedDids({ method: DidMethod.Indy, did: `did:${DidMethod.Indy}:${Network.Bcovrin_Testnet}:${res.data.did}`, @@ -270,11 +272,11 @@ export class DidController extends Controller { didDocument: didDocument, } } else { - const key = await this.createIndicioKey(agent, createDidOptions) + const {keyId, ...key} = await this.createIndicioKey(agent, createDidOptions) const INDICIO_NYM_URL = process.env.INDICIO_NYM_URL as string const res = await axios.post(INDICIO_NYM_URL, key) if (res.data.statusCode === 200) { - await this.importDid(agent, didMethod, key.did, createDidOptions.seed) + await this.importDid(agent, didMethod, key.did, createDidOptions.seed, undefined, keyId) const didRecord = await agent.dids.getCreatedDids({ method: DidMethod.Indy, did: `${didMethod}:${key.did}`, @@ -326,34 +328,39 @@ export class DidController extends Controller { // const buffer = TypedArrayEncoder.fromBase58(key.publicKeyBase58) // const did = TypedArrayEncoder.toBase58(buffer.slice(0, 16)) - const _verificationKey = ( - await agent.kms.createKey({ - type: { - kty: 'OKP', - crv: 'Ed25519', - }, - }) - ).publicJwk + const privateJwk = transformSeedToPrivateJwk({ + seed: TypedArrayEncoder.fromString(createDidOptions.seed), + type: { + crv: 'Ed25519', + kty: 'OKP', + }, + }).privateJwk + + const key = await agent.kms.importKey({ + privateJwk + }) - const verificationKey = Kms.PublicJwk.fromPublicJwk(_verificationKey) as Kms.PublicJwk + const verificationKey = Kms.PublicJwk.fromPublicJwk(key.publicJwk) as Kms.PublicJwk // Create a new key and calculate did according to the rules for indy did method - const buffer = Hasher.hash(verificationKey.publicKey.publicKey, 'sha-256') + const publicKeyBytes = verificationKey.publicKey.publicKey - const did = TypedArrayEncoder.toBase58(buffer.slice(0, 16)) + const did = TypedArrayEncoder.toBase58(publicKeyBytes.slice(0, 16)) let body if (createDidOptions.network === Network.Indicio_Testnet) { body = { network: 'testnet', did, - verkey: TypedArrayEncoder.toBase58(buffer), + verkey: TypedArrayEncoder.toBase58(publicKeyBytes), + keyId: key.keyId } } else if (createDidOptions.network === Network.Indicio_Demonet) { body = { network: 'demonet', did, - verkey: TypedArrayEncoder.toBase58(buffer), + verkey: TypedArrayEncoder.toBase58(publicKeyBytes), + keyId: key.keyId } } else { throw new BadRequestError('Please provide a valid did method') @@ -361,7 +368,7 @@ export class DidController extends Controller { return body } - private async importDid(agent: AgentType, didMethod: string, did: string, seed: string) { + private async importDid(agent: AgentType, didMethod: string, did: string, seed: string, privateKey?: string, _keyId?: string) { // TODO: Remove comments afterwards // await agent.dids.import({ // did: `${didMethod}:${did}`, @@ -374,23 +381,42 @@ export class DidController extends Controller { // ], // }) - const { privateJwk } = transformSeedToPrivateJwk({ - type: { - crv: 'Ed25519', - kty: 'OKP', - }, - seed: TypedArrayEncoder.fromString(seed), - }) + let keyId: string; + + if (!_keyId) { + const { privateJwk } = privateKey ? transformPrivateKeyToPrivateJwk({ + type: { + crv: 'Ed25519', + kty: 'OKP', + }, + privateKey: TypedArrayEncoder.fromString(privateKey), + }) : seed ? transformSeedToPrivateJwk({ + seed: TypedArrayEncoder.fromString(seed), + type: { + crv: 'Ed25519', + kty: 'OKP', + } + }) : { + privateJwk: undefined + } + + if (!privateJwk) { + throw new Error("Either privateKey or seed is required") + } + + const key = await agent.kms.importKey({ privateJwk }) + keyId = key.keyId + } else { + keyId = _keyId + } - const key = await agent.kms.importKey({ privateJwk }) - const publicJwk = Kms.PublicJwk.fromPublicJwk(key.publicJwk) const completeDid = `${didMethod}:${did}` await agent.dids.import({ did: completeDid, keys: [ { - kmsKeyId: key.keyId, + kmsKeyId: keyId, didDocumentRelativeKeyId: verkey, }, ], diff --git a/src/controllers/types.ts b/src/controllers/types.ts index 19e4c635..ac7febb5 100644 --- a/src/controllers/types.ts +++ b/src/controllers/types.ts @@ -1,5 +1,5 @@ import type { RecordId } from './examples' -import type { AnonCredsDidCommCredentialFormat, LegacyIndyCredentialFormat } from '@credo-ts/anoncreds' +import type { AnonCredsDidCommCredentialFormat, LegacyIndyCredentialFormat, RegisterSchemaReturnStateAction, RegisterSchemaReturnStateFailed, RegisterSchemaReturnStateFinished, RegisterSchemaReturnStateWait } from '@credo-ts/anoncreds' import type { DidResolutionMetadata, DidDocumentMetadata, @@ -493,3 +493,22 @@ export type EcType = { kty: 'EC' crv: 'P-256' | 'P-384' | 'P-521' | 'secp256k1' } + +export interface SchemaResponseDTO { + schemaId: string; + schema?: { + issuerId: string; + name: string; + version: string; + attrNames: string[]; + }; + resolutionMetadata: Record; // Use Record or explicitly define what you need + schemaMetadata: Record; +} + +export interface RegisterSchemaReturn { + jobId?: string; + schemaState: RegisterSchemaReturnStateWait | RegisterSchemaReturnStateAction | RegisterSchemaReturnStateFinished | RegisterSchemaReturnStateFailed; + schemaMetadata: Record; + registrationMetadata: Record; +} \ No newline at end of file diff --git a/src/enums/enum.ts b/src/enums/enum.ts index b58196a2..72dcd9fa 100644 --- a/src/enums/enum.ts +++ b/src/enums/enum.ts @@ -44,7 +44,11 @@ export enum NetworkTypes { export enum IndicioAcceptanceMechanism { Wallet_Agreement = 'wallet_agreement', - Accept = 'accept', + At_Submission = 'at_submission', + For_Session = 'for_session', + On_File = 'on_file', + Product_Eula = 'product_eula', + Service_Agreement = 'service_agreement' } export enum EndorserMode { diff --git a/src/routes/routes.ts b/src/routes/routes.ts index 55f296e3..c5bc7cc9 100644 --- a/src/routes/routes.ts +++ b/src/routes/routes.ts @@ -30,6 +30,8 @@ import { AuthController } from './../controllers/auth/AuthController'; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa import { AgentController } from './../controllers/agent/AgentController'; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa +import { SchemaController } from './../controllers/anoncreds/schema/SchemaController'; +// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa import { VerifierController } from './../controllers/openid4vc/verifiers/verifier.Controller'; import { expressAuthentication } from './../authentication'; // @ts-ignore - no great way to install types from subpackage @@ -1540,6 +1542,99 @@ const models: TsoaRoute.Models = { "additionalProperties": false, }, // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "SchemaResponseDTO": { + "dataType": "refObject", + "properties": { + "schemaId": {"dataType":"string","required":true}, + "schema": {"dataType":"nestedObjectLiteral","nestedProperties":{"attrNames":{"dataType":"array","array":{"dataType":"string"},"required":true},"version":{"dataType":"string","required":true},"name":{"dataType":"string","required":true},"issuerId":{"dataType":"string","required":true}}}, + "resolutionMetadata": {"ref":"Record_string.unknown_","required":true}, + "schemaMetadata": {"ref":"Record_string.unknown_","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "SchemaId": { + "dataType": "refAlias", + "type": {"dataType":"string","validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "AnonCredsSchema": { + "dataType": "refObject", + "properties": { + "issuerId": {"dataType":"string","required":true}, + "name": {"dataType":"string","required":true}, + "version": {"dataType":"string","required":true}, + "attrNames": {"dataType":"array","array":{"dataType":"string"},"required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterSchemaReturnStateWait": { + "dataType": "refObject", + "properties": { + "state": {"dataType":"enum","enums":["wait"],"required":true}, + "schema": {"ref":"AnonCredsSchema"}, + "schemaId": {"dataType":"string"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterSchemaReturnStateAction": { + "dataType": "refObject", + "properties": { + "state": {"dataType":"enum","enums":["action"],"required":true}, + "action": {"dataType":"string","required":true}, + "schema": {"ref":"AnonCredsSchema","required":true}, + "schemaId": {"dataType":"string","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterSchemaReturnStateFinished": { + "dataType": "refObject", + "properties": { + "state": {"dataType":"enum","enums":["finished"],"required":true}, + "schema": {"ref":"AnonCredsSchema","required":true}, + "schemaId": {"dataType":"string","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterSchemaReturnStateFailed": { + "dataType": "refObject", + "properties": { + "state": {"dataType":"enum","enums":["failed"],"required":true}, + "reason": {"dataType":"string","required":true}, + "schema": {"ref":"AnonCredsSchema"}, + "schemaId": {"dataType":"string"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterSchemaReturn": { + "dataType": "refObject", + "properties": { + "jobId": {"dataType":"string"}, + "schemaState": {"dataType":"union","subSchemas":[{"ref":"RegisterSchemaReturnStateWait"},{"ref":"RegisterSchemaReturnStateAction"},{"ref":"RegisterSchemaReturnStateFinished"},{"ref":"RegisterSchemaReturnStateFailed"}],"required":true}, + "schemaMetadata": {"ref":"Record_string.unknown_","required":true}, + "registrationMetadata": {"ref":"Record_string.unknown_","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "CreateSchemaInput": { + "dataType": "refObject", + "properties": { + "issuerId": {"dataType":"string","required":true}, + "name": {"dataType":"string","required":true}, + "version": {"dataType":"string","required":true}, + "attributes": {"dataType":"array","array":{"dataType":"string"},"required":true}, + "endorse": {"dataType":"boolean"}, + "endorserDid": {"dataType":"string"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa "OpenId4VcVerifierRecord": { "dataType": "refAlias", "type": {"ref":"Record_string.unknown_","validators":{}}, @@ -4082,6 +4177,80 @@ export function RegisterRoutes(app: Router) { } }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + const argsSchemaController_getSchemaById: Record = { + request: {"in":"request","name":"request","required":true,"dataType":"object"}, + schemaId: {"in":"path","name":"schemaId","required":true,"ref":"SchemaId"}, + }; + app.get('/anoncreds/schemas/:schemaId', + authenticateMiddleware([{"jwt":["tenant","dedicated"]}]), + ...(fetchMiddlewares(SchemaController)), + ...(fetchMiddlewares(SchemaController.prototype.getSchemaById)), + + async function SchemaController_getSchemaById(request: ExRequest, response: ExResponse, next: any) { + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args: argsSchemaController_getSchemaById, request, response }); + + const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer; + + const controller: any = await container.get(SchemaController); + if (typeof controller['setStatus'] === 'function') { + controller.setStatus(undefined); + } + + await templateService.apiHandler({ + methodName: 'getSchemaById', + controller, + response, + next, + validatedArgs, + successStatus: undefined, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + const argsSchemaController_createSchema: Record = { + request: {"in":"request","name":"request","required":true,"dataType":"object"}, + schema: {"in":"body","name":"schema","required":true,"ref":"CreateSchemaInput"}, + }; + app.post('/anoncreds/schemas', + authenticateMiddleware([{"jwt":["tenant","dedicated"]}]), + ...(fetchMiddlewares(SchemaController)), + ...(fetchMiddlewares(SchemaController.prototype.createSchema)), + + async function SchemaController_createSchema(request: ExRequest, response: ExResponse, next: any) { + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args: argsSchemaController_createSchema, request, response }); + + const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer; + + const controller: any = await container.get(SchemaController); + if (typeof controller['setStatus'] === 'function') { + controller.setStatus(undefined); + } + + await templateService.apiHandler({ + methodName: 'createSchema', + controller, + response, + next, + validatedArgs, + successStatus: undefined, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa const argsVerifierController_createVerifier: Record = { request: {"in":"request","name":"request","required":true,"dataType":"object"}, options: {"in":"body","name":"options","required":true,"ref":"OpenId4VcSiopCreateVerifierOptions"}, diff --git a/src/routes/swagger.json b/src/routes/swagger.json index 55f04345..9c86bfe7 100644 --- a/src/routes/swagger.json +++ b/src/routes/swagger.json @@ -3477,6 +3477,252 @@ "type": "object", "additionalProperties": false }, + "SchemaResponseDTO": { + "properties": { + "schemaId": { + "type": "string" + }, + "schema": { + "properties": { + "attrNames": { + "items": { + "type": "string" + }, + "type": "array" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "issuerId": { + "type": "string" + } + }, + "required": [ + "attrNames", + "version", + "name", + "issuerId" + ], + "type": "object" + }, + "resolutionMetadata": { + "$ref": "#/components/schemas/Record_string.unknown_" + }, + "schemaMetadata": { + "$ref": "#/components/schemas/Record_string.unknown_" + } + }, + "required": [ + "schemaId", + "resolutionMetadata", + "schemaMetadata" + ], + "type": "object", + "additionalProperties": false + }, + "SchemaId": { + "type": "string", + "example": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0" + }, + "AnonCredsSchema": { + "properties": { + "issuerId": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "attrNames": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "issuerId", + "name", + "version", + "attrNames" + ], + "type": "object", + "additionalProperties": false + }, + "RegisterSchemaReturnStateWait": { + "properties": { + "state": { + "type": "string", + "enum": [ + "wait" + ], + "nullable": false + }, + "schema": { + "$ref": "#/components/schemas/AnonCredsSchema" + }, + "schemaId": { + "type": "string" + } + }, + "required": [ + "state" + ], + "type": "object", + "additionalProperties": false + }, + "RegisterSchemaReturnStateAction": { + "properties": { + "state": { + "type": "string", + "enum": [ + "action" + ], + "nullable": false + }, + "action": { + "type": "string" + }, + "schema": { + "$ref": "#/components/schemas/AnonCredsSchema" + }, + "schemaId": { + "type": "string" + } + }, + "required": [ + "state", + "action", + "schema", + "schemaId" + ], + "type": "object", + "additionalProperties": false + }, + "RegisterSchemaReturnStateFinished": { + "properties": { + "state": { + "type": "string", + "enum": [ + "finished" + ], + "nullable": false + }, + "schema": { + "$ref": "#/components/schemas/AnonCredsSchema" + }, + "schemaId": { + "type": "string" + } + }, + "required": [ + "state", + "schema", + "schemaId" + ], + "type": "object", + "additionalProperties": false + }, + "RegisterSchemaReturnStateFailed": { + "properties": { + "state": { + "type": "string", + "enum": [ + "failed" + ], + "nullable": false + }, + "reason": { + "type": "string" + }, + "schema": { + "$ref": "#/components/schemas/AnonCredsSchema" + }, + "schemaId": { + "type": "string" + } + }, + "required": [ + "state", + "reason" + ], + "type": "object", + "additionalProperties": false + }, + "RegisterSchemaReturn": { + "properties": { + "jobId": { + "type": "string" + }, + "schemaState": { + "anyOf": [ + { + "$ref": "#/components/schemas/RegisterSchemaReturnStateWait" + }, + { + "$ref": "#/components/schemas/RegisterSchemaReturnStateAction" + }, + { + "$ref": "#/components/schemas/RegisterSchemaReturnStateFinished" + }, + { + "$ref": "#/components/schemas/RegisterSchemaReturnStateFailed" + } + ] + }, + "schemaMetadata": { + "$ref": "#/components/schemas/Record_string.unknown_" + }, + "registrationMetadata": { + "$ref": "#/components/schemas/Record_string.unknown_" + } + }, + "required": [ + "schemaState", + "schemaMetadata", + "registrationMetadata" + ], + "type": "object", + "additionalProperties": false + }, + "CreateSchemaInput": { + "properties": { + "issuerId": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "attributes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "endorse": { + "type": "boolean" + }, + "endorserDid": { + "type": "string" + } + }, + "required": [ + "issuerId", + "name", + "version", + "attributes" + ], + "type": "object", + "additionalProperties": false + }, "OpenId4VcVerifierRecord": { "$ref": "#/components/schemas/Record_string.unknown_", "description": "For OID4VC you need to expos metadata files. Each issuer needs to host this metadata. This is not the case for DIDComm where we can just have one /didcomm endpoint.\nSo we create a record per openid issuer/verifier that you want, and each tenant can create multiple issuers/verifiers which have different endpoints\nand metadata files" @@ -7402,6 +7648,123 @@ } } }, + "/anoncreds/schemas/{schemaId}": { + "get": { + "operationId": "GetSchemaById", + "responses": { + "200": { + "description": "get schema by Id", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SchemaResponseDTO" + }, + "examples": { + "Example 1": { + "value": { + "ver": "1.0", + "id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "name": "schema", + "version": "1.0", + "attrNames": [ + "string" + ], + "seqNo": 351936 + } + } + } + } + } + } + }, + "description": "Get schema by schemaId", + "tags": [ + "Anoncreds - Schemas" + ], + "security": [ + { + "jwt": [ + "tenant", + "dedicated" + ] + } + ], + "parameters": [ + { + "in": "path", + "name": "schemaId", + "required": true, + "schema": { + "$ref": "#/components/schemas/SchemaId" + } + } + ] + } + }, + "/anoncreds/schemas": { + "post": { + "operationId": "CreateSchema", + "responses": { + "200": { + "description": "get schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/RegisterSchemaReturn" + }, + { + "$ref": "#/components/schemas/RegisterSchemaReturnStateFinished" + } + ] + }, + "examples": { + "Example 1": { + "value": { + "state": "finished", + "schema": { + "issuerId": "did:indy:bcovrin:testnet:LRCUFcizUL74AGgLqdJHK7", + "name": "Test Schema", + "version": "1.0.0", + "attrNames": [ + "Name", + "Age" + ] + }, + "schemaId": "LRCUFcizUL74AGgLqdJHK7:2:Test Schema:1.0.0" + } + } + } + } + } + } + }, + "description": "Create schema", + "tags": [ + "Anoncreds - Schemas" + ], + "security": [ + { + "jwt": [ + "tenant", + "dedicated" + ] + } + ], + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSchemaInput" + } + } + } + } + } + }, "/openid4vc/verifier": { "post": { "operationId": "CreateVerifier", From a34d9360dada0a802a64341a1045cab637bc8e12 Mon Sep 17 00:00:00 2001 From: Krishna Waske Date: Wed, 25 Mar 2026 15:48:33 +0530 Subject: [PATCH 2/6] fix: naming convention and remove comments Signed-off-by: Krishna Waske --- src/controllers/did/DidController.ts | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/controllers/did/DidController.ts b/src/controllers/did/DidController.ts index d46efe0f..4b7ca2e5 100644 --- a/src/controllers/did/DidController.ts +++ b/src/controllers/did/DidController.ts @@ -368,22 +368,10 @@ export class DidController extends Controller { return body } - private async importDid(agent: AgentType, didMethod: string, did: string, seed: string, privateKey?: string, _keyId?: string) { - // TODO: Remove comments afterwards - // await agent.dids.import({ - // did: `${didMethod}:${did}`, - // overwrite: true, - // privateKeys: [ - // { - // keyType: KeyAlgorithm.Ed25519, - // privateKey: TypedArrayEncoder.fromString(seed), - // }, - // ], - // }) - - let keyId: string; + private async importDid(agent: AgentType, didMethod: string, did: string, seed: string, privateKey?: string, keyId?: string) { + let _keyId: string; - if (!_keyId) { + if (!keyId) { const { privateJwk } = privateKey ? transformPrivateKeyToPrivateJwk({ type: { crv: 'Ed25519', @@ -405,9 +393,9 @@ export class DidController extends Controller { } const key = await agent.kms.importKey({ privateJwk }) - keyId = key.keyId + _keyId = key.keyId } else { - keyId = _keyId + _keyId = keyId } @@ -416,7 +404,7 @@ export class DidController extends Controller { did: completeDid, keys: [ { - kmsKeyId: keyId, + kmsKeyId: _keyId, didDocumentRelativeKeyId: verkey, }, ], From 482bd7d2946f53fa652d9fe203dec7f5c31e6d89 Mon Sep 17 00:00:00 2001 From: Krishna Waske Date: Wed, 25 Mar 2026 16:30:05 +0530 Subject: [PATCH 3/6] fix: formatting Signed-off-by: Krishna Waske --- .../anoncreds/schema/SchemaController.ts | 10 ++- src/controllers/did/DidController.ts | 62 +++++++++++-------- src/controllers/types.ts | 39 +++++++----- src/enums/enum.ts | 2 +- 4 files changed, 70 insertions(+), 43 deletions(-) diff --git a/src/controllers/anoncreds/schema/SchemaController.ts b/src/controllers/anoncreds/schema/SchemaController.ts index 716a2498..9bb1f9fb 100644 --- a/src/controllers/anoncreds/schema/SchemaController.ts +++ b/src/controllers/anoncreds/schema/SchemaController.ts @@ -26,7 +26,10 @@ export class SchemaController extends Controller { */ @Example(SchemaExample) @Get('/:schemaId') - public async getSchemaById(@Request() request: Req, @Path('schemaId') schemaId: SchemaId): Promise { + public async getSchemaById( + @Request() request: Req, + @Path('schemaId') schemaId: SchemaId, + ): Promise { try { const schemBySchemaId = await request.agent.modules.anoncreds.getSchema(schemaId) @@ -58,7 +61,10 @@ export class SchemaController extends Controller { */ @Post('/') @Example(CreateSchemaSuccessful) - public async createSchema(@Request() request: Req, @Body() schema: CreateSchemaInput): Promise { + public async createSchema( + @Request() request: Req, + @Body() schema: CreateSchemaInput, + ): Promise { try { const { issuerId, name, version, attributes } = schema diff --git a/src/controllers/did/DidController.ts b/src/controllers/did/DidController.ts index 4b7ca2e5..f5c56ce3 100644 --- a/src/controllers/did/DidController.ts +++ b/src/controllers/did/DidController.ts @@ -202,7 +202,7 @@ export class DidController extends Controller { if (createDidOptions.did) { // Hint: Bcovrin uses seed as private key when creating key. But seed is written as a NYM transaction // Triage: Make sure what to use, seed or privateKey when accepting from API itself - await this.importDid(agent, didMethod, createDidOptions.did, "", createDidOptions.seed) + await this.importDid(agent, didMethod, createDidOptions.did, '', createDidOptions.seed) const getDid = await agent.dids.getCreatedDids({ method: createDidOptions.method, did: `did:${createDidOptions.method}:${createDidOptions.network}:${createDidOptions.did}`, @@ -226,7 +226,7 @@ export class DidController extends Controller { seed: createDidOptions.seed, }) const { did } = res?.data || {} - await this.importDid(agent, didMethod, did, "", createDidOptions.seed) + await this.importDid(agent, didMethod, did, '', createDidOptions.seed) const didRecord = await agent.dids.getCreatedDids({ method: DidMethod.Indy, did: `did:${DidMethod.Indy}:${Network.Bcovrin_Testnet}:${res.data.did}`, @@ -272,7 +272,7 @@ export class DidController extends Controller { didDocument: didDocument, } } else { - const {keyId, ...key} = await this.createIndicioKey(agent, createDidOptions) + const { keyId, ...key } = await this.createIndicioKey(agent, createDidOptions) const INDICIO_NYM_URL = process.env.INDICIO_NYM_URL as string const res = await axios.post(INDICIO_NYM_URL, key) if (res.data.statusCode === 200) { @@ -337,7 +337,7 @@ export class DidController extends Controller { }).privateJwk const key = await agent.kms.importKey({ - privateJwk + privateJwk, }) const verificationKey = Kms.PublicJwk.fromPublicJwk(key.publicJwk) as Kms.PublicJwk @@ -353,14 +353,14 @@ export class DidController extends Controller { network: 'testnet', did, verkey: TypedArrayEncoder.toBase58(publicKeyBytes), - keyId: key.keyId + keyId: key.keyId, } } else if (createDidOptions.network === Network.Indicio_Demonet) { body = { network: 'demonet', did, verkey: TypedArrayEncoder.toBase58(publicKeyBytes), - keyId: key.keyId + keyId: key.keyId, } } else { throw new BadRequestError('Please provide a valid did method') @@ -368,37 +368,47 @@ export class DidController extends Controller { return body } - private async importDid(agent: AgentType, didMethod: string, did: string, seed: string, privateKey?: string, keyId?: string) { - let _keyId: string; + private async importDid( + agent: AgentType, + didMethod: string, + did: string, + seed: string, + privateKey?: string, + keyId?: string, + ) { + let _keyId: string if (!keyId) { - const { privateJwk } = privateKey ? transformPrivateKeyToPrivateJwk({ - type: { - crv: 'Ed25519', - kty: 'OKP', - }, - privateKey: TypedArrayEncoder.fromString(privateKey), - }) : seed ? transformSeedToPrivateJwk({ - seed: TypedArrayEncoder.fromString(seed), - type: { - crv: 'Ed25519', - kty: 'OKP', - } - }) : { - privateJwk: undefined - } + const { privateJwk } = privateKey + ? transformPrivateKeyToPrivateJwk({ + type: { + crv: 'Ed25519', + kty: 'OKP', + }, + privateKey: TypedArrayEncoder.fromString(privateKey), + }) + : seed + ? transformSeedToPrivateJwk({ + seed: TypedArrayEncoder.fromString(seed), + type: { + crv: 'Ed25519', + kty: 'OKP', + }, + }) + : { + privateJwk: undefined, + } if (!privateJwk) { - throw new Error("Either privateKey or seed is required") + throw new Error('Either privateKey or seed is required') } - + const key = await agent.kms.importKey({ privateJwk }) _keyId = key.keyId } else { _keyId = keyId } - const completeDid = `${didMethod}:${did}` await agent.dids.import({ did: completeDid, diff --git a/src/controllers/types.ts b/src/controllers/types.ts index ac7febb5..884348ab 100644 --- a/src/controllers/types.ts +++ b/src/controllers/types.ts @@ -1,5 +1,12 @@ import type { RecordId } from './examples' -import type { AnonCredsDidCommCredentialFormat, LegacyIndyCredentialFormat, RegisterSchemaReturnStateAction, RegisterSchemaReturnStateFailed, RegisterSchemaReturnStateFinished, RegisterSchemaReturnStateWait } from '@credo-ts/anoncreds' +import type { + AnonCredsDidCommCredentialFormat, + LegacyIndyCredentialFormat, + RegisterSchemaReturnStateAction, + RegisterSchemaReturnStateFailed, + RegisterSchemaReturnStateFinished, + RegisterSchemaReturnStateWait, +} from '@credo-ts/anoncreds' import type { DidResolutionMetadata, DidDocumentMetadata, @@ -495,20 +502,24 @@ export type EcType = { } export interface SchemaResponseDTO { - schemaId: string; + schemaId: string schema?: { - issuerId: string; - name: string; - version: string; - attrNames: string[]; - }; - resolutionMetadata: Record; // Use Record or explicitly define what you need - schemaMetadata: Record; + issuerId: string + name: string + version: string + attrNames: string[] + } + resolutionMetadata: Record // Use Record or explicitly define what you need + schemaMetadata: Record } export interface RegisterSchemaReturn { - jobId?: string; - schemaState: RegisterSchemaReturnStateWait | RegisterSchemaReturnStateAction | RegisterSchemaReturnStateFinished | RegisterSchemaReturnStateFailed; - schemaMetadata: Record; - registrationMetadata: Record; -} \ No newline at end of file + jobId?: string + schemaState: + | RegisterSchemaReturnStateWait + | RegisterSchemaReturnStateAction + | RegisterSchemaReturnStateFinished + | RegisterSchemaReturnStateFailed + schemaMetadata: Record + registrationMetadata: Record +} diff --git a/src/enums/enum.ts b/src/enums/enum.ts index 72dcd9fa..ed45ac7b 100644 --- a/src/enums/enum.ts +++ b/src/enums/enum.ts @@ -48,7 +48,7 @@ export enum IndicioAcceptanceMechanism { For_Session = 'for_session', On_File = 'on_file', Product_Eula = 'product_eula', - Service_Agreement = 'service_agreement' + Service_Agreement = 'service_agreement', } export enum EndorserMode { From 5f8664f05cc8409f8d71bd927e43259ced7d9bab Mon Sep 17 00:00:00 2001 From: Krishna Waske Date: Wed, 25 Mar 2026 16:32:36 +0530 Subject: [PATCH 4/6] fix: remove unused param Signed-off-by: Krishna Waske --- samples/cliConfig.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/samples/cliConfig.json b/samples/cliConfig.json index 1af1bfad..6743b9b4 100644 --- a/samples/cliConfig.json +++ b/samples/cliConfig.json @@ -12,17 +12,14 @@ "indyLedger": [ { "genesisTransactions": "https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis", - "isProduction": false, "indyNamespace": "indicio:testnet" }, { "genesisTransactions": "https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_demonet_genesis", - "isProduction": false, "indyNamespace": "indicio:demonet" }, { "genesisTransactions": "https://test.bcovrin.vonx.io/genesis", - "isProduction": false, "indyNamespace": "bcovrin:testnet" } ], From b707c76e2147a59817bff5449eb11a777f85b43d Mon Sep 17 00:00:00 2001 From: Krishna Waske Date: Wed, 25 Mar 2026 17:11:21 +0530 Subject: [PATCH 5/6] fix: credential definition controller Signed-off-by: Krishna Waske --- .../CredentialDefinitionController.ts | 263 ++++++------ src/controllers/types.ts | 25 ++ src/routes/routes.ts | 162 ++++++++ src/routes/swagger.json | 390 ++++++++++++++++++ 4 files changed, 711 insertions(+), 129 deletions(-) diff --git a/src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts b/src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts index 57f47061..513d18e9 100644 --- a/src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts +++ b/src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts @@ -1,142 +1,147 @@ -// import type { RestAgentModules } from '../../../cliAgent' -// import type { SchemaId } from '../../examples' +import type { RestAgentModules } from '../../../cliAgent' +import type { SchemaId } from '../../examples' -// import { getUnqualifiedCredentialDefinitionId, parseIndyCredentialDefinitionId } from '@credo-ts/anoncreds' -// import { Agent } from '@credo-ts/core' -// import { Request as Req } from 'express' -// import { Body, Controller, Example, Get, Path, Post, Route, Tags, Security, Response, Request } from 'tsoa' -// import { injectable } from 'tsyringe' +import { getUnqualifiedCredentialDefinitionId, parseIndyCredentialDefinitionId } from '@credo-ts/anoncreds' +import { Agent } from '@credo-ts/core' +import { Request as Req } from 'express' +import { Body, Controller, Example, Get, Path, Post, Route, Tags, Security, Response, Request } from 'tsoa' +import { injectable } from 'tsyringe' -// import { CredentialEnum, EndorserMode, SchemaError, SCOPES } from '../../../enums' -// import ErrorHandlingService from '../../../errorHandlingService' -// import { ENDORSER_DID_NOT_PRESENT } from '../../../errorMessages' -// import { BadRequestError, InternalServerError, NotFoundError } from '../../../errors/errors' -// import { CredentialDefinitionExample, CredentialDefinitionId } from '../../examples' +import { CredentialEnum, EndorserMode, SchemaError, SCOPES } from '../../../enums' +import ErrorHandlingService from '../../../errorHandlingService' +import { ENDORSER_DID_NOT_PRESENT } from '../../../errorMessages' +import { BadRequestError, InternalServerError, NotFoundError } from '../../../errors/errors' +import { CredentialDefinitionExample, CredentialDefinitionId } from '../../examples' +import { + CredentialDefinitionStates, + GetCredentialDefinitionReturn, + RegisterCredentialDefinitionReturn, +} from '../../types' -// @Tags('Anoncreds - Credential Definitions') -// @Route('/anoncreds/credential-definitions') -// @Security('jwt', [SCOPES.TENANT_AGENT, SCOPES.DEDICATED_AGENT]) -// @injectable() -// export class CredentialDefinitionController extends Controller { -// /** -// * Retrieve credential definition by credential definition id -// * -// * @param credentialDefinitionId -// * @returns CredDef -// */ -// @Example(CredentialDefinitionExample) -// @Get('/:credentialDefinitionId') -// public async getCredentialDefinitionById( -// @Request() request: Req, -// @Path('credentialDefinitionId') credentialDefinitionId: CredentialDefinitionId, -// ) { -// try { -// const credentialDefinitionResult = -// await request.agent.modules.anoncreds.getCredentialDefinition(credentialDefinitionId) +@Tags('Anoncreds - Credential Definitions') +@Route('/anoncreds/credential-definitions') +@Security('jwt', [SCOPES.TENANT_AGENT, SCOPES.DEDICATED_AGENT]) +@injectable() +export class CredentialDefinitionController extends Controller { + /** + * Retrieve credential definition by credential definition id + * + * @param credentialDefinitionId + * @returns CredDef + */ + @Example(CredentialDefinitionExample) + @Get('/:credentialDefinitionId') + public async getCredentialDefinitionById( + @Request() request: Req, + @Path('credentialDefinitionId') credentialDefinitionId: CredentialDefinitionId, + ): Promise { + try { + const credentialDefinitionResult = + await request.agent.modules.anoncreds.getCredentialDefinition(credentialDefinitionId) -// if (credentialDefinitionResult.resolutionMetadata?.error === SchemaError.NotFound) { -// throw new NotFoundError(credentialDefinitionResult.resolutionMetadata.message) -// } -// const error = credentialDefinitionResult.resolutionMetadata?.error + if (credentialDefinitionResult.resolutionMetadata?.error === SchemaError.NotFound) { + throw new NotFoundError(credentialDefinitionResult.resolutionMetadata.message) + } + const error = credentialDefinitionResult.resolutionMetadata?.error -// if (error === 'invalid' || error === SchemaError.UnSupportedAnonCredsMethod) { -// throw new BadRequestError(credentialDefinitionResult.resolutionMetadata.message) -// } + if (error === 'invalid' || error === SchemaError.UnSupportedAnonCredsMethod) { + throw new BadRequestError(credentialDefinitionResult.resolutionMetadata.message) + } -// if (error !== undefined || credentialDefinitionResult.credentialDefinition === undefined) { -// throw new InternalServerError(credentialDefinitionResult.resolutionMetadata.message) -// } + if (error !== undefined || credentialDefinitionResult.credentialDefinition === undefined) { + throw new InternalServerError(credentialDefinitionResult.resolutionMetadata.message) + } -// return credentialDefinitionResult -// } catch (error) { -// throw ErrorHandlingService.handle(error) -// } -// } + return credentialDefinitionResult + } catch (error) { + throw ErrorHandlingService.handle(error) + } + } -// /** -// * Creates a new credential definition. -// * -// * @param credentialDefinitionRequest -// * @returns CredDef -// */ -// @Example(CredentialDefinitionExample) -// @Response(200, 'Action required') -// @Response(202, 'Wait for action to complete') -// @Post('/') -// public async createCredentialDefinition( -// @Request() request: Req, -// @Body() -// credentialDefinitionRequest: { -// issuerId: string -// schemaId: SchemaId -// tag: string -// endorse?: boolean -// endorserDid?: string -// }, -// ) { -// try { -// const { issuerId, schemaId, tag, endorse, endorserDid } = credentialDefinitionRequest -// credentialDefinitionRequest.endorse = credentialDefinitionRequest.endorse -// ? credentialDefinitionRequest.endorse -// : false -// const credDef = { -// issuerId, -// schemaId, -// tag, -// type: 'CL', -// } -// const credentialDefinitionPayload = { -// credentialDefinition: credDef, -// options: { -// endorserMode: '', -// endorserDid: '', -// supportRevocation: false, -// }, -// } -// if (!endorse) { -// credentialDefinitionPayload.options.endorserMode = EndorserMode.Internal -// credentialDefinitionPayload.options.endorserDid = issuerId -// } else { -// if (!endorserDid) { -// throw new BadRequestError(ENDORSER_DID_NOT_PRESENT) -// } -// credentialDefinitionPayload.options.endorserMode = EndorserMode.External -// credentialDefinitionPayload.options.endorserDid = endorserDid ? endorserDid : '' -// } + /** + * Creates a new credential definition. + * + * @param credentialDefinitionRequest + * @returns CredDef + */ + @Example(CredentialDefinitionExample) + @Response(200, 'Action required') + @Response(202, 'Wait for action to complete') + @Post('/') + public async createCredentialDefinition( + @Request() request: Req, + @Body() + credentialDefinitionRequest: { + issuerId: string + schemaId: SchemaId + tag: string + endorse?: boolean + endorserDid?: string + }, + ): Promise { + try { + const { issuerId, schemaId, tag, endorse, endorserDid } = credentialDefinitionRequest + credentialDefinitionRequest.endorse = credentialDefinitionRequest.endorse + ? credentialDefinitionRequest.endorse + : false + const credDef = { + issuerId, + schemaId, + tag, + type: 'CL', + } + const credentialDefinitionPayload = { + credentialDefinition: credDef, + options: { + endorserMode: '', + endorserDid: '', + supportRevocation: false, + }, + } + if (!endorse) { + credentialDefinitionPayload.options.endorserMode = EndorserMode.Internal + credentialDefinitionPayload.options.endorserDid = issuerId + } else { + if (!endorserDid) { + throw new BadRequestError(ENDORSER_DID_NOT_PRESENT) + } + credentialDefinitionPayload.options.endorserMode = EndorserMode.External + credentialDefinitionPayload.options.endorserDid = endorserDid ? endorserDid : '' + } -// const registerCredentialDefinitionResult = -// await request.agent.modules.anoncreds.registerCredentialDefinition(credentialDefinitionPayload) + const registerCredentialDefinitionResult = + await request.agent.modules.anoncreds.registerCredentialDefinition(credentialDefinitionPayload) -// if (registerCredentialDefinitionResult.credentialDefinitionState.state === CredentialEnum.Failed) { -// throw new InternalServerError('Falied to register credef on ledger') -// } + if (registerCredentialDefinitionResult.credentialDefinitionState.state === CredentialEnum.Failed) { + throw new InternalServerError('Falied to register credef on ledger') + } -// if (registerCredentialDefinitionResult.credentialDefinitionState.state === CredentialEnum.Wait) { -// // The request has been accepted for processing, but the processing has not been completed. -// this.setStatus(202) -// return registerCredentialDefinitionResult -// } + if (registerCredentialDefinitionResult.credentialDefinitionState.state === CredentialEnum.Wait) { + // The request has been accepted for processing, but the processing has not been completed. + this.setStatus(202) + return registerCredentialDefinitionResult + } -// if (registerCredentialDefinitionResult.credentialDefinitionState.state === CredentialEnum.Action) { -// return registerCredentialDefinitionResult -// } + if (registerCredentialDefinitionResult.credentialDefinitionState.state === CredentialEnum.Action) { + return registerCredentialDefinitionResult + } -// // TODO: Return uniform response for both Internally and Externally endorsed Schemas -// if (!endorse) { -// const indyCredDefId = parseIndyCredentialDefinitionId( -// registerCredentialDefinitionResult.credentialDefinitionState.credentialDefinitionId as string, -// ) -// const getCredentialDefinitionId = await getUnqualifiedCredentialDefinitionId( -// indyCredDefId.namespaceIdentifier, -// indyCredDefId.schemaSeqNo, -// indyCredDefId.tag, -// ) -// registerCredentialDefinitionResult.credentialDefinitionState.credentialDefinitionId = getCredentialDefinitionId -// return registerCredentialDefinitionResult.credentialDefinitionState -// } -// return registerCredentialDefinitionResult -// } catch (error) { -// throw ErrorHandlingService.handle(error) -// } -// } -// } + // TODO: Return uniform response for both Internally and Externally endorsed Schemas + if (!endorse) { + const indyCredDefId = parseIndyCredentialDefinitionId( + registerCredentialDefinitionResult.credentialDefinitionState.credentialDefinitionId as string, + ) + const getCredentialDefinitionId = await getUnqualifiedCredentialDefinitionId( + indyCredDefId.namespaceIdentifier, + indyCredDefId.schemaSeqNo, + indyCredDefId.tag, + ) + registerCredentialDefinitionResult.credentialDefinitionState.credentialDefinitionId = getCredentialDefinitionId + return registerCredentialDefinitionResult.credentialDefinitionState + } + return registerCredentialDefinitionResult + } catch (error) { + throw ErrorHandlingService.handle(error) + } + } +} diff --git a/src/controllers/types.ts b/src/controllers/types.ts index 884348ab..23ea0e8d 100644 --- a/src/controllers/types.ts +++ b/src/controllers/types.ts @@ -1,7 +1,12 @@ import type { RecordId } from './examples' import type { + AnonCredsCredentialDefinition, AnonCredsDidCommCredentialFormat, LegacyIndyCredentialFormat, + RegisterCredentialDefinitionReturnStateAction, + RegisterCredentialDefinitionReturnStateFailed, + RegisterCredentialDefinitionReturnStateFinished, + RegisterCredentialDefinitionReturnStateWait, RegisterSchemaReturnStateAction, RegisterSchemaReturnStateFailed, RegisterSchemaReturnStateFinished, @@ -523,3 +528,23 @@ export interface RegisterSchemaReturn { schemaMetadata: Record registrationMetadata: Record } + +export interface GetCredentialDefinitionReturn { + credentialDefinition?: AnonCredsCredentialDefinition + credentialDefinitionId: string + resolutionMetadata: Record + credentialDefinitionMetadata: Record +} + +export type CredentialDefinitionStates = + | RegisterCredentialDefinitionReturnStateWait + | RegisterCredentialDefinitionReturnStateAction + | RegisterCredentialDefinitionReturnStateFinished + | RegisterCredentialDefinitionReturnStateFailed + +export interface RegisterCredentialDefinitionReturn { + jobId?: string + credentialDefinitionState: CredentialDefinitionStates + credentialDefinitionMetadata: Record + registrationMetadata: Record +} diff --git a/src/routes/routes.ts b/src/routes/routes.ts index c5bc7cc9..6af71e35 100644 --- a/src/routes/routes.ts +++ b/src/routes/routes.ts @@ -32,6 +32,8 @@ import { AgentController } from './../controllers/agent/AgentController'; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa import { SchemaController } from './../controllers/anoncreds/schema/SchemaController'; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa +import { CredentialDefinitionController } from './../controllers/anoncreds/cred-def/CredentialDefinitionController'; +// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa import { VerifierController } from './../controllers/openid4vc/verifiers/verifier.Controller'; import { expressAuthentication } from './../authentication'; // @ts-ignore - no great way to install types from subpackage @@ -1635,6 +1637,92 @@ const models: TsoaRoute.Models = { "additionalProperties": false, }, // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "AnonCredsCredentialDefinition": { + "dataType": "refObject", + "properties": { + "issuerId": {"dataType":"string","required":true}, + "schemaId": {"dataType":"string","required":true}, + "type": {"dataType":"enum","enums":["CL"],"required":true}, + "tag": {"dataType":"string","required":true}, + "value": {"dataType":"nestedObjectLiteral","nestedProperties":{"revocation":{"dataType":"any"},"primary":{"ref":"Record_string.unknown_","required":true}},"required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "GetCredentialDefinitionReturn": { + "dataType": "refObject", + "properties": { + "credentialDefinition": {"ref":"AnonCredsCredentialDefinition"}, + "credentialDefinitionId": {"dataType":"string","required":true}, + "resolutionMetadata": {"ref":"Record_string.unknown_","required":true}, + "credentialDefinitionMetadata": {"ref":"Record_string.unknown_","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "CredentialDefinitionId": { + "dataType": "refAlias", + "type": {"dataType":"string","validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterCredentialDefinitionReturnStateWait": { + "dataType": "refObject", + "properties": { + "state": {"dataType":"enum","enums":["wait"],"required":true}, + "credentialDefinition": {"ref":"AnonCredsCredentialDefinition"}, + "credentialDefinitionId": {"dataType":"string"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterCredentialDefinitionReturnStateAction": { + "dataType": "refObject", + "properties": { + "state": {"dataType":"enum","enums":["action"],"required":true}, + "action": {"dataType":"string","required":true}, + "credentialDefinitionId": {"dataType":"string","required":true}, + "credentialDefinition": {"ref":"AnonCredsCredentialDefinition","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterCredentialDefinitionReturnStateFinished": { + "dataType": "refObject", + "properties": { + "state": {"dataType":"enum","enums":["finished"],"required":true}, + "credentialDefinition": {"ref":"AnonCredsCredentialDefinition","required":true}, + "credentialDefinitionId": {"dataType":"string","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterCredentialDefinitionReturnStateFailed": { + "dataType": "refObject", + "properties": { + "state": {"dataType":"enum","enums":["failed"],"required":true}, + "reason": {"dataType":"string","required":true}, + "credentialDefinition": {"ref":"AnonCredsCredentialDefinition"}, + "credentialDefinitionId": {"dataType":"string"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "CredentialDefinitionStates": { + "dataType": "refAlias", + "type": {"dataType":"union","subSchemas":[{"ref":"RegisterCredentialDefinitionReturnStateWait"},{"ref":"RegisterCredentialDefinitionReturnStateAction"},{"ref":"RegisterCredentialDefinitionReturnStateFinished"},{"ref":"RegisterCredentialDefinitionReturnStateFailed"}],"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "RegisterCredentialDefinitionReturn": { + "dataType": "refObject", + "properties": { + "jobId": {"dataType":"string"}, + "credentialDefinitionState": {"ref":"CredentialDefinitionStates","required":true}, + "credentialDefinitionMetadata": {"ref":"Record_string.unknown_","required":true}, + "registrationMetadata": {"ref":"Record_string.unknown_","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa "OpenId4VcVerifierRecord": { "dataType": "refAlias", "type": {"ref":"Record_string.unknown_","validators":{}}, @@ -4251,6 +4339,80 @@ export function RegisterRoutes(app: Router) { } }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + const argsCredentialDefinitionController_getCredentialDefinitionById: Record = { + request: {"in":"request","name":"request","required":true,"dataType":"object"}, + credentialDefinitionId: {"in":"path","name":"credentialDefinitionId","required":true,"ref":"CredentialDefinitionId"}, + }; + app.get('/anoncreds/credential-definitions/:credentialDefinitionId', + authenticateMiddleware([{"jwt":["tenant","dedicated"]}]), + ...(fetchMiddlewares(CredentialDefinitionController)), + ...(fetchMiddlewares(CredentialDefinitionController.prototype.getCredentialDefinitionById)), + + async function CredentialDefinitionController_getCredentialDefinitionById(request: ExRequest, response: ExResponse, next: any) { + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args: argsCredentialDefinitionController_getCredentialDefinitionById, request, response }); + + const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer; + + const controller: any = await container.get(CredentialDefinitionController); + if (typeof controller['setStatus'] === 'function') { + controller.setStatus(undefined); + } + + await templateService.apiHandler({ + methodName: 'getCredentialDefinitionById', + controller, + response, + next, + validatedArgs, + successStatus: undefined, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + const argsCredentialDefinitionController_createCredentialDefinition: Record = { + request: {"in":"request","name":"request","required":true,"dataType":"object"}, + credentialDefinitionRequest: {"in":"body","name":"credentialDefinitionRequest","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"endorserDid":{"dataType":"string"},"endorse":{"dataType":"boolean"},"tag":{"dataType":"string","required":true},"schemaId":{"ref":"SchemaId","required":true},"issuerId":{"dataType":"string","required":true}}}, + }; + app.post('/anoncreds/credential-definitions', + authenticateMiddleware([{"jwt":["tenant","dedicated"]}]), + ...(fetchMiddlewares(CredentialDefinitionController)), + ...(fetchMiddlewares(CredentialDefinitionController.prototype.createCredentialDefinition)), + + async function CredentialDefinitionController_createCredentialDefinition(request: ExRequest, response: ExResponse, next: any) { + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args: argsCredentialDefinitionController_createCredentialDefinition, request, response }); + + const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer; + + const controller: any = await container.get(CredentialDefinitionController); + if (typeof controller['setStatus'] === 'function') { + controller.setStatus(undefined); + } + + await templateService.apiHandler({ + methodName: 'createCredentialDefinition', + controller, + response, + next, + validatedArgs, + successStatus: undefined, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa const argsVerifierController_createVerifier: Record = { request: {"in":"request","name":"request","required":true,"dataType":"object"}, options: {"in":"body","name":"options","required":true,"ref":"OpenId4VcSiopCreateVerifierOptions"}, diff --git a/src/routes/swagger.json b/src/routes/swagger.json index 9c86bfe7..787e08ae 100644 --- a/src/routes/swagger.json +++ b/src/routes/swagger.json @@ -3723,6 +3723,213 @@ "type": "object", "additionalProperties": false }, + "AnonCredsCredentialDefinition": { + "properties": { + "issuerId": { + "type": "string" + }, + "schemaId": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "CL" + ], + "nullable": false + }, + "tag": { + "type": "string" + }, + "value": { + "properties": { + "revocation": {}, + "primary": { + "$ref": "#/components/schemas/Record_string.unknown_" + } + }, + "required": [ + "primary" + ], + "type": "object" + } + }, + "required": [ + "issuerId", + "schemaId", + "type", + "tag", + "value" + ], + "type": "object", + "additionalProperties": false + }, + "GetCredentialDefinitionReturn": { + "properties": { + "credentialDefinition": { + "$ref": "#/components/schemas/AnonCredsCredentialDefinition" + }, + "credentialDefinitionId": { + "type": "string" + }, + "resolutionMetadata": { + "$ref": "#/components/schemas/Record_string.unknown_" + }, + "credentialDefinitionMetadata": { + "$ref": "#/components/schemas/Record_string.unknown_" + } + }, + "required": [ + "credentialDefinitionId", + "resolutionMetadata", + "credentialDefinitionMetadata" + ], + "type": "object", + "additionalProperties": false + }, + "CredentialDefinitionId": { + "type": "string", + "example": "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag" + }, + "RegisterCredentialDefinitionReturnStateWait": { + "properties": { + "state": { + "type": "string", + "enum": [ + "wait" + ], + "nullable": false + }, + "credentialDefinition": { + "$ref": "#/components/schemas/AnonCredsCredentialDefinition" + }, + "credentialDefinitionId": { + "type": "string" + } + }, + "required": [ + "state" + ], + "type": "object", + "additionalProperties": false + }, + "RegisterCredentialDefinitionReturnStateAction": { + "properties": { + "state": { + "type": "string", + "enum": [ + "action" + ], + "nullable": false + }, + "action": { + "type": "string" + }, + "credentialDefinitionId": { + "type": "string" + }, + "credentialDefinition": { + "$ref": "#/components/schemas/AnonCredsCredentialDefinition" + } + }, + "required": [ + "state", + "action", + "credentialDefinitionId", + "credentialDefinition" + ], + "type": "object", + "additionalProperties": false + }, + "RegisterCredentialDefinitionReturnStateFinished": { + "properties": { + "state": { + "type": "string", + "enum": [ + "finished" + ], + "nullable": false + }, + "credentialDefinition": { + "$ref": "#/components/schemas/AnonCredsCredentialDefinition" + }, + "credentialDefinitionId": { + "type": "string" + } + }, + "required": [ + "state", + "credentialDefinition", + "credentialDefinitionId" + ], + "type": "object", + "additionalProperties": false + }, + "RegisterCredentialDefinitionReturnStateFailed": { + "properties": { + "state": { + "type": "string", + "enum": [ + "failed" + ], + "nullable": false + }, + "reason": { + "type": "string" + }, + "credentialDefinition": { + "$ref": "#/components/schemas/AnonCredsCredentialDefinition" + }, + "credentialDefinitionId": { + "type": "string" + } + }, + "required": [ + "state", + "reason" + ], + "type": "object", + "additionalProperties": false + }, + "CredentialDefinitionStates": { + "anyOf": [ + { + "$ref": "#/components/schemas/RegisterCredentialDefinitionReturnStateWait" + }, + { + "$ref": "#/components/schemas/RegisterCredentialDefinitionReturnStateAction" + }, + { + "$ref": "#/components/schemas/RegisterCredentialDefinitionReturnStateFinished" + }, + { + "$ref": "#/components/schemas/RegisterCredentialDefinitionReturnStateFailed" + } + ] + }, + "RegisterCredentialDefinitionReturn": { + "properties": { + "jobId": { + "type": "string" + }, + "credentialDefinitionState": { + "$ref": "#/components/schemas/CredentialDefinitionStates" + }, + "credentialDefinitionMetadata": { + "$ref": "#/components/schemas/Record_string.unknown_" + }, + "registrationMetadata": { + "$ref": "#/components/schemas/Record_string.unknown_" + } + }, + "required": [ + "credentialDefinitionState", + "credentialDefinitionMetadata", + "registrationMetadata" + ], + "type": "object", + "additionalProperties": false + }, "OpenId4VcVerifierRecord": { "$ref": "#/components/schemas/Record_string.unknown_", "description": "For OID4VC you need to expos metadata files. Each issuer needs to host this metadata. This is not the case for DIDComm where we can just have one /didcomm endpoint.\nSo we create a record per openid issuer/verifier that you want, and each tenant can create multiple issuers/verifiers which have different endpoints\nand metadata files" @@ -7765,6 +7972,189 @@ } } }, + "/anoncreds/credential-definitions/{credentialDefinitionId}": { + "get": { + "operationId": "GetCredentialDefinitionById", + "responses": { + "200": { + "description": "CredDef", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetCredentialDefinitionReturn" + }, + "examples": { + "Example 1": { + "value": { + "ver": "1.0", + "id": "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag", + "schemaId": "351936", + "type": "CL", + "tag": "definition", + "value": { + "primary": { + "n": "string", + "s": "string", + "r": { + "master_secret": "string", + "string": "string" + }, + "rctxt": "string", + "z": "string" + }, + "revocation": { + "g": "1 string", + "g_dash": "string", + "h": "string", + "h0": "string", + "h1": "string", + "h2": "string", + "htilde": "string", + "h_cap": "string", + "u": "string", + "pk": "string", + "y": "string" + } + } + } + } + } + } + } + } + }, + "description": "Retrieve credential definition by credential definition id", + "tags": [ + "Anoncreds - Credential Definitions" + ], + "security": [ + { + "jwt": [ + "tenant", + "dedicated" + ] + } + ], + "parameters": [ + { + "in": "path", + "name": "credentialDefinitionId", + "required": true, + "schema": { + "$ref": "#/components/schemas/CredentialDefinitionId" + } + } + ] + } + }, + "/anoncreds/credential-definitions": { + "post": { + "operationId": "CreateCredentialDefinition", + "responses": { + "200": { + "description": "CredDef", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/RegisterCredentialDefinitionReturn" + }, + { + "$ref": "#/components/schemas/CredentialDefinitionStates" + } + ] + }, + "examples": { + "Example 1": { + "value": { + "ver": "1.0", + "id": "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag", + "schemaId": "351936", + "type": "CL", + "tag": "definition", + "value": { + "primary": { + "n": "string", + "s": "string", + "r": { + "master_secret": "string", + "string": "string" + }, + "rctxt": "string", + "z": "string" + }, + "revocation": { + "g": "1 string", + "g_dash": "string", + "h": "string", + "h0": "string", + "h1": "string", + "h2": "string", + "htilde": "string", + "h_cap": "string", + "u": "string", + "pk": "string", + "y": "string" + } + } + } + } + } + } + } + }, + "202": { + "description": "Wait for action to complete" + } + }, + "description": "Creates a new credential definition.", + "tags": [ + "Anoncreds - Credential Definitions" + ], + "security": [ + { + "jwt": [ + "tenant", + "dedicated" + ] + } + ], + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "properties": { + "endorserDid": { + "type": "string" + }, + "endorse": { + "type": "boolean" + }, + "tag": { + "type": "string" + }, + "schemaId": { + "$ref": "#/components/schemas/SchemaId" + }, + "issuerId": { + "type": "string" + } + }, + "required": [ + "tag", + "schemaId", + "issuerId" + ], + "type": "object" + } + } + } + } + } + }, "/openid4vc/verifier": { "post": { "operationId": "CreateVerifier", From 82c62a6d16ed41d073e6423f887c0967408fc2fb Mon Sep 17 00:00:00 2001 From: Krishna Waske Date: Thu, 26 Mar 2026 12:54:50 +0530 Subject: [PATCH 6/6] fix: error when cred-def failure Signed-off-by: Krishna Waske --- .../anoncreds/cred-def/CredentialDefinitionController.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts b/src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts index 513d18e9..663bec90 100644 --- a/src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts +++ b/src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts @@ -113,7 +113,8 @@ export class CredentialDefinitionController extends Controller { await request.agent.modules.anoncreds.registerCredentialDefinition(credentialDefinitionPayload) if (registerCredentialDefinitionResult.credentialDefinitionState.state === CredentialEnum.Failed) { - throw new InternalServerError('Falied to register credef on ledger') + const failureReason = registerCredentialDefinitionResult.credentialDefinitionState?.reason ?? 'Failed to register credential definition on ledger' + throw new InternalServerError(failureReason) } if (registerCredentialDefinitionResult.credentialDefinitionState.state === CredentialEnum.Wait) {