1
1
import type { AgentContext } from '../../agent'
2
2
3
- import { DcqlCredentialRepresentation , DcqlMdocRepresentation , DcqlQuery , DcqlSdJwtVcRepresentation } from 'dcql'
3
+ import { DcqlCredential , DcqlMdocCredential , DcqlQuery , DcqlSdJwtVcCredential } from 'dcql'
4
4
import { injectable } from 'tsyringe'
5
5
6
6
import { JsonValue } from '../../types'
@@ -34,7 +34,7 @@ export class DcqlService {
34
34
*/
35
35
private async queryCredentialsForDcqlQuery (
36
36
agentContext : AgentContext ,
37
- dcqlQuery : DcqlQuery
37
+ dcqlQuery : DcqlQuery . Input
38
38
) : Promise < Array < SdJwtVcRecord | W3cCredentialRecord | MdocRecord > > {
39
39
const w3cCredentialRepository = agentContext . dependencyManager . resolve ( W3cCredentialRepository )
40
40
@@ -47,47 +47,83 @@ export class DcqlService {
47
47
48
48
const allRecords : Array < SdJwtVcRecord | W3cCredentialRecord | MdocRecord > = [ ]
49
49
50
- // query the wallet ourselves first to avoid the need to query the pex library for all
51
- // credentials for every proof request
52
50
const w3cCredentialRecords =
53
51
formats . has ( 'jwt_vc_json' ) || formats . has ( 'jwt_vc_json-ld' )
54
52
? await w3cCredentialRepository . getAll ( agentContext )
55
53
: [ ]
56
54
allRecords . push ( ...w3cCredentialRecords )
57
55
58
- const sdJwtVcApi = this . getSdJwtVcApi ( agentContext )
59
- const sdJwtVcRecords = formats . has ( 'vc+sd-jwt' ) ? await sdJwtVcApi . getAll ( ) : [ ]
60
- allRecords . push ( ...sdJwtVcRecords )
56
+ // query the wallet ourselves first to avoid the need to query the pex library for all
57
+ // credentials for every proof request
58
+ const mdocDoctypes = dcqlQuery . credentials
59
+ . filter ( ( credentialQuery ) => credentialQuery . format === 'mso_mdoc' )
60
+ . map ( ( c ) => c . meta ?. doctype_value )
61
+ const allMdocCredentialQueriesSpecifyDoctype = mdocDoctypes . every ( ( doctype ) => doctype )
61
62
62
63
const mdocApi = this . getMdocApi ( agentContext )
63
- const mdocRecords = formats . has ( 'mso_mdoc' ) ? await mdocApi . getAll ( ) : [ ]
64
- allRecords . push ( ...mdocRecords )
64
+ if ( allMdocCredentialQueriesSpecifyDoctype ) {
65
+ const mdocRecords = await mdocApi . findAllByQuery ( {
66
+ $or : mdocDoctypes . map ( ( docType ) => ( {
67
+ docType : docType as string ,
68
+ } ) ) ,
69
+ } )
70
+ allRecords . push ( ...mdocRecords )
71
+ } else {
72
+ const mdocRecords = await mdocApi . getAll ( )
73
+ allRecords . push ( ...mdocRecords )
74
+ }
75
+
76
+ // query the wallet ourselves first to avoid the need to query the pex library for all
77
+ // credentials for every proof request
78
+ const sdJwtVctValues = dcqlQuery . credentials
79
+ . filter ( ( credentialQuery ) => credentialQuery . format === 'vc+sd-jwt' )
80
+ . flatMap ( ( c ) => c . meta ?. vct_values )
81
+
82
+ const allSdJwtVcQueriesSpecifyDoctype = sdJwtVctValues . every ( ( vct ) => vct )
83
+
84
+ const sdJwtVcApi = this . getSdJwtVcApi ( agentContext )
85
+ if ( allSdJwtVcQueriesSpecifyDoctype ) {
86
+ const sdjwtVcRecords = await sdJwtVcApi . findAllByQuery ( {
87
+ $or : sdJwtVctValues . map ( ( vct ) => ( {
88
+ vct : vct as string ,
89
+ } ) ) ,
90
+ } )
91
+ allRecords . push ( ...sdjwtVcRecords )
92
+ } else {
93
+ const sdJwtVcRecords = await sdJwtVcApi . getAll ( )
94
+ allRecords . push ( ...sdJwtVcRecords )
95
+ }
65
96
66
97
return allRecords
67
98
}
68
99
69
- public async getCredentialsForRequest ( agentContext : AgentContext , dcqlQuery : DcqlQuery ) : Promise < DcqlQueryResult > {
100
+ public async getCredentialsForRequest (
101
+ agentContext : AgentContext ,
102
+ dcqlQuery : DcqlQuery . Input
103
+ ) : Promise < DcqlQueryResult > {
70
104
const credentialRecords = await this . queryCredentialsForDcqlQuery ( agentContext , dcqlQuery )
71
105
72
- const mappedCredentials : DcqlCredentialRepresentation [ ] = credentialRecords . map ( ( record ) => {
106
+ const dcqlCredentials : DcqlCredential [ ] = credentialRecords . map ( ( record ) => {
73
107
if ( record . type === 'MdocRecord' ) {
74
108
return {
75
- docType : record . getTags ( ) . docType ,
109
+ credentialFormat : 'mso_mdoc' ,
110
+ doctype : record . getTags ( ) . docType ,
76
111
namespaces : Mdoc . fromBase64Url ( record . base64Url ) . issuerSignedNamespaces ,
77
- } satisfies DcqlMdocRepresentation
112
+ } satisfies DcqlMdocCredential
78
113
} else if ( record . type === 'SdJwtVcRecord' ) {
79
114
return {
115
+ credentialFormat : 'vc+sd-jwt' ,
80
116
vct : record . getTags ( ) . vct ,
81
117
claims : this . getSdJwtVcApi ( agentContext ) . fromCompact ( record . compactSdJwtVc )
82
- . prettyClaims as DcqlSdJwtVcRepresentation . Claims ,
83
- } satisfies DcqlSdJwtVcRepresentation
118
+ . prettyClaims as DcqlSdJwtVcCredential . Claims ,
119
+ } satisfies DcqlSdJwtVcCredential
84
120
} else {
85
121
// TODO:
86
122
throw new DcqlError ( 'W3C credentials are not supported yet' )
87
123
}
88
124
} )
89
125
90
- const queryResult = DcqlQuery . query ( dcqlQuery , mappedCredentials )
126
+ const queryResult = DcqlQuery . query ( DcqlQuery . parse ( dcqlQuery ) , dcqlCredentials )
91
127
const matchesWithRecord = Object . fromEntries (
92
128
Object . entries ( queryResult . credential_matches ) . map ( ( [ credential_query_id , result ] ) => {
93
129
return [ credential_query_id , { ...result , record : credentialRecords [ result . credential_index ] } ]
0 commit comments