

import { CredoError } from "../../error/CredoError.mjs";
import "../../error/index.mjs";
import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.97.0/helpers/decorateMetadata.mjs";
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.97.0/helpers/decorate.mjs";
import { JsonTransformer } from "../../utils/JsonTransformer.mjs";
import "../../utils/index.mjs";
import { getJwkHumanDescription } from "../kms/jwk/humanDescription.mjs";
import "../kms/index.mjs";
import { getPublicJwkFromVerificationMethod } from "../dids/domain/key-type/keyDidMapping.mjs";
import { DidsApi } from "../dids/DidsApi.mjs";
import "../dids/index.mjs";
import { ClaimFormat } from "../vc/models/ClaimFormat.mjs";
import { purposes } from "../vc/data-integrity/libraries/jsonld-signatures.mjs";
import { ANONCREDS_DATA_INTEGRITY_CRYPTOSUITE, AnonCredsDataIntegrityServiceSymbol } from "../vc/data-integrity/models/IAnonCredsDataIntegrityService.mjs";
import { W3cPresentation } from "../vc/models/presentation/W3cPresentation.mjs";
import { SignatureSuiteRegistry } from "../vc/data-integrity/SignatureSuiteRegistry.mjs";
import { W3cCredentialRepository } from "../vc/repository/W3cCredentialRepository.mjs";
import { W3cCredentialService } from "../vc/W3cCredentialService.mjs";
import "../vc/index.mjs";
import { MdocDeviceResponse } from "../mdoc/MdocDeviceResponse.mjs";
import { MdocApi } from "../mdoc/MdocApi.mjs";
import "../mdoc/index.mjs";
import { SdJwtVcApi } from "../sd-jwt-vc/SdJwtVcApi.mjs";
import "../sd-jwt-vc/index.mjs";
import { DifPresentationExchangeError } from "./DifPresentationExchangeError.mjs";
import { PresentationSubmissionLocation } from "./models/index.mjs";
import { getSphereonOriginalVerifiableCredential, getSphereonOriginalVerifiablePresentation, getVerifiablePresentationFromEncoded } from "./utils/transform.mjs";
import { getCredentialsForRequest } from "./utils/credentialSelection.mjs";
import { getPresentationsToCreate } from "./utils/presentationsToCreate.mjs";
import "./utils/index.mjs";
import { injectable } from "tsyringe";
import { PEX, Status } from "@animo-id/pex";
import { PEVersion } from "@animo-id/pex/dist/main/lib/index.js";

