@sovrahq/waci 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.js +21 -0
  3. package/.prettierrc +4 -0
  4. package/LICENSE +201 -0
  5. package/dist/callbacks/index.d.ts +108 -0
  6. package/dist/callbacks/index.js +9 -0
  7. package/dist/callbacks/index.js.map +1 -0
  8. package/dist/constants/index.d.ts +1 -0
  9. package/dist/constants/index.js +5 -0
  10. package/dist/constants/index.js.map +1 -0
  11. package/dist/handlers/common/problem-report.handler.d.ts +4 -0
  12. package/dist/handlers/common/problem-report.handler.js +72 -0
  13. package/dist/handlers/common/problem-report.handler.js.map +1 -0
  14. package/dist/handlers/common/step-2-oob-invitation.handler.d.ts +4 -0
  15. package/dist/handlers/common/step-2-oob-invitation.handler.js +93 -0
  16. package/dist/handlers/common/step-2-oob-invitation.handler.js.map +1 -0
  17. package/dist/handlers/decorators/register-handler.decorator.d.ts +2 -0
  18. package/dist/handlers/decorators/register-handler.decorator.js +13 -0
  19. package/dist/handlers/decorators/register-handler.decorator.js.map +1 -0
  20. package/dist/handlers/index.d.ts +6 -0
  21. package/dist/handlers/index.js +11 -0
  22. package/dist/handlers/index.js.map +1 -0
  23. package/dist/handlers/issuance/step-3-propose-credential.handler.d.ts +32 -0
  24. package/dist/handlers/issuance/step-3-propose-credential.handler.js +180 -0
  25. package/dist/handlers/issuance/step-3-propose-credential.handler.js.map +1 -0
  26. package/dist/handlers/issuance/step-4-1-offer-credential-proceed.handler.d.ts +5 -0
  27. package/dist/handlers/issuance/step-4-1-offer-credential-proceed.handler.js +152 -0
  28. package/dist/handlers/issuance/step-4-1-offer-credential-proceed.handler.js.map +1 -0
  29. package/dist/handlers/issuance/step-4-offer-credential.handler.d.ts +5 -0
  30. package/dist/handlers/issuance/step-4-offer-credential.handler.js +169 -0
  31. package/dist/handlers/issuance/step-4-offer-credential.handler.js.map +1 -0
  32. package/dist/handlers/issuance/step-5-request-credential.handler.d.ts +4 -0
  33. package/dist/handlers/issuance/step-5-request-credential.handler.js +275 -0
  34. package/dist/handlers/issuance/step-5-request-credential.handler.js.map +1 -0
  35. package/dist/handlers/issuance/step-6-issue-credential.handler.d.ts +4 -0
  36. package/dist/handlers/issuance/step-6-issue-credential.handler.js +106 -0
  37. package/dist/handlers/issuance/step-6-issue-credential.handler.js.map +1 -0
  38. package/dist/handlers/issuance/step-7-ack-message.handler.d.ts +4 -0
  39. package/dist/handlers/issuance/step-7-ack-message.handler.js +78 -0
  40. package/dist/handlers/issuance/step-7-ack-message.handler.js.map +1 -0
  41. package/dist/handlers/presentation/step-3-propose-presentation.handler.d.ts +5 -0
  42. package/dist/handlers/presentation/step-3-propose-presentation.handler.js +107 -0
  43. package/dist/handlers/presentation/step-3-propose-presentation.handler.js.map +1 -0
  44. package/dist/handlers/presentation/step-4-1-presentation-proceed.handler.d.ts +5 -0
  45. package/dist/handlers/presentation/step-4-1-presentation-proceed.handler.js +130 -0
  46. package/dist/handlers/presentation/step-4-1-presentation-proceed.handler.js.map +1 -0
  47. package/dist/handlers/presentation/step-4-request-presentation.handler.d.ts +5 -0
  48. package/dist/handlers/presentation/step-4-request-presentation.handler.js +151 -0
  49. package/dist/handlers/presentation/step-4-request-presentation.handler.js.map +1 -0
  50. package/dist/handlers/presentation/step-5-present-proof.handler.d.ts +4 -0
  51. package/dist/handlers/presentation/step-5-present-proof.handler.js +211 -0
  52. package/dist/handlers/presentation/step-5-present-proof.handler.js.map +1 -0
  53. package/dist/handlers/presentation/step-6-ack-message.handler.d.ts +4 -0
  54. package/dist/handlers/presentation/step-6-ack-message.handler.js +72 -0
  55. package/dist/handlers/presentation/step-6-ack-message.handler.js.map +1 -0
  56. package/dist/index.d.ts +17 -0
  57. package/dist/index.js +37 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/services/waci-interpreter.d.ts +17 -0
  60. package/dist/services/waci-interpreter.js +222 -0
  61. package/dist/services/waci-interpreter.js.map +1 -0
  62. package/dist/types/actor.d.ts +5 -0
  63. package/dist/types/actor.js +10 -0
  64. package/dist/types/actor.js.map +1 -0
  65. package/dist/types/credential-application.d.ts +36 -0
  66. package/dist/types/credential-application.js +3 -0
  67. package/dist/types/credential-application.js.map +1 -0
  68. package/dist/types/credential-manifest.d.ts +173 -0
  69. package/dist/types/credential-manifest.js +3 -0
  70. package/dist/types/credential-manifest.js.map +1 -0
  71. package/dist/types/index.d.ts +4 -0
  72. package/dist/types/index.js +21 -0
  73. package/dist/types/index.js.map +1 -0
  74. package/dist/types/problem-report.d.ts +13 -0
  75. package/dist/types/problem-report.js +18 -0
  76. package/dist/types/problem-report.js.map +1 -0
  77. package/dist/types/waci-message.d.ts +106 -0
  78. package/dist/types/waci-message.js +106 -0
  79. package/dist/types/waci-message.js.map +1 -0
  80. package/dist/utils/erros.d.ts +15 -0
  81. package/dist/utils/erros.js +42 -0
  82. package/dist/utils/erros.js.map +1 -0
  83. package/dist/utils/index.d.ts +22 -0
  84. package/dist/utils/index.js +356 -0
  85. package/dist/utils/index.js.map +1 -0
  86. package/jest.config.json +17 -0
  87. package/package.json +39 -0
  88. package/readme.md +1 -0
  89. package/src/callbacks/index.ts +75 -0
  90. package/src/constants/index.ts +1 -0
  91. package/src/handlers/common/problem-report.handler.ts +15 -0
  92. package/src/handlers/common/step-2-oob-invitation.handler.ts +45 -0
  93. package/src/handlers/decorators/register-handler.decorator.ts +10 -0
  94. package/src/handlers/index.ts +7 -0
  95. package/src/handlers/issuance/step-3-propose-credential.handler.ts +186 -0
  96. package/src/handlers/issuance/step-4-1-offer-credential-proceed.handler.ts +129 -0
  97. package/src/handlers/issuance/step-4-offer-credential.handler.ts +137 -0
  98. package/src/handlers/issuance/step-5-request-credential.handler.ts +205 -0
  99. package/src/handlers/issuance/step-6-issue-credential.handler.ts +63 -0
  100. package/src/handlers/issuance/step-7-ack-message.handler.ts +21 -0
  101. package/src/handlers/presentation/step-3-propose-presentation.handler.ts +67 -0
  102. package/src/handlers/presentation/step-4-1-presentation-proceed.handler.ts +100 -0
  103. package/src/handlers/presentation/step-4-request-presentation.handler.ts +115 -0
  104. package/src/handlers/presentation/step-5-present-proof.handler.ts +159 -0
  105. package/src/handlers/presentation/step-6-ack-message.handler.ts +15 -0
  106. package/src/index.ts +18 -0
  107. package/src/services/waci-interpreter.ts +161 -0
  108. package/src/types/actor.ts +5 -0
  109. package/src/types/credential-application.ts +38 -0
  110. package/src/types/credential-manifest.ts +184 -0
  111. package/src/types/index.ts +4 -0
  112. package/src/types/problem-report.ts +29 -0
  113. package/src/types/waci-message.ts +148 -0
  114. package/src/utils/erros.ts +21 -0
  115. package/src/utils/index.ts +272 -0
  116. package/test/handlers/issuance/step-3-propose-credential.handler.spec.ts +43 -0
  117. package/test/handlers/issuance/step-4-offer-credential.handler.spec.ts +53 -0
  118. package/test/handlers/issuance/step-5-request-credential.handler.spec.ts +102 -0
  119. package/test/handlers/presentation/step-5-present-proof.handler.spec.ts +142 -0
  120. package/test/handlers/shared/step-2-oob-invitation.handler.spec.ts +55 -0
  121. package/test/stubs/index.ts +842 -0
  122. package/test/waci-interpreter.spec.ts +113 -0
  123. package/tsconfig.build.json +9 -0
  124. package/tsconfig.json +20 -0
