@credo-ts/core
Version:
<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1
1 lines • 56.8 kB
Source Map (JSON)
{"version":3,"file":"DcqlService.mjs","names":["getDcqlVcPresentationsToCreate"],"sources":["../../../src/modules/dcql/DcqlService.ts"],"sourcesContent":["import {\n DcqlCredential,\n DcqlCredentialQuery,\n DcqlMdocCredential,\n DcqlPresentationResult,\n DcqlQuery,\n DcqlSdJwtVcCredential,\n DcqlW3cVcCredential,\n} from 'dcql'\nimport type { AgentContext } from '../../agent'\nimport { injectable } from '../../plugins'\nimport { isNonEmptyArray, type JsonObject, type JsonValue, mapNonEmptyArray } from '../../types'\nimport { asArray, TypedArrayEncoder } from '../../utils'\nimport {\n CredentialMultiInstanceUseMode,\n canUseInstanceFromCredentialRecord,\n useInstanceFromCredentialRecord,\n} from '../../utils/credentialUse'\nimport { DidsApi, getPublicJwkFromVerificationMethod, VerificationMethod } from '../dids'\nimport type { VerifiableCredential, VerifiablePresentation } from '../dif-presentation-exchange/index'\nimport {\n Mdoc,\n MdocApi,\n MdocDeviceResponse,\n type MdocNameSpaces,\n MdocRecord,\n type MdocSessionTranscriptOptions,\n} from '../mdoc'\nimport { SdJwtVcApi, SdJwtVcRecord, SdJwtVcService } from '../sd-jwt-vc'\nimport { buildDisclosureFrameForPayload } from '../sd-jwt-vc/disclosureFrame'\nimport {\n ClaimFormat,\n SignatureSuiteRegistry,\n W3cCredentialRecord,\n W3cCredentialRepository,\n W3cCredentialService,\n W3cJsonLdCredentialService,\n W3cJsonLdVerifiableCredential,\n W3cPresentation,\n W3cV2CredentialRecord,\n W3cV2CredentialRepository,\n W3cV2CredentialService,\n W3cV2EnvelopedVerifiableCredential,\n W3cV2Presentation,\n} from '../vc'\nimport { purposes } from '../vc/data-integrity/libraries/jsonld-signatures'\nimport { W3cV2SdJwtCredentialService, W3cV2SdJwtVerifiableCredential } from '../vc/sd-jwt-vc'\nimport { X509Certificate } from '../x509'\nimport { DcqlError } from './DcqlError'\nimport type {\n DcqlCredentialsForRequest,\n DcqlEncodedPresentations,\n DcqlFailedCredential,\n DcqlPresentation,\n DcqlQueryResult,\n DcqlValidCredential,\n} from './models'\nimport { dcqlGetPresentationsToCreate as getDcqlVcPresentationsToCreate } from './utils'\n\nexport interface DcqlSelectCredentialsForRequestOptions {\n /**\n * The usage mode to apply to the credentials when selecting credentials.\n *\n * If and usage mode is selected that require a new instance to be used, and there's no\n * new instances available, an error will be thrown.\n *\n * It does not actually select the credential from the record yet, it just filters\n * out records that don't match the filter.\n */\n useMode?: CredentialMultiInstanceUseMode\n}\n\n@injectable()\nexport class DcqlService {\n /**\n * Queries the wallet for credentials that match the given dcql query. This only does an initial query based on the\n * schema of the input descriptors. It does not do any further filtering based on the constraints in the input descriptors.\n */\n private async queryCredentialsForDcqlQuery(\n agentContext: AgentContext,\n dcqlQuery: DcqlQuery\n ): Promise<Array<SdJwtVcRecord | W3cCredentialRecord | W3cV2CredentialRecord | MdocRecord>> {\n const formats = new Set(dcqlQuery.credentials.map((c) => c.format))\n const allRecords: Array<SdJwtVcRecord | W3cCredentialRecord | W3cV2CredentialRecord | MdocRecord> = []\n\n const mdocDoctypes = dcqlQuery.credentials\n .filter((credentialQuery) => credentialQuery.format === 'mso_mdoc')\n .map((c) => c.meta?.doctype_value)\n\n const mdocApi = this.getMdocApi(agentContext)\n if (mdocDoctypes.every((doctype) => doctype !== undefined)) {\n const mdocRecords = await mdocApi.findAllByQuery({\n $or: mdocDoctypes.map((docType) => ({\n docType: docType,\n })),\n })\n allRecords.push(...mdocRecords)\n } else if (formats.has('mso_mdoc')) {\n const mdocRecords = await mdocApi.getAll()\n allRecords.push(...mdocRecords)\n }\n\n const sdJwts = dcqlQuery.credentials.filter(\n (credentialQuery): credentialQuery is DcqlCredentialQuery.SdJwtVc =>\n (credentialQuery.format === 'vc+sd-jwt' && !(credentialQuery.meta && 'type_values' in credentialQuery.meta)) ||\n credentialQuery.format === 'dc+sd-jwt'\n )\n\n const sdJwtVctValues = sdJwts.flatMap((c) => c.meta?.vct_values)\n\n const sdJwtVcApi = this.getSdJwtVcApi(agentContext)\n if (sdJwtVctValues.every((vct) => vct !== undefined)) {\n const sdjwtVcRecords = await sdJwtVcApi.findAllByQuery({\n $or: [\n // Look for direct vct match\n ...sdJwtVctValues.map((vct) => ({\n vct,\n })),\n // Or an extended vct value\n ...sdJwtVctValues.map((vct) => ({\n extendedVctValues: [vct],\n })),\n ],\n })\n allRecords.push(...sdjwtVcRecords)\n } else if (sdJwts.length > 0) {\n const sdJwtVcRecords = await sdJwtVcApi.getAll()\n allRecords.push(...sdJwtVcRecords)\n }\n\n const w3cCredentialRepository = agentContext.dependencyManager.resolve(W3cCredentialRepository)\n if (formats.has('jwt_vc_json')) {\n const w3cRecords = await w3cCredentialRepository.findByQuery(agentContext, {\n claimFormat: ClaimFormat.JwtVc,\n\n // For jwt_vc_json we query the non-expanded types\n $or: dcqlQuery.credentials\n .flatMap((c) => (c.format === 'jwt_vc_json' ? c.meta.type_values : []))\n .map((typeValues) => ({\n types: typeValues,\n })),\n })\n allRecords.push(...w3cRecords)\n }\n\n if (formats.has('ldp_vc')) {\n const w3cRecords = await w3cCredentialRepository.findByQuery(agentContext, {\n claimFormat: ClaimFormat.LdpVc,\n\n // For LDP_VC we query the expanded types\n $or: dcqlQuery.credentials\n .flatMap((c) => (c.format === 'jwt_vc_json' ? c.meta.type_values : []))\n .map((typeValues) => ({\n expandedTypes: typeValues,\n })),\n })\n allRecords.push(...w3cRecords)\n }\n\n const w3cSdJwts = dcqlQuery.credentials.filter(\n (credentialQuery): credentialQuery is DcqlCredentialQuery.W3cVc & { format: 'vc+sd-jwt' } =>\n credentialQuery.format === 'vc+sd-jwt' && !!credentialQuery.meta && 'type_values' in credentialQuery.meta\n )\n\n if (w3cSdJwts.length > 0) {\n const w3cV2CredentialRepository = agentContext.dependencyManager.resolve(W3cV2CredentialRepository)\n\n const w3cV2Records = await w3cV2CredentialRepository.findByQuery(agentContext, {\n claimFormat: ClaimFormat.SdJwtW3cVc,\n $or: dcqlQuery.credentials\n .flatMap((c) => (c.format === 'vc+sd-jwt' && c.meta && 'type_values' in c.meta ? c.meta.type_values : []))\n .map((typeValues) => ({\n types: typeValues,\n })),\n })\n\n allRecords.push(...w3cV2Records)\n }\n\n return allRecords\n }\n\n private getAuthorityForCredential(\n credential: VerifiableCredential | W3cV2EnvelopedVerifiableCredential\n ): DcqlCredential['authority'] {\n if (credential.claimFormat === ClaimFormat.SdJwtDc) {\n const akiValues = (credential.header.x5c as string[] | undefined)\n ?.map((c) => {\n const akiHex = X509Certificate.fromEncodedCertificate(c).authorityKeyIdentifier\n return akiHex ? TypedArrayEncoder.toBase64Url(TypedArrayEncoder.fromHex(akiHex)) : undefined\n })\n .filter((aki) => aki !== undefined)\n\n return akiValues && isNonEmptyArray(akiValues)\n ? ({\n type: 'aki',\n values: akiValues,\n } as const)\n : undefined\n }\n\n if (credential.claimFormat === ClaimFormat.MsoMdoc) {\n const akiValues = credential.issuerSignedCertificateChain\n .map((c) => {\n const akiHex = X509Certificate.fromRawCertificate(c).authorityKeyIdentifier\n return akiHex ? TypedArrayEncoder.toBase64Url(TypedArrayEncoder.fromHex(akiHex)) : undefined\n })\n .filter((aki) => aki !== undefined)\n\n return akiValues && isNonEmptyArray(akiValues)\n ? ({\n type: 'aki',\n values: akiValues,\n } as const)\n : undefined\n }\n\n return undefined\n }\n\n public async getDcqlCredentialRepresentation(\n agentContext: AgentContext,\n presentation: VerifiablePresentation,\n queryCredential: DcqlQuery['credentials'][number]\n ): Promise<DcqlCredential> {\n // SD-JWT credential can be used as both dc+sd-jwt and vc+sd-jwt\n // At some point we might want to look at the header value of the sd-jwt (vc+sd-jwt vc dc+sd-jwt)\n if (presentation.claimFormat === ClaimFormat.SdJwtDc) {\n const requestedVcts = queryCredential.format === 'dc+sd-jwt' ? queryCredential.meta?.vct_values : undefined\n\n let presentationVctValues = [presentation.payload.vct]\n // FIXME: we should probably add an option whether to resolve VCT if we didn't get a direct hit\n if (!requestedVcts?.includes(presentation.payload.vct)) {\n const typeMetadataChain = await agentContext\n .resolve(SdJwtVcService)\n .fetchTypeMetadata(agentContext, presentation, {\n throwErrorOnFetchError: false,\n throwErrorOnUnsupportedVctValue: false,\n })\n\n if (typeMetadataChain) {\n presentationVctValues = typeMetadataChain?.vctValues\n }\n }\n\n return {\n credential_format: queryCredential.format === 'dc+sd-jwt' ? 'dc+sd-jwt' : 'vc+sd-jwt',\n authority: this.getAuthorityForCredential(presentation),\n cryptographic_holder_binding: true,\n vct:\n presentationVctValues.find((presentationVctValue) => requestedVcts?.includes(presentationVctValue)) ??\n presentation.payload.vct,\n claims: presentation.prettyClaims as DcqlSdJwtVcCredential.Claims,\n } satisfies DcqlSdJwtVcCredential\n }\n if (presentation.claimFormat === ClaimFormat.MsoMdoc) {\n if (!presentation.deviceResponse.documents || presentation.deviceResponse.documents.length !== 1) {\n throw new DcqlError('MDOC presentations must contain exactly one document')\n }\n\n return {\n cryptographic_holder_binding: true,\n credential_format: 'mso_mdoc',\n authority: this.getAuthorityForCredential(new Mdoc(presentation.deviceResponse.documents[0].issuerSigned)),\n doctype: presentation.deviceResponse.documents[0].docType,\n namespaces: Object.entries(\n Object.fromEntries(presentation.deviceResponse.documents[0].issuerSigned.issuerNamespaces.issuerNamespaces)\n ).reduce(\n (prev, [key, value]) => ({\n // biome-ignore lint/performance/noAccumulatingSpread: time complexity not relevant here\n ...prev,\n [key]: value.reduce<Record<string, unknown>>(\n // biome-ignore lint/performance/noAccumulatingSpread: time complexity not relevant here\n (prev, curr) => ({ ...prev, [curr.elementIdentifier]: curr.elementValue }),\n {}\n ),\n }),\n {}\n ),\n } satisfies DcqlMdocCredential\n }\n if (presentation.claimFormat === ClaimFormat.JwtVp) {\n const vc = Array.isArray(presentation.verifiableCredential)\n ? presentation.verifiableCredential[0]\n : presentation.verifiableCredential\n\n return {\n cryptographic_holder_binding: true,\n credential_format: 'jwt_vc_json',\n authority: this.getAuthorityForCredential(vc),\n claims: vc.jsonCredential as { [key: string]: JsonValue },\n type: vc.type,\n } satisfies DcqlW3cVcCredential\n }\n if (presentation.claimFormat === ClaimFormat.LdpVp) {\n const vc = Array.isArray(presentation.verifiableCredential)\n ? (presentation.verifiableCredential[0] as W3cJsonLdVerifiableCredential)\n : (presentation.verifiableCredential as W3cJsonLdVerifiableCredential)\n\n const w3cJsonLdCredentialService = agentContext.dependencyManager.resolve(W3cJsonLdCredentialService)\n const expandedTypes = await w3cJsonLdCredentialService.getExpandedTypesForCredential(agentContext, vc)\n\n return {\n cryptographic_holder_binding: true,\n credential_format: 'ldp_vc',\n authority: this.getAuthorityForCredential(vc),\n claims: vc.jsonCredential as DcqlW3cVcCredential.Claims,\n type: expandedTypes,\n } satisfies DcqlW3cVcCredential\n }\n if (presentation.claimFormat === ClaimFormat.SdJwtW3cVp) {\n const envelopedVc = Array.isArray(presentation.resolvedPresentation.verifiableCredential)\n ? presentation.resolvedPresentation.verifiableCredential[0]\n : presentation.resolvedPresentation.verifiableCredential\n\n return {\n cryptographic_holder_binding: true,\n credential_format: 'vc+sd-jwt',\n authority: this.getAuthorityForCredential(envelopedVc),\n type: asArray(envelopedVc.resolvedCredential.type),\n claims: envelopedVc.resolvedCredential.toJSON() as { [key: string]: JsonValue },\n } satisfies DcqlW3cVcCredential\n }\n\n throw new DcqlError('Unsupported claim format for presentation')\n }\n\n public async getCredentialsForRequest(agentContext: AgentContext, dcqlQuery: DcqlQuery): Promise<DcqlQueryResult> {\n const credentialRecords = await this.queryCredentialsForDcqlQuery(agentContext, dcqlQuery)\n const credentialRecordsWithFormatDuplicates: typeof credentialRecords = []\n const parsedQuery = DcqlQuery.parse(dcqlQuery)\n\n const dcqlCredentials: DcqlCredential[] = credentialRecords.flatMap((record): DcqlCredential | DcqlCredential[] => {\n if (record.type === 'MdocRecord') {\n credentialRecordsWithFormatDuplicates.push(record)\n\n // We always extract the first mdoc for querying\n const mdoc = record.firstCredential\n\n return {\n authority: this.getAuthorityForCredential(mdoc),\n credential_format: 'mso_mdoc',\n doctype: mdoc.docType,\n namespaces: mdoc.issuerSignedNamespaces,\n cryptographic_holder_binding: true,\n } satisfies DcqlCredential\n }\n\n if (record.type === 'SdJwtVcRecord') {\n const sdJwtVc = record.firstCredential\n const claims = sdJwtVc.prettyClaims as DcqlSdJwtVcCredential.Claims\n\n // To keep correct mapping of input credential index, we add it multiple times here:\n // - for dc+sd-jwt and vc+sd-jwt\n // - for each extended VCT (until we have multi-vct support in DCQL)\n credentialRecordsWithFormatDuplicates.push(\n record,\n record,\n ...record.extendedVctValues.map(() => record),\n ...record.extendedVctValues.map(() => record)\n )\n\n return [\n {\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'dc+sd-jwt',\n vct: record.getTags().vct,\n claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlSdJwtVcCredential,\n ...record.extendedVctValues.map(\n (extendedVctValue) =>\n ({\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'dc+sd-jwt',\n vct: extendedVctValue,\n claims,\n cryptographic_holder_binding: true,\n }) satisfies DcqlSdJwtVcCredential\n ),\n {\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'vc+sd-jwt',\n vct: record.getTags().vct,\n claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlSdJwtVcCredential,\n ...record.extendedVctValues.map(\n (extendedVctValue) =>\n ({\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'vc+sd-jwt',\n vct: extendedVctValue,\n claims,\n cryptographic_holder_binding: true,\n }) satisfies DcqlSdJwtVcCredential\n ),\n ] satisfies DcqlSdJwtVcCredential[]\n }\n\n if (record.type === 'W3cCredentialRecord') {\n const firstCredential = record.firstCredential\n credentialRecordsWithFormatDuplicates.push(record)\n if (firstCredential.claimFormat === ClaimFormat.LdpVc) {\n return {\n credential_format: 'ldp_vc',\n authority: this.getAuthorityForCredential(firstCredential),\n type: record.getTags().expandedTypes ?? [],\n claims: firstCredential.jsonCredential as DcqlW3cVcCredential.Claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlW3cVcCredential\n }\n\n return {\n credential_format: 'jwt_vc_json',\n authority: this.getAuthorityForCredential(firstCredential),\n type: firstCredential.type,\n claims: firstCredential.jsonCredential as DcqlW3cVcCredential.Claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlW3cVcCredential\n }\n\n if (record.type === 'W3cV2CredentialRecord') {\n credentialRecordsWithFormatDuplicates.push(record)\n const firstCredential = record.firstCredential\n\n return {\n credential_format: 'vc+sd-jwt',\n authority: this.getAuthorityForCredential(firstCredential),\n type: asArray(firstCredential.resolvedCredential.type),\n claims: firstCredential.resolvedCredential.toJSON() as DcqlW3cVcCredential.Claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlW3cVcCredential\n }\n\n throw new DcqlError('Unsupported record type')\n })\n\n const queryResult = DcqlQuery.query(parsedQuery, dcqlCredentials)\n\n const matchesWithRecord = Object.fromEntries(\n Object.entries(queryResult.credential_matches).map(([credential_query_id, result]) => {\n const failedCredentials = result.failed_credentials\n ? mapNonEmptyArray(result.failed_credentials, (credential) => {\n const record = credentialRecordsWithFormatDuplicates[credential.input_credential_index]\n const updatedCredential: DcqlFailedCredential = {\n ...credential,\n record,\n claims: credential.claims.success\n ? {\n ...credential.claims,\n success: true,\n valid_claim_sets: mapNonEmptyArray(credential.claims.valid_claim_sets, (claimSet) => ({\n ...claimSet,\n ...(record.type === 'SdJwtVcRecord'\n ? // NOTE: we cast from SdJwtVcPayload (which is Record<string, unknown> to { [key: string]: JsonValue })\n // Otherwise TypeScript explains, but I'm not sure why Record<string, unknown> wouldn't be applicable to { [key: string]: JsonValue }\n {\n output: agentContext.dependencyManager\n .resolve(SdJwtVcService)\n .applyDisclosuresForPayload(record.encoded, claimSet.output as JsonObject)\n .prettyClaims as { [key: string]: JsonValue },\n }\n : record.type === 'W3cV2CredentialRecord' &&\n record.firstCredential instanceof W3cV2SdJwtVerifiableCredential\n ? {\n output: agentContext.dependencyManager\n .resolve(SdJwtVcService)\n .applyDisclosuresForPayload(\n record.firstCredential.encoded,\n claimSet.output as JsonObject\n ).prettyClaims as { [key: string]: JsonValue },\n }\n : {}),\n })),\n }\n : credential.claims,\n }\n return updatedCredential\n })\n : undefined\n\n // If not success, valid_credentials will be undefined, so we only have to map failed_credentials\n if (!result.success) {\n return [\n credential_query_id,\n {\n ...result,\n failed_credentials: failedCredentials,\n },\n ]\n }\n\n return [\n credential_query_id,\n {\n ...result,\n failed_credentials: failedCredentials,\n valid_credentials: mapNonEmptyArray(result.valid_credentials, (credential) => {\n const record = credentialRecordsWithFormatDuplicates[credential.input_credential_index]\n const updatedCredential: DcqlValidCredential = {\n ...credential,\n record,\n claims: {\n ...credential.claims,\n valid_claim_sets: mapNonEmptyArray(credential.claims.valid_claim_sets, (claimSet) => ({\n ...claimSet,\n ...(record.type === 'SdJwtVcRecord'\n ? // NOTE: we cast from SdJwtVcPayload (which is Record<string, unknown> to { [key: string]: JsonValue })\n // Otherwise TypeScript explains, but I'm not sure why Record<string, unknown> wouldn't be applicable to { [key: string]: JsonValue }\n {\n output: agentContext.dependencyManager\n .resolve(SdJwtVcService)\n .applyDisclosuresForPayload(record.encoded, claimSet.output as JsonObject).prettyClaims as {\n [key: string]: JsonValue\n },\n }\n : record.type === 'W3cV2CredentialRecord' &&\n record.firstCredential instanceof W3cV2SdJwtVerifiableCredential\n ? {\n output: agentContext.dependencyManager\n .resolve(SdJwtVcService)\n .applyDisclosuresForPayload(record.firstCredential.encoded, claimSet.output as JsonObject)\n .prettyClaims as { [key: string]: JsonValue },\n }\n : {}),\n })),\n },\n }\n return updatedCredential\n }),\n },\n ]\n })\n )\n\n return {\n ...queryResult,\n credential_matches: matchesWithRecord,\n }\n }\n\n public async assertValidDcqlPresentation(\n agentContext: AgentContext,\n dcqlPresentation: DcqlPresentation,\n dcqlQuery: DcqlQuery\n ) {\n const internalDcqlPresentation = Object.fromEntries(\n await Promise.all(\n Object.entries(dcqlPresentation).map(async ([credentialId, presentations]) => {\n const queryCredential = dcqlQuery.credentials.find((c) => c.id === credentialId)\n if (!queryCredential) {\n throw new DcqlError(\n `DCQL presentation contains presentation entry for credential id '${credentialId}', but this id is not present in the DCQL query`\n )\n }\n\n return [\n credentialId,\n await Promise.all(\n presentations.map((presentation) =>\n this.getDcqlCredentialRepresentation(agentContext, presentation, queryCredential)\n )\n ),\n ]\n })\n )\n )\n\n const presentationResult = DcqlPresentationResult.fromDcqlPresentation(internalDcqlPresentation, { dcqlQuery })\n\n if (!presentationResult.can_be_satisfied) {\n throw new DcqlError('Presentations do not satisfy the DCQL query.', {\n additionalMessages: Object.entries(presentationResult.credential_matches ?? {})\n .flatMap(([queryId, match]) =>\n match.success\n ? undefined\n : !match.failed_credentials\n ? `Unable to match query credential '${queryId}'. No prsentations provided`\n : match.failed_credentials.map(\n (failedCredential) =>\n `Presentation at index ${failedCredential.input_credential_index} does not match query credential '${queryId}'. ${JSON.stringify(\n {\n ...(failedCredential.claims.success\n ? {}\n : { claims: failedCredential.claims.failed_claim_sets.map((cs) => cs.issues) }),\n ...(failedCredential.trusted_authorities.success\n ? {}\n : {\n trusted_authorities:\n failedCredential.trusted_authorities.failed_trusted_authorities.map(\n (ta) => ta.issues\n ),\n }),\n ...(failedCredential.meta.success ? {} : { meta: failedCredential.meta.issues }),\n },\n null,\n 2\n )}`\n )\n )\n .filter((message) => message !== undefined),\n })\n }\n\n return presentationResult\n }\n\n private dcqlCredentialForRequestForValidCredential(validCredential: DcqlValidCredential) {\n if (validCredential.record.type === 'MdocRecord') {\n return {\n claimFormat: ClaimFormat.MsoMdoc,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.claims.valid_claim_sets[0].output as MdocNameSpaces,\n } as const\n }\n if (validCredential.record.type === 'SdJwtVcRecord') {\n return {\n claimFormat: ClaimFormat.SdJwtDc,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.claims.valid_claim_sets[0].output as JsonObject,\n } as const\n }\n\n if (validCredential.record.type === 'W3cCredentialRecord') {\n return {\n claimFormat: validCredential.record.firstCredential.claimFormat,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.record.firstCredential.jsonCredential as JsonObject,\n } as const\n }\n\n if (validCredential.record.type === 'W3cV2CredentialRecord') {\n return {\n claimFormat: validCredential.record.firstCredential.claimFormat,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.claims.valid_claim_sets[0].output as JsonObject,\n } as const\n }\n\n throw new DcqlError('Unsupported record type for DCQL')\n }\n\n /**\n * Selects the credentials to use based on the output from `getCredentialsForRequest`\n * Use this method if you don't want to manually select the credentials yourself.\n */\n public selectCredentialsForRequest(\n dcqlQueryResult: DcqlQueryResult,\n { useMode = CredentialMultiInstanceUseMode.NewOrFirst }: DcqlSelectCredentialsForRequestOptions = {}\n ): DcqlCredentialsForRequest {\n if (!dcqlQueryResult.can_be_satisfied) {\n throw new DcqlError(\n 'Cannot select the credentials for the dcql query presentation if the request cannot be satisfied'\n )\n }\n\n const credentials: DcqlCredentialsForRequest = {}\n\n if (dcqlQueryResult.credential_sets) {\n credentialSetLoop: for (const credentialSet of dcqlQueryResult.credential_sets) {\n // undefined defaults to true\n if (credentialSet.required === false) continue\n const fullfillableOptions = credentialSet.matching_options\n\n if (!fullfillableOptions) {\n throw new DcqlError('Invalid dcql query result. No option is fullfillable')\n }\n\n for (const fullfillableOption of fullfillableOptions) {\n const optionMatches = fullfillableOption.map((credentialQueryId) => {\n const credentialMatch = dcqlQueryResult.credential_matches[credentialQueryId]\n if (!credentialMatch.success) return undefined\n const match = credentialMatch.valid_credentials.find((match: DcqlValidCredential) =>\n canUseInstanceFromCredentialRecord({ credentialRecord: match.record, useMode })\n )\n\n if (!match) return undefined\n return {\n match,\n credentialQueryId,\n }\n })\n\n if (optionMatches.every((c) => c !== undefined)) {\n for (const { match, credentialQueryId } of optionMatches) {\n credentials[credentialQueryId] = [this.dcqlCredentialForRequestForValidCredential(match)]\n }\n\n continue credentialSetLoop\n }\n }\n\n throw new DcqlError(\n 'Unable to select credentials for credential set. No new credential instance available on any of the available credentials.'\n )\n }\n } else {\n for (const credentialQuery of dcqlQueryResult.credentials) {\n const credentialMatch = dcqlQueryResult.credential_matches[credentialQuery.id]\n if (!credentialMatch.success) {\n throw new DcqlError(\n `Invalid dcql query result for credential query id '${credentialQuery.id}'. Cannot auto-select credentials`\n )\n }\n\n const credential = credentialMatch.valid_credentials.find((match: DcqlValidCredential) =>\n canUseInstanceFromCredentialRecord({ credentialRecord: match.record, useMode })\n )\n if (!credential) {\n throw new DcqlError(\n `Unable to select credential for credential query id '${credentialQuery.id}'. No new credential instance available on any of the available credentials.`\n )\n }\n\n credentials[credentialQuery.id] = [this.dcqlCredentialForRequestForValidCredential(credential)]\n }\n }\n\n return credentials\n }\n\n public validateDcqlQuery(dcqlQuery: DcqlQuery | DcqlQuery.Input | unknown): DcqlQuery {\n const parsed = DcqlQuery.parse(dcqlQuery as DcqlQuery)\n DcqlQuery.validate(parsed)\n return parsed\n }\n\n public async createPresentation(\n agentContext: AgentContext,\n options: {\n credentialQueryToCredential: DcqlCredentialsForRequest\n challenge: string\n domain?: string\n mdocSessionTranscript?: MdocSessionTranscriptOptions\n }\n ): Promise<{\n dcqlPresentation: DcqlPresentation\n encodedDcqlPresentation: DcqlEncodedPresentations\n }> {\n const { domain, challenge, mdocSessionTranscript } = options\n\n const dcqlPresentation: DcqlPresentation = {}\n const encodedDcqlPresentation: DcqlEncodedPresentations = {}\n const vcPresentationsToCreate = getDcqlVcPresentationsToCreate(options.credentialQueryToCredential)\n\n for (const [credentialQueryId, presentationsToCreate] of Object.entries(vcPresentationsToCreate)) {\n for (const presentationToCreate of presentationsToCreate) {\n let createdPresentation: VerifiablePresentation\n let encodedCreatedPresentation: string | Record<string, unknown>\n\n if (presentationToCreate.claimFormat === ClaimFormat.MsoMdoc) {\n const mdocRecord = presentationToCreate.credentialRecord\n if (!mdocSessionTranscript) {\n throw new DcqlError('Missing mdoc session transcript options for creating MDOC presentation.')\n }\n\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: mdocRecord,\n })\n\n const deviceResponse = await MdocDeviceResponse.createDeviceResponse(agentContext, {\n mdocs: [credentialInstance],\n documentRequests: [\n {\n docType: mdocRecord.getTags().docType,\n nameSpaces: Object.fromEntries(\n Object.entries(presentationToCreate.disclosedPayload).map(([key, value]) => {\n // FIXME: we need the DCQL query here to get the intent_to_retain from query (currently hardcoded to false)\n return [key, Object.fromEntries(Object.entries(value).map(([key]) => [key, false]))]\n })\n ),\n },\n ],\n sessionTranscriptOptions: mdocSessionTranscript,\n })\n const deviceResponseBase64Url = deviceResponse.encoded\n\n encodedCreatedPresentation = deviceResponseBase64Url\n createdPresentation = MdocDeviceResponse.fromBase64Url(deviceResponseBase64Url)\n } else if (presentationToCreate.claimFormat === ClaimFormat.SdJwtDc) {\n const presentationFrame = buildDisclosureFrameForPayload(presentationToCreate.disclosedPayload)\n\n if (!domain) {\n throw new DcqlError('Missing domain property for creating SdJwtVc presentation.')\n }\n\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: presentationToCreate.credentialRecord,\n })\n\n const sdJwtVcApi = this.getSdJwtVcApi(agentContext)\n const presentation = await sdJwtVcApi.present({\n sdJwtVc: credentialInstance,\n presentationFrame,\n verifierMetadata: {\n audience: domain,\n nonce: challenge,\n issuedAt: Math.floor(Date.now() / 1000),\n },\n additionalPayload: presentationToCreate.additionalPayload,\n })\n\n encodedCreatedPresentation = presentation\n createdPresentation = sdJwtVcApi.fromCompact(presentation)\n } else if (presentationToCreate.claimFormat === ClaimFormat.JwtVp) {\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: presentationToCreate.credentialRecord,\n })\n\n if (!credentialInstance.credentialSubjectIds[0]) {\n throw new DcqlError('Cannot create presentation for credentials without subject id')\n }\n\n // Determine a suitable verification method for the presentation\n const verificationMethod = await this.getVerificationMethodForSubjectId(\n agentContext,\n credentialInstance.credentialSubjectIds[0]\n )\n\n const w3cCredentialService = agentContext.resolve(W3cCredentialService)\n const w3cPresentation = new W3cPresentation({\n verifiableCredential: [credentialInstance],\n holder: verificationMethod.controller,\n })\n\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n\n const signedPresentation = await w3cCredentialService.signPresentation<ClaimFormat.JwtVp>(agentContext, {\n format: ClaimFormat.JwtVp,\n alg: publicJwk.signatureAlgorithm,\n verificationMethod: verificationMethod.id,\n presentation: w3cPresentation,\n challenge,\n domain,\n })\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else if (presentationToCreate.claimFormat === ClaimFormat.LdpVp) {\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: presentationToCreate.credentialRecord,\n })\n\n if (!credentialInstance.credentialSubjectIds[0]) {\n throw new DcqlError('Cannot create presentation for credentials without subject id')\n }\n\n // Determine a suitable verification method for the presentation\n const verificationMethod = await this.getVerificationMethodForSubjectId(\n agentContext,\n credentialInstance.credentialSubjectIds[0]\n )\n\n const w3cCredentialService = agentContext.resolve(W3cCredentialService)\n const w3cPresentation = new W3cPresentation({\n verifiableCredential: [credentialInstance],\n holder: verificationMethod.controller,\n })\n\n const signedPresentation = await w3cCredentialService.signPresentation(agentContext, {\n format: ClaimFormat.LdpVp,\n // TODO: we should move the check for which proof to use for a presentation to earlier\n // as then we know when determining which VPs to submit already if the proof types are supported\n // by the verifier, and we can then just add this to the vpToCreate interface\n proofType: this.getProofTypeForLdpVc(agentContext, verificationMethod),\n proofPurpose: new purposes.AuthenticationProofPurpose({ challenge, domain }),\n verificationMethod: verificationMethod.id,\n presentation: w3cPresentation,\n challenge,\n domain,\n })\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else if (presentationToCreate.claimFormat === ClaimFormat.JwtW3cVp) {\n const w3cV2CredentialService = agentContext.resolve(W3cV2CredentialService)\n const w3cV2Presentation = new W3cV2Presentation({\n holder: presentationToCreate.credentialRecord.firstCredential.resolvedCredential.credentialSubjectIds[0],\n verifiableCredential: [\n W3cV2EnvelopedVerifiableCredential.fromVerifiableCredential(\n presentationToCreate.credentialRecord.firstCredential\n ),\n ],\n })\n\n const signedPresentation = await w3cV2CredentialService.signPresentation<ClaimFormat.JwtW3cVp>(agentContext, {\n format: ClaimFormat.JwtW3cVp,\n presentation: w3cV2Presentation,\n challenge,\n domain,\n })\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else if (presentationToCreate.claimFormat === ClaimFormat.SdJwtW3cVp) {\n const presentationFrame = buildDisclosureFrameForPayload(presentationToCreate.disclosedPayload)\n if (!domain) {\n throw new DcqlError('Missing domain property for creating SdJwtVc presentation.')\n }\n\n const w3cV2SdJwtCredentialService = agentContext.resolve(W3cV2SdJwtCredentialService)\n const sdJwtVc = await w3cV2SdJwtCredentialService.present(agentContext, {\n credential: presentationToCreate.credentialRecord.firstCredential.encoded,\n presentationFrame,\n })\n\n const w3cV2CredentialService = agentContext.resolve(W3cV2CredentialService)\n const w3cV2Presentation = new W3cV2Presentation({\n holder: presentationToCreate.credentialRecord.firstCredential.resolvedCredential.credentialSchemaIds[0],\n verifiableCredential: [W3cV2EnvelopedVerifiableCredential.fromVerifiableCredential(sdJwtVc)],\n })\n\n const signedPresentation = await w3cV2CredentialService.signPresentation<ClaimFormat.SdJwtW3cVp>(\n agentContext,\n {\n format: ClaimFormat.SdJwtW3cVp,\n presentation: w3cV2Presentation,\n challenge,\n domain,\n }\n )\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else {\n throw new DcqlError('Unsupported presentation format.')\n }\n\n if (!dcqlPresentation[credentialQueryId]) {\n dcqlPresentation[credentialQueryId] = [createdPresentation]\n } else {\n dcqlPresentation[credentialQueryId].push(createdPresentation)\n }\n\n if (!encodedDcqlPresentation[credentialQueryId]) {\n encodedDcqlPresentation[credentialQueryId] = [encodedCreatedPresentation]\n } else {\n encodedDcqlPresentation[credentialQueryId].push(encodedCreatedPresentation)\n }\n }\n }\n\n return {\n dcqlPresentation,\n encodedDcqlPresentation,\n }\n }\n\n private getSdJwtVcApi(agentContext: AgentContext) {\n return agentContext.dependencyManager.resolve(SdJwtVcApi)\n }\n\n private getMdocApi(agentContext: AgentContext) {\n return agentContext.dependencyManager.resolve(MdocApi)\n }\n\n private async getVerificationMethodForSubjectId(agentContext: AgentContext, subjectId: string) {\n const didsApi = agentContext.dependencyManager.resolve(DidsApi)\n\n if (!subjectId.startsWith('did:')) {\n throw new DcqlError(`Only dids are supported as credentialSubject id. ${subjectId} is not a valid did`)\n }\n\n const didDocument = await didsApi.resolveDidDocument(subjectId)\n\n if (!didDocument.authentication || didDocument.authentication.length === 0) {\n throw new DcqlError(`No authentication verificationMethods found for did ${subjectId} in did document`)\n }\n\n // the signature suite to use for the presentation is dependant on the credentials we share.\n // 1. Get the verification method for this given proof purpose in this DID document\n let [verificationMethod] = didDocument.authentication\n if (typeof verificationMethod === 'string') {\n verificationMethod = didDocument.dereferenceKey(verificationMethod, ['authentication'])\n }\n\n return verificationMethod\n }\n\n // FIXME: We need to take into account OpenID4VP metadata (probably providing supported/allowed algs to the DCQL create presentation method)\n private getProofTypeForLdpVc(agentContext: AgentContext, verificationMethod: VerificationMethod) {\n // For each of the supported algs, find the key types, then find the proof types\n const signatureSuiteRegistry = agentContext.dependencyManager.resolve(SignatureSuiteRegistry)\n\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n const supportedSignatureSuites = signatureSuiteRegistry.getAllByPublicJwkType(publicJwk)\n if (supportedSignatureSuites.length === 0) {\n throw new DcqlError(\n `Couldn't find a supported signature suite for the given jwk ${publicJwk.jwkTypeHumanDescription}`\n )\n }\n\n return supportedSignatureSuites[0].proofType\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEO,wBAAM,YAAY;;;;;CAKvB,MAAc,6BACZ,cACA,WAC0F;EAC1F,MAAM,UAAU,IAAI,IAAI,UAAU,YAAY,KAAK,MAAM,EAAE,OAAO,CAAC;EACnE,MAAM,aAA8F,EAAE;EAEtG,MAAM,eAAe,UAAU,YAC5B,QAAQ,oBAAoB,gBAAgB,WAAW,WAAW,CAClE,KAAK,MAAM,EAAE,MAAM,cAAc;EAEpC,MAAM,UAAU,KAAK,WAAW,aAAa;AAC7C,MAAI,aAAa,OAAO,YAAY,YAAY,OAAU,EAAE;GAC1D,MAAM,cAAc,MAAM,QAAQ,eAAe,EAC/C,KAAK,aAAa,KAAK,aAAa,EACzB,SACV,EAAE,EACJ,CAAC;AACF,cAAW,KAAK,GAAG,YAAY;aACtB,QAAQ,IAAI,WAAW,EAAE;GAClC,MAAM,cAAc,MAAM,QAAQ,QAAQ;AAC1C,cAAW,KAAK,GAAG,YAAY;;EAGjC,MAAM,SAAS,UAAU,YAAY,QAClC,oBACE,gBAAgB,WAAW,eAAe,EAAE,gBAAgB,QAAQ,iBAAiB,gBAAgB,SACtG,gBAAgB,WAAW,YAC9B;EAED,MAAM,iBAAiB,OAAO,SAAS,MAAM,EAAE,MAAM,WAAW;EAEhE,MAAM,aAAa,KAAK,cAAc,aAAa;AACnD,MAAI,eAAe,OAAO,QAAQ,QAAQ,OAAU,EAAE;GACpD,MAAM,iBAAiB,MAAM,WAAW,eAAe,EACrD,KAAK,CAEH,GAAG,eAAe,KAAK,SAAS,EAC9B,KACD,EAAE,EAEH,GAAG,eAAe,KAAK,SAAS,EAC9B,mBAAmB,CAAC,IAAI,EACzB,EAAE,CACJ,EACF,CAAC;AACF,cAAW,KAAK,GAAG,eAAe;aACzB,OAAO,SAAS,GAAG;GAC5B,MAAM,iBAAiB,MAAM,WAAW,QAAQ;AAChD,cAAW,KAAK,GAAG,eAAe;;EAGpC,MAAM,0BAA0B,aAAa,kBAAkB,QAAQ,wBAAwB;AAC/F,MAAI,QAAQ,IAAI,cAAc,EAAE;GAC9B,MAAM,aAAa,MAAM,wBAAwB,YAAY,cAAc;IACzE,aAAa,YAAY;IAGzB,KAAK,UAAU,YACZ,SAAS,MAAO,EAAE,WAAW,gBAAgB,EAAE,KAAK,cAAc,EAAE,CAAE,CACtE,KAAK,gBAAgB,EACpB,OAAO,YACR,EAAE;IACN,CAAC;AACF,cAAW,KAAK,GAAG,WAAW;;AAGhC,MAAI,QAAQ,IAAI,SAAS,EAAE;GACzB,MAAM,aAAa,MAAM,wBAAwB,YAAY,cAAc;IACzE,aAAa,YAAY;IAGzB,KAAK,UAAU,YACZ,SAAS,MAAO,EAAE,WAAW,gBAAgB,EAAE,KAAK,cAAc,EAAE,CAAE,CACtE,KAAK,gBAAgB,EACpB,eAAe,YAChB,EAAE;IACN,CAAC;AACF,cAAW,KAAK,GAAG,WAAW;;AAQhC,MALkB,UAAU,YAAY,QACrC,oBACC,gBAAgB,WAAW,eAAe,CAAC,CAAC,gBAAgB,QAAQ,iBAAiB,gBAAgB,KACxG,CAEa,SAAS,GAAG;GAGxB,MAAM,eAAe,MAFa,aAAa,kBAAkB,QAAQ,0BAA0B,CAE9C,YAAY,cAAc;IAC7E,aAAa,YAAY;IACzB,KAAK,UAAU,YACZ,SAAS,MAAO,EAAE,WAAW,eAAe,EAAE,QAAQ,iBAAiB,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,CAAE,CACzG,KAAK,gBAAgB,EACpB,OAAO,YACR,EAAE;IACN,CAAC;AAEF,cAAW,KAAK,GAAG,aAAa;;AAGlC,SAAO;;CAGT,AAAQ,0BACN,YAC6B;AAC7B,MAAI,WAAW,gBAAgB,YAAY,SAAS;GAClD,MAAM,YAAa,WAAW,OAAO,KACjC,KAAK,MAAM;IACX,MAAM,SAAS,gBAAgB,uBAAuB,EAAE,CAAC;AACzD,WAAO,SAAS,kBAAkB,YAAY,kBAAkB,QAAQ,OAAO,CAAC,GAAG;KACnF,CACD,QAAQ,QAAQ,QAAQ,OAAU;AAErC,UAAO,aAAa,gBAAgB,UAAU,GACzC;IACC,MAAM;IACN,QAAQ;IACT,GACD;;AAGN,MAAI,WAAW,gBAAgB,YAAY,SAAS;GAClD,MAAM,YAAY,WAAW,6BAC1B,KAAK,MAAM;IACV,MAAM,SAAS,gBAAgB,mBAAmB,EAAE,CAAC;AACrD,WAAO,SAAS,kBAAkB,YAAY,kBAAkB,QAAQ,OAAO,CAAC,GAAG;KACnF,CACD,QAAQ,QAAQ,QAAQ,OAAU;AAErC,UAAO,aAAa,gBAAgB,UAAU,GACzC;IACC,MAAM;IACN,QAAQ;IACT,GACD;;;CAMR,MAAa,gCACX,cACA,cACA,iBACyB;AAGzB,MAAI,aAAa,gBAAgB,YAAY,SAAS;GACpD,MAAM,gBAAgB,gBAAgB,WAAW,cAAc,gBAAgB,MAAM,aAAa;GAElG,IAAI,wBAAwB,CAAC,aAAa,QAAQ,IAAI;AAEtD,OAAI,CAAC,eAAe,SAAS,aAAa,QAAQ,IAAI,EAAE;IACtD,MAAM,oBAAoB,MAAM,aAC7B,QAAQ,eAAe,CACvB,kBAAkB,cAAc,cAAc;KAC7C,wBAAwB;KACxB,iCAAiC;KAClC,CAAC;AAEJ,QAAI,kBACF,yBAAwB,mBAAmB;;AAI/C,UAAO;IACL,mBAAmB,gBAAgB,WAAW,cAAc,cAAc;IAC1E,WAAW,KAAK,0BAA0B,aAAa;IACvD,8BAA8B;IAC9B,KACE,sBAAsB,MAAM,yBAAyB,eAAe,SAAS,qBAAqB,CAAC,IACnG,aAAa,QAAQ;IACvB,QAAQ,aAAa;IACtB;;AAEH,MAAI,aAAa,gBAAgB,YAAY,SAAS;AACpD,OAAI,CAAC,aAAa,eAAe,aAAa,aAAa,eAAe,UAAU,WAAW,EAC7F,OAAM,IAAI,UAAU,uDAAuD;AAG7E,UAAO;IACL,8BAA8B;IAC9B,mBAAmB;IACnB,WAAW,KAAK,0BAA0B,IAAI,KAAK,aAAa,eAAe,UAAU,GAAG,aAAa,CAAC;IAC1G,SAAS,aAAa,eAAe,UAAU,GAAG;IAClD,YAAY,OAAO,QACjB,OAAO,YAAY,aAAa,eAAe,UAAU,GAAG,aAAa,iBAAiB,iBAAiB,CAC5G,CAAC,QACC,MAAM,CAAC,KAAK,YAAY;KAEvB,GAAG;MACF,MAAM,MAAM,QAEV,MAAM,UAAU;MAAE,GAAG;OAAO,KAAK,oBAAoB,KAAK;MAAc,GACzE,EAAE,CACH;KACF,GACD,EAAE,CACH;IACF;;AAEH,MAAI,aAAa,gBAAgB,YAAY,OAAO;GAClD,MAAM,KAAK,MAAM,QAAQ,aAAa,qBAAqB,GACvD,aAAa,qBAAqB,KAClC,aAAa;AAEjB,UAAO;IACL,8BAA8B;IAC9B,mBAAmB;IACnB,WAAW,KAAK,0BAA0B,GAAG;IAC7C,QAAQ,GAAG;IACX,MAAM,GAAG;IACV;;AAEH,MAAI,aAAa,gBAAgB,YAAY,OAAO;GAClD,MAAM,KAAK,MAAM,QAAQ,aAAa,qBAAqB,GACtD,aAAa,qBAAqB,KAClC,aAAa;GAGlB,MAAM,gBAAgB,MADa,aAAa,kBAAkB,QAAQ,2BAA2B,CAC9C,8BAA8B,cAAc,GAAG;AAEtG,UAAO;IACL,8BAA8B;IAC9B,mBAAmB;IACnB,WAAW,KAAK,0BAA0B,GAAG;IAC7C,QAAQ,GAAG;IACX,MAAM;IACP;;AAEH,MAAI,aAAa,gBAAgB,YAAY,YAAY;GACvD,MAAM,cAAc,MAAM,QAAQ,aAAa,qBAAqB,qBAAqB,GACrF,aAAa,qBAAqB,qBAAqB,KACvD,aAAa,qBAAqB;AAEtC,UAAO;IACL,8BAA8B;IAC9B,mBAAmB;IACnB,WAAW,KAAK,0BAA0B,YAAY;IACtD,MAAM,QAAQ,YAAY,mBAAmB,KAAK;IAClD,QAAQ,YAAY,mBAAmB,QAAQ;IAChD;;AAGH,QAAM,IAAI,UAAU,4CAA4C;;CAGlE,MAAa,yBAAyB,cAA4B,WAAgD;EAChH,MAAM,oBAAoB,MAAM,KAAK,6BAA6B,cAAc,UAAU;EAC1F,MAAM,wCAAkE,EAAE;EAC1E,MAAM,cAAc,UAAU,MAAM,UAAU;EAE9C,MAAM,kBAAoC,kBAAkB,SAAS,WAA8C;AACjH,OAAI,OAAO,SAAS,cAAc;AAChC,0CAAsC,KAAK,OAAO;IAGlD,MAAM,OAAO,OAAO;AAEpB,WAAO;KACL,WAAW,KAAK,0BAA0B,KAAK;KAC/C,mBAAmB;KACnB,SAAS,KAAK;KACd,YAAY,KAAK;KACjB,8BAA8B;KAC/B;;AAGH,OAAI,OAAO,SAAS,iBAAiB;IACnC,MAAM,UAAU,OAAO;IACvB,MAAM,SAAS,QAAQ;AAKvB,0CAAsC,KACpC,QACA,QACA,GAAG,OAAO,kBAAkB,UAAU,OAAO,EAC7C,GAAG,OAAO,kBAAkB,UAAU,OAAO,CAC9C;AAED,WAAO;KACL;MACE,WAAW,KAAK,0BAA0B,QAAQ;MAClD,mBAAmB;MACnB,KAAK,OAAO,SAAS,CAAC;MACtB;MACA,8BAA8B;MAC/B;KACD,GAAG,OAAO,kBAAkB,KACzB,sBACE;MACC,WAAW,KAAK,0BAA0B,QAAQ;MAClD,mBAAmB;MACnB,KAAK;MACL;MACA,8BAA8B;MAC/B,EACJ;KACD;MACE,WAAW,KAAK,0BAA0B,QAAQ;MAClD,mBAAmB;MACnB,KAAK,OAAO,SAAS,CAAC;MACtB;MACA,8BAA8B;MAC/B;KACD,GAAG,OAAO,kBAAkB,KACzB,sBACE;MACC,WAAW,KAAK,0BAA0B,QAAQ;MAClD,mBAAmB;MACnB,KAAK;MACL;MACA,8BAA8B;MAC/B,EACJ;KACF;;AAGH,OAAI,OAAO,SAAS,uBAAuB;IACzC,MAAM,kBAAkB,OAAO;AAC/B,0CAAsC,KAAK,OAAO;AAClD,QAAI,gBAAgB,gBAAgB,YAAY,MAC9C,QAAO;KACL,mBAAmB;KACnB,WAAW,KAAK,0BAA0B,gBAAgB;KAC1D,MAAM,OAAO,SAAS,CAAC,iBAAiB,EAAE;KAC1C,QAAQ,gBAAgB;KACxB,8BAA8B;KAC/B;AAGH,WAAO;KACL,mBAAmB;KACnB,WAAW,KAAK,0BAA0B,gBAAgB;KAC1D,MAAM,gBAAgB;KACtB,QAAQ,gBAAgB;KACxB,8BAA8B;KAC/B;;AAGH,OAAI,OAAO,SAAS,yBAAyB;AAC3C,0CAAsC,KAAK,OAAO;IAClD,MAAM,kBAAkB,OAAO;AAE/B,WAAO;KACL,mBAAmB;KACnB,WAAW,KAAK,0BAA0B,gBAAgB;KAC1D,MAAM,QAAQ,gBAAgB,mBAAmB,KAAK;KACtD,QAAQ,gBAAgB,mBAAmB,QAAQ;KACnD,8BAA8B;KAC/B;;AAGH,SAAM,IAAI,UAAU,0BAA0B;IAC9C;EAEF,MAAM,cAAc,UAAU,MAAM,aAAa,gBAAgB;EAEjE,MAAM,oBAAoB,OAAO,YAC/B,OAAO,QAAQ,YAAY,mBAAmB,CAAC,KAAK,CAAC,qBAAqB,YAAY;GACpF,MAAM,oBAAoB,OAAO,qBAC7B,iBAAiB,OAAO,qBAAqB,eAAe;IAC1D,MAAM,SAAS,sCAAsC,WAAW;AAkChE,WAjCgD;KAC9C,GAAG;KACH;KACA,QAAQ,WAAW,OAAO,UACtB;MACE,GAAG,WAAW;MACd,SAAS;MACT,kBAAkB,iBAAiB,WAAW,OAAO,mBAAmB,cAAc;OACpF,GAAG;OACH,GAAI,OAAO,SAAS,kBAGhB,EACE,QAAQ,aAAa,kBAClB,QAAQ,eAAe,CACvB,2BAA2B,OAAO,SAAS,SAAS,OAAqB,CACzE,cACJ,GACD,OAAO,SAAS,2BACd,OAAO,2BAA2B,iCAClC,EACE,QAAQ,aAAa,kBAClB,QAAQ,eAAe,CACvB,2BACC,OAAO,gBAAgB,SACvB,SAAS,OACV,CAAC,cACL,GACD,EAAE;OACT,EAAE;MACJ,GACD,WAAW;KAChB;KAED,GACF;AAGJ,OAAI,CAAC,OAAO,QACV,QAAO,CACL,qBACA;IACE,GAAG;IACH,oBAAoB;IACrB,CACF;AAGH,UAAO,CACL,qBACA;IACE,GAAG;IACH,oBAAoB;IACpB,mBAAmB,iBAAiB,OAAO,oBAAoB,eAAe;KAC5E,MAAM,SAAS,sCAAsC,WAAW;AA8BhE,YA7B+C;MAC7C,GAAG;MACH;MACA,QAAQ;OACN,GAAG,WAAW;OACd,kBAAkB,iBAAiB,WAAW,OAAO,mBAAmB,cAAc;QACpF,GAAG;QACH,GAAI,OAAO,SAAS,kBAGhB,EACE,QAAQ,aAAa,kBAClB,QAAQ,eAAe,CACvB,2BAA2B,OAAO,SAAS,SAAS,OAAqB,CAAC,cAG9E,GACD,OAAO,SAAS,2BACd,OAAO,2BAA2B,iCAClC,EACE,QAAQ,aAAa,kBAClB,QAAQ,eAAe,CACvB,2BAA2B,OAAO,gBAAgB,SAAS,SAAS,OAAqB,CACzF,cACJ,GACD,EAAE;QACT,EAAE;OACJ;MACF;MAED;IACH,CACF;IACD,CACH;AAED,SAAO;GACL,GAAG;GACH,oBAAoB;GACrB;;CAGH,MAAa,4BACX,cACA,kBACA,WACA;EACA,MAAM,2BAA2B,OAAO,YACtC,MAAM,QAAQ,IACZ,OAAO,QAAQ,iBAAiB,CAAC,IAAI,OAAO,CAAC,cAAc,mBAAmB;GAC5E,MAAM,kBAAkB,UAAU,YAAY,MAAM,MAAM,EAAE,OAAO,aAAa;AAChF,OAAI,CAAC,gBACH,OAAM,IAAI,UACR,oEAAoE,aAAa,iDAClF;AAGH,UAAO,CACL,cACA,MAAM,QAAQ,IACZ,cAAc,KAAK,iBACjB,KAAK,gCAAgC,cAAc,cAAc,gBAAgB,CAClF,CACF,CACF;IACD,CACH,CACF;EAED,MAAM,qBAAqB,uBAAuB,qBAAqB,0BAA0B,EAAE,WAAW,CAAC;AAE/G,MAAI,CAAC,mBAAmB,iBACtB,OAAM,IAAI,UAAU,gDAAgD,EAClE,oBAAoB,OAAO,QAAQ,mBAAmB,sBAAsB,EAAE,CAAC,CAC5E,SAAS,CAAC,SAAS,WAClB,MAAM,UACF,SACA,CAAC,MAAM,qBACL,qCAAqC,QAAQ,+BAC7C,MAAM,mBAAmB,KACtB,qBACC,yBAAyB,iBAAiB,uBAAuB,oCAAoC,QAAQ,KAAK,KAAK,UACrH;GACE,GAAI,iBAAiB,OAAO,UACxB,EAAE,GACF,EAAE,QAAQ,iBAAiB,OAAO,kBAAkB,KAAK,OAAO,GAAG,OAAO,EAAE;GAChF,GAAI,iBAAiB,oBAAoB,UACrC,EAAE,GACF,EACE,qBACE,iBAAiB,oBAAoB,2BAA2B,KAC7D,OAAO,GAAG,OACZ,EACJ;GACL,GAAI,iBAAiB,KAAK,UAAU,EAAE,GAAG,EAAE,MAAM,iBAAiB,KAAK,QAAQ;GAChF,EACD,MACA,EACD,GACJ,CACR,CACA,QAAQ,YAAY,YAAY,OAAU,EAC9C,CAAC;AAGJ,SAAO;;CAGT,AAAQ,2CAA2C,iBAAsC;AACvF,MAAI,gBAAgB,OAAO,SAAS,aAClC,QAAO;GACL,aAAa,YAAY;GACzB,kBAAkB,gBAAgB;GAClC,kBAAkB,gBAAgB,OAAO,iBAAiB,GAAG;GAC9D;AAEH,MAAI,gBAAgB,OAAO,SAAS,gBAClC,QAAO;GACL,aAAa,YAAY;GACzB,kBAAkB,gBAAgB;GAClC,kBAAkB,gBAAgB,OAAO,iBAAiB,GAAG;GAC9D;AAGH,MAAI,gBAAgB,OAAO,SAAS,sBAClC,QAAO;GACL,aAAa,gBAAgB,OAAO,gBAAgB;GACpD,kBAAkB,gBAAgB;GAClC,kBAAkB,gBAAgB,OAAO,gBAAgB;GAC1D;AAGH,MAAI,gBAAgB,OAAO,SAAS,wBAClC,QAAO;GACL,aAAa,gBAAgB,OAAO,gBAAgB;GACpD,kBAAkB,gBAAgB;GAClC,kBAAkB,gBAAgB,OAAO,iBAAiB,GAAG;GAC9D;AAGH,QAAM,IAAI,UAAU,mCAAmC;;;;;;CAOzD,AAAO,4BACL,iBACA,EAAE,UAAU,+BAA+B,eAAuD,EAAE,EACzE;AAC3B,MAAI,CAAC,gBAAgB,iBACnB,OAAM,IAAI,UACR,mGACD;EAGH,MAAM,cAAyC,EAAE;AAEjD,MAAI,gBAAgB,gBAClB,mBAAmB,MAAK,MAAM,iBAAiB,gBAAgB,iBAAiB;AAE9E,OAAI,cAAc,aAAa,MAAO;GACtC,MAAM,sBAAsB,cAAc;AAE1C,OAAI,CAAC,oBACH,OAAM,IAAI,UAAU,uDAAuD;AAG7E,QAAK,MAAM,sBAAsB,qBAAqB;IACpD,MAAM,gBAAgB,mBAAmB,KAAK,sBAAsB;KAClE,MAAM,kBAAkB,gBAAgB,mBAAmB;AAC3D,SAAI,CAAC,gBAAgB,QAAS,QAAO;KACrC,MAAM,QAAQ,gBAAgB,kBAAkB,MAAM,UACpD,mCAAmC;MAAE,kBAAkB,MAAM;MAAQ;MAAS,CAAC,CAChF;AAED,SAAI,CAAC,MAAO,QAAO;AACnB,YAAO;MACL;MACA;MACD;MACD;AAEF,QAAI,cAAc,OAAO,MAAM,MAAM,OAAU,EAAE;AAC/C,UAAK,MAAM,EAAE,OAAO,uBAAuB,cACzC,aAAY,qBAAqB,CAAC,KAAK,2CAA2C,MAAM,CAAC;AAG3F,cAAS;;;AAIb,SAAM,IAAI,UACR,6HACD;;MAGH,MAAK,MAAM,mBAAmB,gBAAgB,aAAa;GACzD,MAAM,kBAAkB,gBAAgB,mBAAmB,gBAAgB;AAC3E,OAAI,CAAC,gBAAgB,QACnB,OAAM,IAAI,UACR,sDAAsD,gBAAgB,GAAG,mCAC1E;GAGH,MAAM,aAAa,gBAAgB,kBAAkB,MAAM,UACzD,mCAAmC;IAAE,kBAAkB,MAAM;IAAQ;IAAS,CAAC,CAChF;AACD,OAAI,CAAC,WACH,OAAM,IAAI,UACR,wDAAwD,gBAAgB,GAAG,8EAC5E;AAGH,eAAY,gBAAgB,MAAM,CAAC,KAAK,2CAA2C,WAAW,CAAC;;AAInG,SAAO;;CAGT,AAAO,kBAAkB,WAA6D;EACpF,MAAM,SAAS,UAAU,MAAM,UAAuB;AACtD,YAAU,SAAS,OAAO;AAC1B,SAAO;;CAGT,MAAa,mBACX,cACA,SASC;EACD,MAAM,EAAE,QAAQ,WAAW,0BAA0B;EAErD,MAAM,mBAAqC,EAAE;EAC7C,MAAM,0BAAoD,EAAE;EAC5D,MAAM,0BAA0BA,6BAA+B,QAAQ,4BAA4B;AAEnG,OAAK,MAAM,CAAC,mBAAmB,0BAA0B,OAAO,QAAQ,wBAAwB,CAC9F,MAAK,MAAM,wBAAwB,uBAAuB;GACxD,IAAI;GACJ,IAAI;AAEJ,OAAI,qBAAqB,gBAAgB,YAAY,SAAS;IAC5D,MAAM,aAAa,qBAAqB;AACxC,QAAI,CAAC,sBACH,OAAM,IAAI,UAAU,0EAA0E;IAGhG,MAAM,EAAE,uBAAuB,MAAM,gCAAgC;KACnE;KACA,SAAS,qBAAqB;KAC9B,kBAAkB;KACnB,CAAC;IAiBF,MAAM,2BAfiB,MAAM,mBAAmB,qBAAqB,cAAc;KACjF,OAAO,CAAC,mBAAmB;KAC3B,kBAAkB,CAChB;MACE,SAAS,WAAW,SAAS,CAAC;MAC9B,YAAY,OAAO,YACjB,OAAO,QAAQ,qBAAqB,iBAAiB,CAAC,KAAK,CAAC,KAAK,WAAW;AAE1E,cAAO,CAAC,KAAK,OAAO,YAAY,OAAO,QAAQ,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC;QACpF,CACH;MACF,CACF;KACD,0BAA0B;KAC3B,CAAC,EAC6C;AAE/C,iCAA6B;AAC7B,0BAAsB,mBAAmB,cAAc,wBAAwB;cACtE,qBAAqB,gBAAgB,YAAY,SAAS;IACnE,MAAM,oBAAoB,+BAA+B,qBAAqB,iBAAiB;AAE/F,QAAI,CAAC,OACH,OAAM,IAAI,UAAU,6DAA6D;IAGnF,MAAM,EAAE,uBAAuB,MAAM,gCAAgC;KACnE;KACA,SAAS,qBAAqB;KAC9B,kBAAkB,qBAAqB;KACxC,CAAC;IAEF,MAAM,aAAa,KAAK,cAAc,aAAa;IACnD,MAAM,eAAe,MAAM,WAAW,QAAQ;KAC5C,SAAS;KACT;KACA,kBAAkB;MAChB,UAAU;MACV,OAAO;MACP,UAAU,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;MACxC;KACD,mBAAmB,qBAAqB;KACzC,CAAC;AAEF,iCAA6B;AAC7B,0BAAsB,WAAW,YAAY,aAAa;cACjD,qBAAqB,gBAAgB,YAAY,OAAO;IACjE,MAAM,EAAE,uBAAuB,MAAM,gCAAgC;KACnE;KACA,SAAS,qBAAqB;KAC9B,kBAAkB,qBAAqB;KACxC,CAAC;AAEF,QAAI,CAAC,mBAAmB,qBAAqB,GAC3C,OAAM,IAAI,UAAU,gEAAgE;IAItF,MAAM,qBAAqB,MAAM,KAAK,kCACpC,cACA,mBAAmB,qBAAqB,GACzC;IAED,MAAM,uBAAuB,aAAa,QAAQ,qBAAqB;IACvE,MAAM,kBAAkB,IAAI,gBAAgB;KAC1C,sBAAsB,CAAC,mBAAmB;KAC1C,QAAQ,mBAAmB;KAC5B,CAAC;IAEF,MAAM,YAAY,mCAAmC,mBAAmB;IAExE,MAAM,qBAAqB,MAAM,qBAAqB,iBAAoC,cAAc;KACtG,QAAQ,YAAY;KACpB,KAAK,UAAU;KACf,oBAAoB,mBAAmB;KACvC,cAAc;KACd;KACA;KACD,CAAC;AAEF,iCAA6B,mBAAmB;AAChD,0BAAsB;cACb,qBAAqB,gBAAgB,YAAY,OAAO;IACjE,MAAM,EAAE,uBAAuB,MAAM,gCAAgC;KACnE;KACA,SAAS,qBAAqB;KAC9B,kBAAkB,qBAAqB;KACxC,CAAC;AAEF,QAAI,CAAC,mBAAmB,qBAAqB,GAC3C,OAAM,IAAI,UAAU,gEAAgE;IAItF,MAAM,qBAAqB,MAAM,KAAK,kCACpC,cACA,mBAAmB,qBAAqB,GACzC;IAED,MAAM,uBAAuB,aAAa,QAAQ,qBAAqB;IACvE,MAAM,kBAAkB,IAAI,gBAAgB;KAC1C,sBAAsB,CAAC,mBAAmB;KAC1C,QAAQ,mBAAmB;KAC5B,CAAC;IAEF,MAAM,qBAAqB,MAAM,qBAAqB,iBAAiB,cAAc;KACnF,QAAQ,YAAY;KAIpB,WAAW,KAAK,qBAAqB,cAAc,mBAAmB;KACtE,cAAc,IAAI,SAAS,2BAA2B;MAAE;MAAW;MAAQ,CAAC;KAC5E,oBAAoB,mBAAmB;KACvC,cAAc;KACd;KACA;KACD,CAAC;AAEF,iCAA6B,mBAAmB;AAChD,0BAAsB;cACb,qBAAqB,gBAAgB,YAAY,UAAU;IACpE,MAAM,yBAAyB,aAAa,QAAQ,uBAAuB;IAC3E,MAAM,oBAAoB,IAAI,kBAAkB;KAC9C,QAAQ,qBAAqB,iBAAiB,gBAAgB,mBAAmB,qBAAqB;KACtG,sBAAsB,CACpB,mCAAmC,yBACjC,qBAAqB,iBAAiB,gBACvC,CACF;KACF,CAAC;IAEF,MAAM,qBAAqB,MAAM,uBAAuB,iBAAuC,cAAc;KAC3G,QAAQ,YAAY;KACpB,cAAc;KACd;KACA;KACD,CAAC;AAEF,iCAA6B,mBAAmB;AAChD,0BAAsB;cACb,qBAAqB,gBAAgB,YAAY,YAAY;IACtE,MAAM,oBAAoB,+BAA+B,qBAAqB,iBAAiB;AAC/F,QAAI,CAAC,OACH,OAAM,IAAI,UAAU,6DAA6D;IAInF,MAAM,UAAU,MADoB,aAAa,QAAQ,4BAA4B,CACnC,QAAQ,cAAc;KACtE,YAAY,qBAAqB,iBAAiB,gBAAgB;KAClE;KACD,CAAC;IAEF,MAAM,yBAAyB,aAAa,QAAQ,uBAAuB;IAC3E,MAAM,oBAAoB,IAAI,kBAAkB;KAC9C,QAAQ,qBAAqB,iBAAiB,gBAAgB,mBAAmB,oBAAoB;KACrG,sBAAsB,CAAC,mCAAmC,yBAAyB,QAAQ,CAAC;KAC7F,CAAC;IAEF,MAAM,qBAAqB,MAAM,uBAAuB,iBACtD,cACA;KACE,QAAQ,YAAY;KACpB,cAAc;KACd;KACA;KACD,CACF;AAED,iCAA6B,mBAAmB;AAChD,0BAAsB;SAEtB,OAAM,IAAI,UAAU,mCAAmC;AAGzD,OAAI,CAAC,iBAAiB,mBACpB,kBAAiB,qBAAqB,CAAC,oBAAoB;OAE3D,kBAAiB,mBAAmB,KAAK,oBAAoB;AAG/D,OAAI,CAAC,wBAAwB,mBAC3B,yBAAwB,qBAAqB,CAAC,2BAA2B;OAEzE,yBAAwB,mBAAmB,KAAK,2BAA2B;;AAKjF,SAAO;GACL;GACA;GACD;;CAGH,AAAQ,cAAc,cAA4B;AAChD,SAAO,aAAa,kBAAkB,QAAQ,WAAW;;CAG3D,AAAQ,WAAW,cAA4B;AAC7C,SAAO,aAAa,kBAAkB,QAAQ,QAAQ;;CAGxD,MAAc,kCAAkC,cAA4B,WAAmB;EAC7F,MAAM,UAAU,aAAa,kBAAkB,QAAQ,QAAQ;AAE/D,MAAI,CAAC,UAAU,WAAW,OAAO,CAC/B,OAAM,IAAI,UAAU,oDAAoD,UAAU,qBAAqB;EAGzG,MAAM,cAAc,MAAM,QAAQ,mBAAmB,UAAU;AAE/D,MAAI,CAAC,YAAY,kBAAkB,YAAY,eAAe,WAAW,EACvE,OAAM,IAAI,UAAU,uDAAuD,UAAU,kBAAkB;EAKzG,IAAI,CAAC,sBAAsB,YAAY;AACvC,MAAI,OAAO,uBAAuB,SAChC,sBAAqB,YAAY,eAAe,oBAAoB,CAAC,iBAAiB,CAAC;AAGzF,SAAO;;CAIT,AAAQ,qBAAqB,cAA4B,oBAAwC;EAE/F,MAAM,yBAAyB,aAAa,kBAAkB,QAAQ,uBAAuB;EAE7F,MAAM,YAAY,mCAAmC,mBAAmB;EACxE,MAAM,2BAA2B,uBAAuB,sBAAsB,UAAU;AACxF,MAAI,yBAAyB,WAAW,EACtC,OAAM,IAAI,UACR,+DAA+D,UAAU,0BAC1E;AAGH,SAAO,yBAAyB,GAAG;;;0BAj6BtC,YAAY"}