//#region src/modules/dif-presentation-exchange/DifPresentationExchangeService.ts
var _ref;
let DifPresentationExchangeService = class DifPresentationExchangeService$1 {
	constructor(w3cCredentialService) {
		this.w3cCredentialService = w3cCredentialService;
		this.pex = new PEX();
	}
	async getCredentialsForRequest(agentContext, presentationDefinition) {
		const credentialRecords = await this.queryCredentialForPresentationDefinition(agentContext, presentationDefinition);
		return getCredentialsForRequest(this.pex, presentationDefinition, credentialRecords);
	}
	/**
	* Selects the credentials to use based on the output from `getCredentialsForRequest`
	* Use this method if you don't want to manually select the credentials yourself.
	*/
	selectCredentialsForRequest(credentialsForRequest) {
		if (!credentialsForRequest.areRequirementsSatisfied) throw new CredoError("Could not find the required credentials for the presentation submission");
		const credentials = {};
		for (const requirement of credentialsForRequest.requirements) for (const submission of requirement.submissionEntry.slice(0, requirement.needsCount)) {
			if (!credentials[submission.inputDescriptorId]) credentials[submission.inputDescriptorId] = [];
			credentials[submission.inputDescriptorId].push(submission.verifiableCredentials[0]);
		}
		return credentials;
	}
	validatePresentationDefinition(presentationDefinition) {
		const validation = PEX.validateDefinition(presentationDefinition);
		const errorMessages = this.formatValidated(validation);
		if (errorMessages.length > 0) throw new DifPresentationExchangeError("Invalid presentation definition", { additionalMessages: errorMessages });
	}
	validatePresentationSubmission(presentationSubmission) {
		const validation = PEX.validateSubmission(presentationSubmission);
		const errorMessages = this.formatValidated(validation);
		if (errorMessages.length > 0) throw new DifPresentationExchangeError("Invalid presentation submission", { additionalMessages: errorMessages });
	}
	validatePresentation(presentationDefinition, presentations, presentationSubmission) {
		const result = this.pex.evaluatePresentation(presentationDefinition, Array.isArray(presentations) ? presentations.map(getSphereonOriginalVerifiablePresentation) : getSphereonOriginalVerifiablePresentation(presentations), {
			limitDisclosureSignatureSuites: ["DataIntegrityProof.anoncreds-2023"],
			presentationSubmission
		});
		if (result.areRequiredCredentialsPresent === Status.ERROR) throw new DifPresentationExchangeError("Invalid presentation", { additionalMessages: this.formatValidated(result.errors) });
	}
	formatValidated(v) {
		return (Array.isArray(v) ? v : v ? [v] : []).filter((r) => r.status === Status.ERROR).map((r) => r.message).filter((r) => Boolean(r));
	}
	async createPresentation(agentContext, options) {
		const { presentationDefinition, domain, challenge, mdocSessionTranscript } = options;
		const presentationSubmissionLocation = options.presentationSubmissionLocation ?? PresentationSubmissionLocation.PRESENTATION;
		const verifiablePresentationResultsWithFormat = [];
		const presentationsToCreate = getPresentationsToCreate(options.credentialsForInputDescriptor);
		for (const presentationToCreate of presentationsToCreate) {
			const inputDescriptorIds = presentationToCreate.verifiableCredentials.map((c) => c.inputDescriptorId);
			const inputDescriptorsForPresentation = presentationDefinition.input_descriptors.filter((inputDescriptor) => inputDescriptorIds.includes(inputDescriptor.id));
			const presentationDefinitionForSubject = {
				...presentationDefinition,
				input_descriptors: inputDescriptorsForPresentation,
				submission_requirements: void 0
			};
			if (presentationToCreate.claimFormat === ClaimFormat.MsoMdoc) {
				if (presentationToCreate.verifiableCredentials.length !== 1) throw new DifPresentationExchangeError("Currently a Mdoc presentation can only be created from a single credential");
				const mdocRecord = presentationToCreate.verifiableCredentials[0].credential;
				if (!mdocSessionTranscript) throw new DifPresentationExchangeError("Missing mdoc session transcript options for creating MDOC presentation.");
				const { deviceResponseBase64Url, presentationSubmission: presentationSubmission$1 } = await MdocDeviceResponse.createPresentationDefinitionDeviceResponse(agentContext, {
					mdocs: [mdocRecord.firstCredential],
					presentationDefinition,
					sessionTranscriptOptions: mdocSessionTranscript
				});
				if (presentationSubmissionLocation !== PresentationSubmissionLocation.EXTERNAL) throw new DifPresentationExchangeError("Only EXTERNAL DifPresentationExchangeSubmissionLocation supported for mdoc presentations");
				verifiablePresentationResultsWithFormat.push({
					verifiablePresentationResult: {
						presentationSubmission: presentationSubmission$1,
						verifiablePresentations: [deviceResponseBase64Url],
						presentationSubmissionLocation
					},
					claimFormat: presentationToCreate.claimFormat
				});
			} else {
				const credentialsForPresentation = presentationToCreate.verifiableCredentials.map((c) => getSphereonOriginalVerifiableCredential(c.credential));
				const extraProofOptions = this.shouldSignUsingAnonCredsDataIntegrity(presentationToCreate) ? {
					typeSupportsSelectiveDisclosure: true,
					type: `DataIntegrityProof.${ANONCREDS_DATA_INTEGRITY_CRYPTOSUITE}`
				} : {};
				const verifiablePresentationResult = await this.pex.verifiablePresentationFrom(presentationDefinitionForSubject, credentialsForPresentation, this.getPresentationSignCallback(agentContext, presentationToCreate), {
					proofOptions: {
						challenge,
						domain,
						...extraProofOptions
					},
					presentationSubmissionLocation
				});
				verifiablePresentationResultsWithFormat.push({
					verifiablePresentationResult,
					claimFormat: presentationToCreate.claimFormat
				});
			}
		}
		if (verifiablePresentationResultsWithFormat.length === 0) throw new DifPresentationExchangeError("No verifiable presentations created");
		if (presentationsToCreate.length !== verifiablePresentationResultsWithFormat.length) throw new DifPresentationExchangeError("Invalid amount of verifiable presentations created");
		const presentationSubmission = {
			id: verifiablePresentationResultsWithFormat[0].verifiablePresentationResult.presentationSubmission.id,
			definition_id: verifiablePresentationResultsWithFormat[0].verifiablePresentationResult.presentationSubmission.definition_id,
			descriptor_map: []
		};
		verifiablePresentationResultsWithFormat.forEach(({ verifiablePresentationResult }, index) => {
			const descriptorMap = verifiablePresentationResult.presentationSubmission.descriptor_map.map((d) => {
				const descriptor = { ...d };
				if (presentationSubmissionLocation === PresentationSubmissionLocation.EXTERNAL && verifiablePresentationResultsWithFormat.length > 1) descriptor.path = `$[${index}]`;
				return descriptor;
			});
			presentationSubmission.descriptor_map.push(...descriptorMap);
		});
		return {
			verifiablePresentations: verifiablePresentationResultsWithFormat.flatMap((resultWithFormat) => resultWithFormat.verifiablePresentationResult.verifiablePresentations.map((vp) => getVerifiablePresentationFromEncoded(agentContext, vp))),
			encodedVerifiablePresentations: verifiablePresentationResultsWithFormat.flatMap((resultWithFormat) => resultWithFormat.verifiablePresentationResult.verifiablePresentations),
			presentationSubmission,
			presentationSubmissionLocation: verifiablePresentationResultsWithFormat[0].verifiablePresentationResult.presentationSubmissionLocation
		};
	}
	getSigningAlgorithmFromVerificationMethod(verificationMethod, suitableAlgorithms) {
		const publicJwk = getPublicJwkFromVerificationMethod(verificationMethod);
		if (suitableAlgorithms) {
			const possibleAlgorithms = publicJwk.supportedSignatureAlgorithms.filter((alg) => suitableAlgorithms?.includes(alg));
			if (!possibleAlgorithms || possibleAlgorithms.length === 0) throw new DifPresentationExchangeError([
				"Found no suitable signing algorithm.",
				`Algorithms supported by Verification method: ${publicJwk.supportedSignatureAlgorithms.join(", ")}`,
				`Suitable algorithms: ${suitableAlgorithms.join(", ")}`
			].join("\n"));
			return possibleAlgorithms[0];
		}
		return publicJwk.signatureAlgorithm;
	}
	getSigningAlgorithmsForPresentationDefinitionAndInputDescriptors(algorithmsSatisfyingDefinition, inputDescriptorAlgorithms) {
		const allDescriptorAlgorithms = inputDescriptorAlgorithms.flat();
		const algorithmsSatisfyingDescriptors = allDescriptorAlgorithms.filter((alg) => inputDescriptorAlgorithms.every((descriptorAlgorithmSet) => descriptorAlgorithmSet.includes(alg)));
		const algorithmsSatisfyingPdAndDescriptorRestrictions = algorithmsSatisfyingDefinition.filter((alg) => algorithmsSatisfyingDescriptors.includes(alg));
		if (algorithmsSatisfyingDefinition.length > 0 && algorithmsSatisfyingDescriptors.length > 0 && algorithmsSatisfyingPdAndDescriptorRestrictions.length === 0) throw new DifPresentationExchangeError("No signature algorithm found for satisfying restrictions of the presentation definition and input descriptors");
		if (allDescriptorAlgorithms.length > 0 && algorithmsSatisfyingDescriptors.length === 0) throw new DifPresentationExchangeError("No signature algorithm found for satisfying restrictions of the input descriptors");
		let suitableAlgorithms;
		if (algorithmsSatisfyingPdAndDescriptorRestrictions.length > 0) suitableAlgorithms = algorithmsSatisfyingPdAndDescriptorRestrictions;
		else if (algorithmsSatisfyingDescriptors.length > 0) suitableAlgorithms = algorithmsSatisfyingDescriptors;
		else if (algorithmsSatisfyingDefinition.length > 0) suitableAlgorithms = algorithmsSatisfyingDefinition;
		return suitableAlgorithms;
	}
	getSigningAlgorithmForJwtVc(presentationDefinition, verificationMethod) {
		const algorithmsSatisfyingDefinition = presentationDefinition.format?.jwt_vc?.alg ?? [];
		const inputDescriptorAlgorithms = presentationDefinition.input_descriptors.map((descriptor) => descriptor.format?.jwt_vc?.alg ?? []).filter((alg) => alg.length > 0);
		const suitableAlgorithms = this.getSigningAlgorithmsForPresentationDefinitionAndInputDescriptors(algorithmsSatisfyingDefinition, inputDescriptorAlgorithms);
		return this.getSigningAlgorithmFromVerificationMethod(verificationMethod, suitableAlgorithms);
	}
	getProofTypeForLdpVc(agentContext, presentationDefinition, verificationMethod) {
		const algorithmsSatisfyingDefinition = presentationDefinition.format?.ldp_vc?.proof_type ?? [];
		const inputDescriptorAlgorithms = presentationDefinition.input_descriptors.map((descriptor) => descriptor.format?.ldp_vc?.proof_type ?? []).filter((alg) => alg.length > 0);
		const suitableSignatureSuites = this.getSigningAlgorithmsForPresentationDefinitionAndInputDescriptors(algorithmsSatisfyingDefinition, inputDescriptorAlgorithms);
		const signatureSuiteRegistry = agentContext.dependencyManager.resolve(SignatureSuiteRegistry);
		const publicJwk = getPublicJwkFromVerificationMethod(verificationMethod);
		const supportedSignatureSuites = signatureSuiteRegistry.getAllByPublicJwkType(publicJwk);
		if (supportedSignatureSuites.length === 0) throw new DifPresentationExchangeError(`Couldn't find a supported signature suite for the given jwk ${getJwkHumanDescription(publicJwk.toJson())}`);
		if (suitableSignatureSuites) {
			if (!supportedSignatureSuites.find((suite) => suitableSignatureSuites.includes(suite.proofType))) throw new DifPresentationExchangeError([
				"No possible signature suite found for the given verification method.",
				`Verification method type: ${verificationMethod.type}`,
				`jwk type: ${getJwkHumanDescription(publicJwk.toJson())}`,
				`SupportedSignatureSuites: '${supportedSignatureSuites.map((s) => s.proofType).join(", ")}'`,
				`SuitableSignatureSuites: ${suitableSignatureSuites.join(", ")}`
			].join("\n"));
			return supportedSignatureSuites[0].proofType;
		}
		return supportedSignatureSuites[0].proofType;
	}
	/**
	* if all submission descriptors have a format of di | ldp,
	* and all credentials have an ANONCREDS_DATA_INTEGRITY proof we default to
	* signing the presentation using the ANONCREDS_DATA_INTEGRITY_CRYPTOSUITE
	*/
	shouldSignUsingAnonCredsDataIntegrity(presentationToCreate, presentationSubmission) {
		if (presentationToCreate.claimFormat !== ClaimFormat.LdpVp) return void 0;
		const validDescriptorFormat = !presentationSubmission || presentationSubmission.descriptor_map.every((descriptor) => [
			ClaimFormat.DiVc,
			ClaimFormat.DiVp,
			ClaimFormat.LdpVc,
			ClaimFormat.LdpVp
		].includes(descriptor.format));
		const credentialAreSignedUsingAnonCredsDataIntegrity = presentationToCreate.verifiableCredentials.every(({ credential }) => {
			const firstCredential = credential.firstCredential;
			if (firstCredential.claimFormat !== ClaimFormat.LdpVc) return false;
			return firstCredential.dataIntegrityCryptosuites.includes(ANONCREDS_DATA_INTEGRITY_CRYPTOSUITE);
		});
		return validDescriptorFormat && credentialAreSignedUsingAnonCredsDataIntegrity;
	}
	getPresentationSignCallback(agentContext, presentationToCreate) {
		return async (callBackParams) => {
			const { presentation: presentationInput, options, presentationDefinition, presentationSubmission } = callBackParams;
			const { challenge, domain } = options.proofOptions ?? {};
			if (!challenge) throw new CredoError("challenge MUST be provided when signing a Verifiable Presentation");
			if (presentationToCreate.claimFormat === ClaimFormat.JwtVp) {
				if (!presentationToCreate.subjectIds) throw new DifPresentationExchangeError("Cannot create presentation for credentials without subject id");
				const verificationMethod = await this.getVerificationMethodForSubjectId(agentContext, presentationToCreate.subjectIds[0]);
				const w3cPresentation = JsonTransformer.fromJSON(presentationInput, W3cPresentation);
				w3cPresentation.holder = verificationMethod.controller;
				return (await this.w3cCredentialService.signPresentation(agentContext, {
					format: ClaimFormat.JwtVp,
					alg: this.getSigningAlgorithmForJwtVc(presentationDefinition, verificationMethod),
					verificationMethod: verificationMethod.id,
					presentation: w3cPresentation,
					challenge,
					domain
				})).encoded;
			}
			if (presentationToCreate.claimFormat === ClaimFormat.LdpVp) {
				if (this.shouldSignUsingAnonCredsDataIntegrity(presentationToCreate, presentationSubmission)) {
					presentationSubmission.descriptor_map = presentationSubmission.descriptor_map.map((descriptor) => ({
						...descriptor,
						format: "di_vp"
					}));
					return {
						...(await agentContext.dependencyManager.resolve(AnonCredsDataIntegrityServiceSymbol).createPresentation(agentContext, {
							presentationDefinition,
							presentationSubmission,
							selectedCredentialRecords: presentationToCreate.verifiableCredentials.map((vc) => vc.credential),
							challenge
						})).toJSON(),
						presentation_submission: presentationSubmission
					};
				}
				if (!presentationToCreate.subjectIds) throw new DifPresentationExchangeError("Cannot create presentation for credentials without subject id");
				const verificationMethod = await this.getVerificationMethodForSubjectId(agentContext, presentationToCreate.subjectIds[0]);
				const w3cPresentation = JsonTransformer.fromJSON(presentationInput, W3cPresentation);
				w3cPresentation.holder = verificationMethod.controller;
				return (await this.w3cCredentialService.signPresentation(agentContext, {
					format: ClaimFormat.LdpVp,
					proofType: this.getProofTypeForLdpVc(agentContext, presentationDefinition, verificationMethod),
					proofPurpose: new purposes.AuthenticationProofPurpose({
						challenge,
						domain
					}),
					verificationMethod: verificationMethod.id,
					presentation: w3cPresentation,
					challenge,
					domain
				})).encoded;
			}
			if (presentationToCreate.claimFormat === ClaimFormat.SdJwtDc) {
				const sdJwtInput = presentationInput;
				if (!domain) throw new CredoError("Missing 'domain' property, unable to set required 'aud' property in SD-JWT KB-JWT");
				const sdJwtVcApi = this.getSdJwtVcApi(agentContext);
				const originalSdJwtVc = sdJwtVcApi.fromCompact(sdJwtInput.compactSdJwtVc);
				originalSdJwtVc.kmsKeyId = presentationToCreate.verifiableCredentials[0].credential.credentialInstances[0].kmsKeyId;
				return await sdJwtVcApi.present({
					sdJwtVc: originalSdJwtVc,
					presentationFrame: void 0,
					verifierMetadata: {
						audience: domain,
						nonce: challenge,
						issuedAt: Math.floor(Date.now() / 1e3)
					},
					additionalPayload: presentationToCreate.verifiableCredentials[0].additionalPayload
				});
			}
			throw new DifPresentationExchangeError("Only JWT, SD-JWT-VC, JSONLD credentials are supported for a single presentation");
		};
	}
	async getVerificationMethodForSubjectId(agentContext, subjectId) {
		const didsApi = agentContext.dependencyManager.resolve(DidsApi);
		if (!subjectId.startsWith("did:")) throw new DifPresentationExchangeError(`Only dids are supported as credentialSubject id. ${subjectId} is not a valid did`);
		const didDocument = await didsApi.resolveDidDocument(subjectId);
		if (!didDocument.authentication || didDocument.authentication.length === 0) throw new DifPresentationExchangeError(`No authentication verificationMethods found for did ${subjectId} in did document`);
		let [verificationMethod] = didDocument.authentication;
		if (typeof verificationMethod === "string") verificationMethod = didDocument.dereferenceKey(verificationMethod, ["authentication"]);
		return verificationMethod;
	}
	/**
	* Queries the wallet for credentials that match the given presentation definition. This only does an initial query based on the
	* schema of the input descriptors. It does not do any further filtering based on the constraints in the input descriptors.
	*/
	async queryCredentialForPresentationDefinition(agentContext, presentationDefinition) {
		const w3cCredentialRepository = agentContext.dependencyManager.resolve(W3cCredentialRepository);
		const w3cQuery = [];
		const sdJwtVcQuery = [];
		const mdocQuery = [];
		const presentationDefinitionVersion = PEX.definitionVersionDiscovery(presentationDefinition);
		if (!presentationDefinitionVersion.version) throw new DifPresentationExchangeError("Unable to determine the Presentation Exchange version from the presentation definition", presentationDefinitionVersion.error ? { additionalMessages: [presentationDefinitionVersion.error] } : {});
		if (presentationDefinitionVersion.version === PEVersion.v1) {
			const pd = presentationDefinition;
			for (const inputDescriptor of pd.input_descriptors) for (const schema of inputDescriptor.schema) {
				sdJwtVcQuery.push({ vct: schema.uri });
				w3cQuery.push({ $or: [
					{ expandedTypes: [schema.uri] },
					{ contexts: [schema.uri] },
					{ types: [schema.uri] }
				] });
				mdocQuery.push({ docType: inputDescriptor.id });
			}
		} else if (presentationDefinitionVersion.version === PEVersion.v2) {} else throw new DifPresentationExchangeError(`Unsupported presentation definition version ${presentationDefinitionVersion.version}`);
		const allRecords = [];
		const w3cCredentialRecords = w3cQuery.length > 0 ? await w3cCredentialRepository.findByQuery(agentContext, { $or: w3cQuery }) : await w3cCredentialRepository.getAll(agentContext);
		allRecords.push(...w3cCredentialRecords);
		const sdJwtVcApi = this.getSdJwtVcApi(agentContext);
		const sdJwtVcRecords = sdJwtVcQuery.length > 0 ? await sdJwtVcApi.findAllByQuery({ $or: sdJwtVcQuery }) : await sdJwtVcApi.getAll();
		allRecords.push(...sdJwtVcRecords);
		const mdocApi = this.getMdocApi(agentContext);
		const mdocRecords = mdocQuery.length > 0 ? await mdocApi.findAllByQuery({ $or: mdocQuery }) : await mdocApi.getAll();
		allRecords.push(...mdocRecords);
		return allRecords;
	}
	getSdJwtVcApi(agentContext) {
		return agentContext.dependencyManager.resolve(SdJwtVcApi);
	}
	getMdocApi(agentContext) {
		return agentContext.dependencyManager.resolve(MdocApi);
	}
};
DifPresentationExchangeService = __decorate([injectable(), __decorateMetadata("design:paramtypes", [typeof (_ref = typeof W3cCredentialService !== "undefined" && W3cCredentialService) === "function" ? _ref : Object])], DifPresentationExchangeService);

//#endregion
export { DifPresentationExchangeService };
//# sourceMappingURL=DifPresentationExchangeService.mjs.map