@@ -0,0 +1,186 @@
1
+ import { RegisterHandler } from '../decorators/register-handler.decorator';
2
+ import {
3
+ WACIMessage,
4
+ WACIMessageHandler,
5
+ WACIMessageHandlerResponse,
6
+ WACIMessageResponseType,
7
+ WACIMessageType,
8
+ Actor,
9
+ CredentialManifest,
10
+ CredentialFulfillment,
11
+ PresentationDefinition,
12
+ InputDescriptor,
13
+ OutputDescriptor,
14
+ PresentationDefinitionFrame,
15
+ } from '../../types';
16
+ import { createUUID } from '../../utils';
17
+ import { ProblemReportMessage } from '../../types/problem-report';
18
+
19
+ export type OfferCredentialMessageParamsBase =
20
+ | OfferCredentialMessageParams
21
+ | OfferCredentialMessageParamsFailed
22
+ | OfferCredentialMessageParamsAsyncProcess;
23
+
24
+ export type OfferCredentialMessageParams = {
25
+ issuerDid: string;
26
+ issuerName: string;
27
+ issuerStyles: any;
28
+ output: {
29
+ outputDescriptor: OutputDescriptor;
30
+ verifiableCredential: any;
31
+ //Verificar de donde sale este dato
32
+ format: 'ldp_vc' | '';
33
+ }[];
34
+ input?: InputDescriptor[];
35
+ frame?: PresentationDefinitionFrame;
36
+ result?: OfferCredentialMessageResult.Succeded;
37
+ };
38
+
39
+ export type OfferCredentialMessageParamsFailed = {
40
+ result?: OfferCredentialMessageResult.Failed;
41
+ errorMessage?: string;
42
+ };
43
+
44
+ export type OfferCredentialMessageParamsAsyncProcess = {
45
+ result?: OfferCredentialMessageResult.AsyncProcess;
46
+ errorMessage?: string;
47
+ };
48
+
49
+ @RegisterHandler(Actor.Issuer, WACIMessageType.ProposeCredential)
50
+ export class ProposeCredentialHandler implements WACIMessageHandler {
51
+ async handle(
52
+ messageThread: WACIMessage[],
53
+ callbacks: any,
54
+ ): Promise<WACIMessageHandlerResponse> {
55
+ const message = messageThread[messageThread.length - 1];
56
+ const holderDID = message.from;
57
+ const issuerDID = message.to[0];
58
+ const invitationId = message.pthid;
59
+ const credentialManifestParams = await callbacks[
60
+ Actor.Issuer
61
+ ].getCredentialManifest({
62
+ invitationId: invitationId,
63
+ holderDid: holderDID,
64
+ message,
65
+ });
66
+
67
+ credentialManifestParams.result =
68
+ credentialManifestParams.result || OfferCredentialMessageResult.Succeded;
69
+
70
+ if (
71
+ credentialManifestParams.result == OfferCredentialMessageResult.Succeded
72
+ ) {
73
+ const credentialManifest = this.createMessage(credentialManifestParams);
74
+
75
+ return {
76
+ responseType: WACIMessageResponseType.ReplyThread,
77
+ message: {
78
+ type: WACIMessageType.OfferCredential,
79
+ id: createUUID(),
80
+ thid: message.id,
81
+ from: issuerDID,
82
+ to: [holderDID],
83
+ body: {},
84
+ attachments: credentialManifest,
85
+ },
86
+ };
87
+ } else if (
88
+ credentialManifestParams.result == OfferCredentialMessageResult.Failed
89
+ ) {
90
+ const problemReport = new ProblemReportMessage();
91
+
92
+ return {
93
+ responseType: WACIMessageResponseType.ReplyThread,
94
+ message: {
95
+ type: WACIMessageType.ProblemReport,
96
+ id: createUUID(),
97
+ thid: message.id,
98
+ from: issuerDID,
99
+ to: [holderDID],
100
+ body: problemReport.presentProofMessage(
101
+ "credential_issuance_error",
102
+ credentialManifestParams.errorMessage,
103
+ ),
104
+ },
105
+ };
106
+ }
107
+
108
+ //If credentialManifestParams.result == OfferCredentialMessageResult.AsyncProcess do nothing
109
+ }
110
+
111
+ private createMessage(
112
+ params: OfferCredentialMessageParams,
113
+ ): (CredentialManifest | CredentialFulfillment)[] {
114
+ const manifestId = createUUID();
115
+ const presentationDefinition: PresentationDefinition = params.input?.length
116
+ ? {
117
+ id: createUUID(),
118
+ input_descriptors: params.input,
119
+ frame: params.frame,
120
+ }
121
+ : undefined;
122
+
123
+
124
+ return [
125
+ {
126
+ id: createUUID(),
127
+ media_type: 'application/json',
128
+ format: 'dif/credential-manifest/manifest@v1.0',
129
+ data: {
130
+ json: {
131
+ options: {
132
+ challenge: createUUID(),
133
+ },
134
+ credential_manifest: {
135
+ id: manifestId,
136
+ version: '0.1.0',
137
+ issuer: {
138
+ id: params.issuerDid,
139
+ name: params.issuerName,
140
+ styles: params.issuerStyles
141
+ },
142
+ presentation_definition: presentationDefinition,
143
+ output_descriptors: params.output.map(
144
+ (descriptors) => descriptors.outputDescriptor,
145
+ ),
146
+ },
147
+ },
148
+ },
149
+ },
150
+ {
151
+ id: createUUID(),
152
+ media_type: 'application/json',
153
+ format: 'dif/credential-manifest/fulfillment@v1.0',
154
+ data: {
155
+ json: {
156
+ '@context': [
157
+ 'https://extrimian.blob.core.windows.net/rskec/credentialsv1.jsonld',
158
+ 'https://extrimian.blob.core.windows.net/rskec/credential-manifestfulfillmentv1.jsonld',
159
+ ],
160
+ type: ['VerifiablePresentation', 'CredentialFulfillment'],
161
+ credential_fulfillment: {
162
+ id: createUUID(),
163
+ manifest_id: manifestId,
164
+ descriptor_map: params.output.map((descriptor, index) => {
165
+ return {
166
+ id: descriptor.outputDescriptor.id,
167
+ format: descriptor.format || 'ldp_vp',
168
+ path: `$.verifiableCredential[${index}]`,
169
+ };
170
+ }),
171
+ },
172
+ verifiableCredential: params.output.map(
173
+ (vcData) => vcData.verifiableCredential,
174
+ ),
175
+ },
176
+ },
177
+ },
178
+ ];
179
+ }
180
+ }
181
+
182
+ export enum OfferCredentialMessageResult {
183
+ Succeded,
184
+ Failed,
185
+ AsyncProcess,
186
+ }
@@ -0,0 +1,129 @@
1
+ import { RegisterHandler } from '../decorators/register-handler.decorator';
2
+ import {
3
+ WACIMessage,
4
+ WACIMessageHandler,
5
+ WACIMessageHandlerResponse,
6
+ WACIMessageType,
7
+ WACIMessageResponseType,
8
+ Actor,
9
+ CredentialApplication,
10
+ CredentialManifest,
11
+ CredentialFulfillment,
12
+ } from '../../types';
13
+ import { createUUID } from '../../utils';
14
+ import { isNil } from 'lodash';
15
+
16
+ export class OfferCredentialProceed {
17
+ static async handle(
18
+ messageThread: WACIMessage[],
19
+ credentialsToPresent: any[],
20
+ presentationProofTypes: string[],
21
+ callbacks: any,
22
+ ): Promise<WACIMessageHandlerResponse> {
23
+ const message = messageThread[messageThread.length - 1];
24
+ const holderDID = message.to[0];
25
+ const issuerDID = message.from;
26
+
27
+ const credentialApplicationParams = {
28
+ manifest: message.attachments.find(
29
+ (attachment) => !isNil(attachment?.data?.json?.credential_manifest),
30
+ ) as CredentialManifest,
31
+ fulfillment: message.attachments.find(
32
+ (attachment) => !isNil(attachment?.data?.json?.credential_fulfillment),
33
+ ) as CredentialFulfillment,
34
+ message
35
+ };
36
+
37
+ if (!credentialApplicationParams.manifest)
38
+ throw new Error('Malformed offer credential message');
39
+
40
+ const credentialApplication = await this.createMessage(
41
+ credentialsToPresent,
42
+ presentationProofTypes,
43
+ credentialApplicationParams.manifest,
44
+ message,
45
+ callbacks,
46
+ );
47
+
48
+ return {
49
+ responseType: WACIMessageResponseType.ReplyThread,
50
+ message: {
51
+ type: WACIMessageType.RequestCredential,
52
+ id: createUUID(),
53
+ thid: message.thid,
54
+ from: holderDID,
55
+ to: [issuerDID],
56
+ body: {},
57
+
58
+ attachments: credentialApplication ? [credentialApplication] : [],
59
+ },
60
+ };
61
+ }
62
+
63
+ private static async createMessage(
64
+ verifiableCredential: any[],
65
+ proofTypes: string[],
66
+ manifest: CredentialManifest,
67
+ message: WACIMessage,
68
+ callbacks: any
69
+ ): Promise<CredentialApplication> {
70
+ const credential_manifest = manifest?.data?.json?.credential_manifest;
71
+ const manifest_id = credential_manifest?.id;
72
+ const presentation_definition =
73
+ credential_manifest?.presentation_definition;
74
+ const definition_id = presentation_definition?.id;
75
+ const input_descriptors = presentation_definition?.input_descriptors;
76
+ const challenge = manifest?.data?.json?.options?.challenge;
77
+
78
+ if (!challenge) throw new Error('No challenge defined');
79
+ if (!input_descriptors?.length) return;
80
+
81
+ const descriptor_map = input_descriptors?.map((descriptor, index) => ({
82
+ id: descriptor.id,
83
+ format: 'ldp_vp',
84
+ path: `$.verifiableCredential[${index}]`,
85
+ }));
86
+
87
+ if (!proofTypes?.length) throw new Error('Proof types need to be defined');
88
+ if (!manifest_id) throw new Error('Malformed credential manifest');
89
+
90
+ const messageData = {
91
+ '@context': [
92
+ 'https://extrimian.blob.core.windows.net/rskec/securityv1.jsonld',
93
+ 'https://extrimian.blob.core.windows.net/rskec/credentialsv1.jsonld',
94
+ 'https://extrimian.blob.core.windows.net/rskec/credential-manifestapplicationv1.jsonld',
95
+ ],
96
+ type: ['VerifiablePresentation', 'CredentialApplication'],
97
+ credential_application: {
98
+ id: createUUID(),
99
+ manifest_id,
100
+ format: {
101
+ ldp_vc: {
102
+ proof_type: proofTypes,
103
+ },
104
+ },
105
+ },
106
+ presentation_submission: {
107
+ id: createUUID(),
108
+ definition_id,
109
+ descriptor_map,
110
+ },
111
+ verifiableCredential,
112
+ };
113
+
114
+ const signedData = await callbacks[Actor.Holder].signPresentation({
115
+ contentToSign: messageData,
116
+ challenge,
117
+ message
118
+ });
119
+
120
+ return {
121
+ id: createUUID(),
122
+ media_type: 'application/json',
123
+ format: 'dif/credential-manifest/application@v1.0',
124
+ data: {
125
+ json: signedData,
126
+ },
127
+ } as CredentialApplication;
128
+ }
129
+ }
@@ -0,0 +1,137 @@
1
+ import { RegisterHandler } from '../decorators/register-handler.decorator';
2
+ import {
3
+ WACIMessage,
4
+ WACIMessageHandler,
5
+ WACIMessageHandlerResponse,
6
+ WACIMessageType,
7
+ WACIMessageResponseType,
8
+ Actor,
9
+ CredentialApplication,
10
+ CredentialManifest,
11
+ CredentialFulfillment,
12
+ } from '../../types';
13
+ import { createUUID } from '../../utils';
14
+ import { CredentialPresentationResponse } from '../../callbacks';
15
+ import { isNil } from 'lodash';
16
+
17
+ @RegisterHandler(Actor.Holder, WACIMessageType.OfferCredential)
18
+ export class OfferCredentialHandler implements WACIMessageHandler {
19
+ async handle(
20
+ messageThread: WACIMessage[],
21
+ callbacks: any,
22
+ ): Promise<WACIMessageHandlerResponse> {
23
+ const message = messageThread[messageThread.length - 1];
24
+ const holderDID = message.to[0];
25
+ const issuerDID = message.from;
26
+
27
+ const credentialApplicationParams = {
28
+ manifest: message.attachments.find(
29
+ (attachment) => !isNil(attachment?.data?.json?.credential_manifest),
30
+ ) as CredentialManifest,
31
+ fulfillment: message.attachments.find(
32
+ (attachment) => !isNil(attachment?.data?.json?.credential_fulfillment),
33
+ ) as CredentialFulfillment,
34
+ message
35
+ };
36
+
37
+ if (!credentialApplicationParams.manifest)
38
+ throw new Error('Malformed offer credential message');
39
+
40
+ const response = await callbacks[
41
+ Actor.Holder
42
+ ].getCredentialApplication(credentialApplicationParams);
43
+
44
+ if (response == CredentialPresentationResponse.AsyncProcess) {
45
+ return;
46
+ }
47
+
48
+ const credentialApplication = await this.createMessage(
49
+ response.credentialsToPresent,
50
+ response.presentationProofTypes,
51
+ credentialApplicationParams.manifest,
52
+ message,
53
+ callbacks,
54
+ );
55
+
56
+ return {
57
+ responseType: WACIMessageResponseType.ReplyThread,
58
+ message: {
59
+ type: WACIMessageType.RequestCredential,
60
+ id: createUUID(),
61
+ thid: message.thid,
62
+ from: holderDID,
63
+ to: [issuerDID],
64
+ body: {},
65
+
66
+ attachments: credentialApplication ? [credentialApplication] : [],
67
+ },
68
+ };
69
+ }
70
+
71
+ private async createMessage(
72
+ verifiableCredential: any[],
73
+ proofTypes: string[],
74
+ manifest: CredentialManifest,
75
+ message: WACIMessage,
76
+ callbacks: any
77
+ ): Promise<CredentialApplication> {
78
+ const credential_manifest = manifest?.data?.json?.credential_manifest;
79
+ const manifest_id = credential_manifest?.id;
80
+ const presentation_definition =
81
+ credential_manifest?.presentation_definition;
82
+ const definition_id = presentation_definition?.id;
83
+ const input_descriptors = presentation_definition?.input_descriptors;
84
+ const challenge = manifest?.data?.json?.options?.challenge;
85
+
86
+ if (!challenge) throw new Error('No challenge defined');
87
+ if (!input_descriptors?.length) return;
88
+
89
+ const descriptor_map = input_descriptors?.map((descriptor, index) => ({
90
+ id: descriptor.id,
91
+ format: 'ldp_vp',
92
+ path: `$.verifiableCredential[${index}]`,
93
+ }));
94
+
95
+ if (!proofTypes?.length) throw new Error('Proof types need to be defined');
96
+ if (!manifest_id) throw new Error('Malformed credential manifest');
97
+
98
+ const messageData = {
99
+ '@context': [
100
+ 'https://extrimian.blob.core.windows.net/rskec/securityv1.jsonld',
101
+ 'https://extrimian.blob.core.windows.net/rskec/credentialsv1.jsonld',
102
+ 'https://extrimian.blob.core.windows.net/rskec/credential-manifestapplicationv1.jsonld',
103
+ ],
104
+ type: ['VerifiablePresentation', 'CredentialApplication'],
105
+ credential_application: {
106
+ id: createUUID(),
107
+ manifest_id,
108
+ format: {
109
+ ldp_vc: {
110
+ proof_type: proofTypes,
111
+ },
112
+ },
113
+ },
114
+ presentation_submission: {
115
+ id: createUUID(),
116
+ definition_id,
117
+ descriptor_map,
118
+ },
119
+ verifiableCredential,
120
+ };
121
+
122
+ const signedData = await callbacks[Actor.Holder].signPresentation({
123
+ contentToSign: messageData,
124
+ challenge,
125
+ message
126
+ });
127
+
128
+ return {
129
+ id: createUUID(),
130
+ media_type: 'application/json',
131
+ format: 'dif/credential-manifest/application@v1.0',
132
+ data: {
133
+ json: signedData,
134
+ },
135
+ } as CredentialApplication;
136
+ }
137
+ }
@@ -0,0 +1,205 @@
1
+ import { isNil } from 'lodash';
2
+ import { RegisterHandler } from '../decorators/register-handler.decorator';
3
+ import {
4
+ WACIMessage,
5
+ WACIMessageHandler,
6
+ WACIMessageHandlerResponse,
7
+ WACIMessageType,
8
+ WACIMessageResponseType,
9
+ Actor,
10
+ CredentialManifest,
11
+ CredentialFulfillment,
12
+ } from '../../types';
13
+ import {
14
+ extractExpectedChallenge,
15
+ createUUID,
16
+ verifyPresentation,
17
+ } from '../../utils';
18
+ import { ProblemReportMessage } from '../../types/problem-report';
19
+
20
+ @RegisterHandler(Actor.Issuer, WACIMessageType.RequestCredential)
21
+ export class RequestCredentialHandler implements WACIMessageHandler {
22
+ async handle(
23
+ messageThread: WACIMessage[],
24
+ callbacks: any,
25
+ ): Promise<WACIMessageHandlerResponse | void> {
26
+ const messageToProcess = messageThread[messageThread.length - 1];
27
+ const holderDID = messageToProcess.from;
28
+ const issuerDID = messageToProcess.to[0];
29
+ const problemReport = new ProblemReportMessage();
30
+ const offerCredentialMessage = messageThread.find(
31
+ (message) => message.type === WACIMessageType.OfferCredential,
32
+ );
33
+
34
+ try {
35
+ const manifests: CredentialManifest[] =
36
+ offerCredentialMessage.attachments.filter(
37
+ (attachment) => !isNil(attachment?.data?.json?.credential_manifest),
38
+ );
39
+
40
+ const applicationsToCheck = manifests
41
+ .filter(
42
+ (manifest) =>
43
+ !isNil(
44
+ manifest?.data?.json?.credential_manifest?.presentation_definition,
45
+ ),
46
+ )
47
+ .map((manifest) => ({
48
+ presentationDefinition:
49
+ manifest.data.json.credential_manifest.presentation_definition,
50
+ application: messageToProcess.attachments.find(
51
+ (attachment) =>
52
+ attachment.data.json.credential_application.manifest_id ===
53
+ manifest.data.json.credential_manifest.id,
54
+ ),
55
+ }));
56
+
57
+ const verificationResultCallback = callbacks[Actor.Issuer]?.credentialVerificationResult;
58
+ let vcs = [];
59
+
60
+ if (
61
+ applicationsToCheck.every((applicationToCheck) =>
62
+ !isNil(applicationToCheck.application),
63
+ )
64
+ ) {
65
+ for await (const applicationToCheck of applicationsToCheck) {
66
+ const verify = await verifyPresentation(
67
+ applicationToCheck.presentationDefinition,
68
+ applicationToCheck.application,
69
+ callbacks[Actor.Issuer].verifyCredential,
70
+ );
71
+ let result = verify.result;
72
+
73
+ for (let vc of verify.vcs) {
74
+ vcs.push(vc);
75
+ }
76
+
77
+ if (!result) {
78
+ if (verificationResultCallback) {
79
+ verificationResultCallback({
80
+ result: verify.result,
81
+ error: verify.erorrs,
82
+ thid: messageToProcess.thid,
83
+ vcs: verify.vcs,
84
+ message: messageToProcess,
85
+ })
86
+ }
87
+
88
+ return {
89
+ responseType: WACIMessageResponseType.ReplyThread,
90
+ message: {
91
+ type: WACIMessageType.ProblemReport,
92
+ id: createUUID(),
93
+ thid: messageToProcess.id,
94
+ from: issuerDID,
95
+ to: [holderDID],
96
+ body: problemReport.presentProofMessage(
97
+ verify.error.name,
98
+ verify.error.description,
99
+ ),
100
+ },
101
+ };
102
+ }
103
+
104
+ if (applicationsToCheck.length) {
105
+ const challengeToCheck = extractExpectedChallenge(
106
+ offerCredentialMessage,
107
+ );
108
+
109
+ const presentation = messageToProcess.attachments[0].data.json;
110
+ const verifyPresentationResult = await callbacks[
111
+ Actor.Issuer
112
+ ].verifyPresentation({ presentation, challenge: challengeToCheck, message: messageToProcess, holderDid: holderDID });
113
+ if (!verifyPresentationResult.result) {
114
+ return {
115
+ responseType: WACIMessageResponseType.ReplyThread,
116
+ message: {
117
+ type: WACIMessageType.ProblemReport,
118
+ id: createUUID(),
119
+ thid: messageToProcess.id,
120
+ from: issuerDID,
121
+ to: [holderDID],
122
+ body: problemReport.presentProofMessage(
123
+ verifyPresentationResult.error.name,
124
+ verifyPresentationResult.error.description,
125
+ ),
126
+ },
127
+ };
128
+ }
129
+
130
+ }
131
+ }
132
+
133
+ if (verificationResultCallback) {
134
+ verificationResultCallback({
135
+ result: true,
136
+ error: null,
137
+ thid: messageToProcess.thid,
138
+ vcs: vcs,
139
+ message: messageToProcess,
140
+ })
141
+ }
142
+ }
143
+
144
+
145
+ const fulfillments: CredentialFulfillment[] =
146
+ offerCredentialMessage.attachments.filter(
147
+ (attachment) =>
148
+ !isNil(attachment?.data?.json?.credential_fulfillment),
149
+ );
150
+
151
+ let attachments = [];
152
+
153
+ for (let f of fulfillments) {
154
+ const attachment = {
155
+ id: createUUID(),
156
+ media_type: 'application/json',
157
+ format: 'dif/credential-manifest/fulfillment@v1.0',
158
+ data: {
159
+ json: {
160
+ ...f.data.json,
161
+ },
162
+ },
163
+ };
164
+ attachment.data.json.verifiableCredential = [];
165
+
166
+ for (let vc of f.data.json.verifiableCredential) {
167
+ attachment.data.json.verifiableCredential.push(await callbacks[Actor.Issuer].signCredential({ vc: vc, message: messageToProcess }));
168
+ }
169
+
170
+ attachments.push(attachment);
171
+ }
172
+
173
+ return {
174
+ responseType: WACIMessageResponseType.ReplyThread,
175
+ message: {
176
+ type: WACIMessageType.IssueCredential,
177
+ id: createUUID(),
178
+ thid: messageToProcess.thid,
179
+ from: issuerDID,
180
+ to: [holderDID],
181
+ body: {},
182
+ attachments: attachments,
183
+ },
184
+ };
185
+ }
186
+ catch (ex) {
187
+ return {
188
+ responseType: WACIMessageResponseType.ReplyThread,
189
+ message: {
190
+ type: WACIMessageType.ProblemReport,
191
+ id: createUUID(),
192
+ thid: messageToProcess.id,
193
+ from: issuerDID,
194
+ to: [holderDID],
195
+ body: problemReport.presentProofMessage(
196
+ 'unexpected-error',
197
+ 'Unexpected error: ' + ex?.message,
198
+ )
199
+ },
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+