diff --git a/packages/core/src/modules/dcql/DcqlService.ts b/packages/core/src/modules/dcql/DcqlService.ts index c0456a38c..8ca84de74 100644 --- a/packages/core/src/modules/dcql/DcqlService.ts +++ b/packages/core/src/modules/dcql/DcqlService.ts @@ -3,6 +3,7 @@ import type { AgentContext } from '../../agent' import { DcqlCredential, DcqlMdocCredential, DcqlQuery, DcqlSdJwtVcCredential } from 'dcql' import { injectable } from 'tsyringe' +import { JsonValue } from '../../types' import { Mdoc, MdocApi, MdocDeviceResponse, MdocOpenId4VpSessionTranscriptOptions, MdocRecord } from '../mdoc' import { SdJwtVcApi, SdJwtVcRecord, SdJwtVcService } from '../sd-jwt-vc' import { buildDisclosureFrameForPayload } from '../sd-jwt-vc/disclosureFrame' @@ -17,6 +18,19 @@ import { } from './models' import { dcqlGetPresentationsToCreate as getDcqlVcPresentationsToCreate } from './utils' +interface HasToJson { + toJson(): JsonValue +} + +function isToJsonable(value: unknown): value is HasToJson { + return ( + value !== null && + typeof value === 'object' && + 'toJson' in value && + typeof (value as HasToJson).toJson === 'function' + ) +} + /** * @todo create a public api for using dif presentation exchange */ @@ -99,10 +113,23 @@ export class DcqlService { const dcqlCredentials: DcqlCredential[] = credentialRecords.map((record) => { if (record.type === 'MdocRecord') { + const transformValue = (value: unknown): unknown => { + if (typeof value !== 'function' && typeof value !== 'object') return value + return isToJsonable(value) ? value.toJson() : 'unknown json representation' + } + + const mdoc = Mdoc.fromBase64Url(record.base64Url) + + const namespaces = Object.fromEntries( + Object.entries(mdoc.issuerSignedNamespaces).map(([key, namespace]) => [ + key, + Object.fromEntries(Object.entries(namespace).map(([k, v]) => [k, transformValue(v)])), + ]) + ) return { credential_format: 'mso_mdoc', doctype: record.getTags().docType, - namespaces: Mdoc.fromBase64Url(record.base64Url).issuerSignedNamespaces, + namespaces, } satisfies DcqlMdocCredential } else if (record.type === 'SdJwtVcRecord') { return { @@ -123,9 +150,17 @@ export class DcqlService { if (result.success) { if (result.output.credential_format === 'vc+sd-jwt') { const sdJwtVcRecord = credentialRecords[result.input_credential_index] as SdJwtVcRecord - agentContext.dependencyManager + const claims = agentContext.dependencyManager .resolve(SdJwtVcService) .applyDisclosuresForPayload(sdJwtVcRecord.compactSdJwtVc, result.output.claims) + return [ + credential_query_id, + { + ...result, + output: { ...result.output, claims }, + record: credentialRecords[result.input_credential_index], + }, + ] } return [credential_query_id, { ...result, record: credentialRecords[result.input_credential_index] }]