diff --git a/apps/easypid/src/features/proximity/mdocProximity.ts b/apps/easypid/src/features/proximity/mdocProximity.ts index 9a488ba8..a0280542 100644 --- a/apps/easypid/src/features/proximity/mdocProximity.ts +++ b/apps/easypid/src/features/proximity/mdocProximity.ts @@ -12,6 +12,7 @@ import { import { TypedArrayEncoder } from '@credo-ts/core' import { getMdocContext } from '@credo-ts/core/build/modules/mdoc/MdocContext' import type { EasyPIDAppAgent, FormattedSubmission, MdocRecord } from '@package/agent' +import { handleBatchCredential } from '@package/agent/src/batch' import { type Permission, PermissionsAndroid, Platform } from 'react-native' const requireMdocDataTransfer = () => @@ -83,12 +84,22 @@ export const shareDeviceResponse = async (options: ShareDeviceResponseOptions) = throw new Error('Not all requirements are satisfied') } - const issuerSignedDocuments = options.submission.entries.map((e) => { - if (!e.isSatisfied) throw new Error(`Requirement for doctype ${e.inputDescriptorId} not satisfied`) + if (options.submission.entries.length > 1) { + throw new Error('Only one mdoc supported at the moment due to only being able to sign with one device key') + } + + const issuerSignedDocuments = await Promise.all( + options.submission.entries.map(async (e) => { + if (!e.isSatisfied) throw new Error(`Requirement for doctype ${e.inputDescriptorId} not satisfied`) + + const credential = e.credentials[0].credential.record as MdocRecord + + // Optionally handle batch issuance + const credentialRecord = await handleBatchCredential(options.agent, credential) - const credential = e.credentials[0].credential.record as MdocRecord - return parseIssuerSigned(TypedArrayEncoder.fromBase64(credential.base64Url), credential.getTags().docType) - }) + return parseIssuerSigned(TypedArrayEncoder.fromBase64(credentialRecord.base64Url), credential.getTags().docType) + }) + ) const mdoc = new MDoc(issuerSignedDocuments) diff --git a/apps/easypid/src/features/receive/FunkeCredentialNotificationScreen.tsx b/apps/easypid/src/features/receive/FunkeCredentialNotificationScreen.tsx index 589ceb32..e7194bf8 100644 --- a/apps/easypid/src/features/receive/FunkeCredentialNotificationScreen.tsx +++ b/apps/easypid/src/features/receive/FunkeCredentialNotificationScreen.tsx @@ -134,6 +134,8 @@ export function FunkeCredentialNotificationScreen() { credentialConfigurationIdsToRequest: [configurationId], accessToken: tokenResponse, clientId: resolvedAuthorizationRequest ? authorization.clientId : undefined, + // Always request batch for non pid credentials + requestBatch: true, }) const credentialRecord = credentialResponses[0].credential diff --git a/packages/agent/src/batch.ts b/packages/agent/src/batch.ts index c3dbe88b..e5a61b63 100644 --- a/packages/agent/src/batch.ts +++ b/packages/agent/src/batch.ts @@ -31,10 +31,10 @@ export async function refreshPid({ * * @todo: what if batch is gone? */ -export async function handleBatchCredential( +export async function handleBatchCredential( agent: EitherAgent, - credentialRecord: W3cCredentialRecord | SdJwtVcRecord | MdocRecord -) { + credentialRecord: CredentialRecord +): Promise { const batchMetadata = getBatchCredentialMetadata(credentialRecord) if (!batchMetadata) return credentialRecord @@ -77,18 +77,18 @@ export async function handleBatchCredential( if (credentialRecord instanceof MdocRecord) { return new MdocRecord({ mdoc: Mdoc.fromBase64Url(batchCredential as string), - }) + }) as CredentialRecord } if (credentialRecord instanceof SdJwtVcRecord) { return new SdJwtVcRecord({ compactSdJwtVc: batchCredential as string, - }) + }) as CredentialRecord } if (credentialRecord instanceof W3cCredentialRecord) { return new W3cCredentialRecord({ tags: { expandedTypes: [] }, credential: decodeW3cCredential(batchCredential), - }) + }) as CredentialRecord } } diff --git a/packages/agent/src/invitation/shareProof.ts b/packages/agent/src/invitation/shareProof.ts index 9171af34..c1cc91d5 100644 --- a/packages/agent/src/invitation/shareProof.ts +++ b/packages/agent/src/invitation/shareProof.ts @@ -46,7 +46,18 @@ export const shareProof = async ({ // TODO: support credential selection for DCQL const dcqlCredentials = resolvedRequest.queryResult - ? agent.modules.openId4VcHolder.selectCredentialsForDcqlRequest(resolvedRequest.queryResult) + ? Object.fromEntries( + await Promise.all( + Object.entries( + agent.modules.openId4VcHolder.selectCredentialsForDcqlRequest(resolvedRequest.queryResult) + ).map(async ([queryCredentialId, credential]) => { + // Optionally use a batch credential + const credentialRecord = await handleBatchCredential(agent, credential.credentialRecord) + + return [queryCredentialId, { ...credential, credentialRecord }] + }) + ) + ) : undefined try {