@mattrglobal/verifier-sdk-web 2.0.0-preview-digital-credential-api.4 → 2.0.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.
- package/README.md +71 -86
- package/dist/lib/verifier-js-no-deps.cjs.js +608 -336
- package/dist/lib/verifier-js-no-deps.cjs.js.map +1 -1
- package/dist/lib/verifier-js.cjs.js +911 -511
- package/dist/lib/verifier-js.cjs.js.map +1 -1
- package/dist/typings/common/safeFetch.d.ts +6 -3
- package/dist/typings/common/sleep.d.ts +1 -0
- package/dist/typings/index.d.ts +6 -7
- package/dist/typings/verifier/abortCredentialRequest.d.ts +6 -0
- package/dist/typings/verifier/handleRedirectCallback.d.ts +1 -1
- package/dist/typings/verifier/index.d.ts +3 -1
- package/dist/typings/verifier/initialize.d.ts +12 -0
- package/dist/typings/verifier/instanceContext.d.ts +7 -0
- package/dist/typings/verifier/requestCredentials.d.ts +2 -2
- package/dist/typings/verifier/requestCredentialsCrossDevice.d.ts +3 -47
- package/dist/typings/verifier/requestCredentialsDigitalCredentialsApi.d.ts +17 -0
- package/dist/typings/verifier/requestCredentialsSameDevice.d.ts +1 -1
- package/dist/typings/verifier/types/credential-presentation.d.ts +136 -37
- package/dist/typings/verifier/types/verifier-web-sdk.d.ts +153 -214
- package/dist/typings/verifier/utils.d.ts +23 -37
- package/dist/verifier-js.development.js +866 -499
- package/dist/verifier-js.development.js.map +1 -1
- package/dist/verifier-js.production.esm.js +4 -4
- package/dist/verifier-js.production.esm.js.map +1 -1
- package/dist/verifier-js.production.js +4 -4
- package/dist/verifier-js.production.js.map +1 -1
- package/package.json +3 -3
- package/dist/typings/verifier/initialise.d.ts +0 -12
- package/dist/typings/verifier/requestCredentialsViaDigitalCredentialsApi.d.ts +0 -7
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* Do Not Translate or Localize
|
|
8
8
|
*
|
|
9
9
|
* Bundle of @mattrglobal/verifier-sdk-web
|
|
10
|
-
* Generated: 2025-
|
|
11
|
-
* Version: 2.0.0
|
|
10
|
+
* Generated: 2025-05-28
|
|
11
|
+
* Version: 2.0.0
|
|
12
12
|
* Dependencies:
|
|
13
13
|
*/
|
|
14
14
|
|
|
@@ -69,10 +69,20 @@ const unwrap = (result, errMessage) => {
|
|
|
69
69
|
|
|
70
70
|
const isType = validator => value => v__namespace.safeParse(validator, value).success;
|
|
71
71
|
|
|
72
|
-
const getValidationErrors = issues =>
|
|
73
|
-
message: message,
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
const getValidationErrors = issues => {
|
|
73
|
+
const formatIssue = ({message: message, path: path}) => ({
|
|
74
|
+
message: message,
|
|
75
|
+
path: path === null || path === void 0 ? void 0 : path.map((p => p.key))
|
|
76
|
+
});
|
|
77
|
+
const uniqueErrors = new Map;
|
|
78
|
+
issues.flatMap((issue => issue.type === "union" && issue.issues ? issue.issues.map(formatIssue) : [ formatIssue(issue) ])).forEach((error => {
|
|
79
|
+
const key = `${error.message}-${JSON.stringify(error.path)}`;
|
|
80
|
+
if (!uniqueErrors.has(key)) {
|
|
81
|
+
uniqueErrors.set(key, error);
|
|
82
|
+
}
|
|
83
|
+
}));
|
|
84
|
+
return Array.from(uniqueErrors.values());
|
|
85
|
+
};
|
|
76
86
|
|
|
77
87
|
const validateType = (value, validator) => {
|
|
78
88
|
const result = v__namespace.safeParse(validator, value);
|
|
@@ -89,47 +99,21 @@ const assertType = (validator, message) => data => {
|
|
|
89
99
|
}
|
|
90
100
|
};
|
|
91
101
|
|
|
92
|
-
var SafeFetchCommonRespondErrorType;
|
|
93
|
-
|
|
94
|
-
(function(SafeFetchCommonRespondErrorType) {
|
|
95
|
-
SafeFetchCommonRespondErrorType["UnexpectedRespond"] = "UnexpectedRespond";
|
|
96
|
-
})(SafeFetchCommonRespondErrorType || (SafeFetchCommonRespondErrorType = {}));
|
|
97
|
-
|
|
98
|
-
var SafeFetchErrorType;
|
|
99
|
-
|
|
100
|
-
(function(SafeFetchErrorType) {
|
|
101
|
-
SafeFetchErrorType["HttpError"] = "HttpError";
|
|
102
|
-
SafeFetchErrorType["UnknownError"] = "UnknownError";
|
|
103
|
-
})(SafeFetchErrorType || (SafeFetchErrorType = {}));
|
|
104
|
-
|
|
105
|
-
const safeFetch = async (input, init) => {
|
|
106
|
-
try {
|
|
107
|
-
const response = await fetch(input, init);
|
|
108
|
-
if (response.status > 299 || response.status < 200) {
|
|
109
|
-
return neverthrow.err({
|
|
110
|
-
type: SafeFetchErrorType.HttpError,
|
|
111
|
-
message: `HTTP error, status = ${response.status}`,
|
|
112
|
-
status: response.status
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
return neverthrow.ok(response);
|
|
116
|
-
} catch (error) {
|
|
117
|
-
return neverthrow.err({
|
|
118
|
-
type: SafeFetchErrorType.UnknownError,
|
|
119
|
-
message: "Unknown error",
|
|
120
|
-
cause: error
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
102
|
exports.MobileCredentialVerificationReasonType = void 0;
|
|
126
103
|
|
|
127
104
|
(function(MobileCredentialVerificationReasonType) {
|
|
128
|
-
MobileCredentialVerificationReasonType["
|
|
129
|
-
MobileCredentialVerificationReasonType["
|
|
130
|
-
MobileCredentialVerificationReasonType["
|
|
131
|
-
MobileCredentialVerificationReasonType["
|
|
132
|
-
MobileCredentialVerificationReasonType["
|
|
105
|
+
MobileCredentialVerificationReasonType["TrustedIssuerCertificateExpired"] = "TrustedIssuerCertificateExpired";
|
|
106
|
+
MobileCredentialVerificationReasonType["TrustedIssuerCertificateNotYetValid"] = "TrustedIssuerCertificateNotYetValid";
|
|
107
|
+
MobileCredentialVerificationReasonType["IssuerNotTrusted"] = "IssuerNotTrusted";
|
|
108
|
+
MobileCredentialVerificationReasonType["MobileCredentialInvalid"] = "MobileCredentialInvalid";
|
|
109
|
+
MobileCredentialVerificationReasonType["MobileCredentialExpired"] = "MobileCredentialExpired";
|
|
110
|
+
MobileCredentialVerificationReasonType["MobileCredentialNotYetValid"] = "MobileCredentialNotYetValid";
|
|
111
|
+
MobileCredentialVerificationReasonType["InvalidSignerCertificate"] = "InvalidSignerCertificate";
|
|
112
|
+
MobileCredentialVerificationReasonType["DeviceKeyInvalid"] = "DeviceKeyInvalid";
|
|
113
|
+
MobileCredentialVerificationReasonType["UnsupportedCurve"] = "UnsupportedCurve";
|
|
114
|
+
MobileCredentialVerificationReasonType["StatusRevoked"] = "StatusRevoked";
|
|
115
|
+
MobileCredentialVerificationReasonType["StatusSuspended"] = "StatusSuspended";
|
|
116
|
+
MobileCredentialVerificationReasonType["StatusUnknown"] = "StatusUnknown";
|
|
133
117
|
})(exports.MobileCredentialVerificationReasonType || (exports.MobileCredentialVerificationReasonType = {}));
|
|
134
118
|
|
|
135
119
|
exports.ClaimType = void 0;
|
|
@@ -164,6 +148,15 @@ exports.OpenidPresentationCredentialProfileSupported = void 0;
|
|
|
164
148
|
OpenidPresentationCredentialProfileSupported["MOBILE"] = "mobile";
|
|
165
149
|
})(exports.OpenidPresentationCredentialProfileSupported || (exports.OpenidPresentationCredentialProfileSupported = {}));
|
|
166
150
|
|
|
151
|
+
var PresentationStatusCode;
|
|
152
|
+
|
|
153
|
+
(function(PresentationStatusCode) {
|
|
154
|
+
PresentationStatusCode["AwaitingRequestRetrieval"] = "AwaitingRequestRetrieval";
|
|
155
|
+
PresentationStatusCode["AwaitingResponse"] = "AwaitingResponse";
|
|
156
|
+
PresentationStatusCode["ResponseSubmitted"] = "ResponseSubmitted";
|
|
157
|
+
PresentationStatusCode["ResultReady"] = "ResultReady";
|
|
158
|
+
})(PresentationStatusCode || (PresentationStatusCode = {}));
|
|
159
|
+
|
|
167
160
|
const CredentialQueryValidator = v__namespace.object({
|
|
168
161
|
profile: v__namespace.picklist([ exports.OpenidPresentationCredentialProfileSupported.MOBILE ]),
|
|
169
162
|
docType: v__namespace.string(),
|
|
@@ -191,23 +184,63 @@ const PresentationResultRelaxValidator = v__namespace.object({
|
|
|
191
184
|
error: v__namespace.optional(v__namespace.unknown())
|
|
192
185
|
});
|
|
193
186
|
|
|
187
|
+
exports.Mode = void 0;
|
|
188
|
+
|
|
189
|
+
(function(Mode) {
|
|
190
|
+
Mode["SameDevice"] = "sameDevice";
|
|
191
|
+
Mode["CrossDevice"] = "crossDevice";
|
|
192
|
+
})(exports.Mode || (exports.Mode = {}));
|
|
193
|
+
|
|
194
|
+
var SessionType;
|
|
195
|
+
|
|
196
|
+
(function(SessionType) {
|
|
197
|
+
SessionType["DigitalCredentialsApi"] = "digital-credentials-api";
|
|
198
|
+
SessionType["Openid4vp"] = "openid4vp";
|
|
199
|
+
})(SessionType || (SessionType = {}));
|
|
200
|
+
|
|
194
201
|
v__namespace.object({
|
|
195
202
|
credentialQuery: v__namespace.array(CredentialQueryValidator),
|
|
196
203
|
challenge: v__namespace.string(),
|
|
197
204
|
redirectUri: v__namespace.optional(v__namespace.string()),
|
|
198
|
-
walletProviderId: v__namespace.optional(v__namespace.string())
|
|
205
|
+
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
206
|
+
dcApiSupported: v__namespace.optional(v__namespace.boolean())
|
|
199
207
|
});
|
|
200
208
|
|
|
201
|
-
const
|
|
209
|
+
const CreateSessionDigitalCredentialsValidator = v__namespace.object({
|
|
210
|
+
type: v__namespace.literal(SessionType.DigitalCredentialsApi),
|
|
202
211
|
sessionId: v__namespace.string(),
|
|
212
|
+
sessionKey: v__namespace.string(),
|
|
213
|
+
sessionTtl: v__namespace.number(),
|
|
214
|
+
request: v__namespace.record(v__namespace.string(), v__namespace.any())
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const CreateSessionOpenId4vpResponseValidator = v__namespace.object({
|
|
218
|
+
type: v__namespace.optional(v__namespace.literal(SessionType.Openid4vp)),
|
|
219
|
+
sessionId: v__namespace.string(),
|
|
220
|
+
sessionKey: v__namespace.string(),
|
|
203
221
|
sessionUrl: v__namespace.string()
|
|
204
222
|
});
|
|
205
223
|
|
|
206
|
-
const
|
|
224
|
+
const CreateSessionResponseValidator = v__namespace.union([ CreateSessionDigitalCredentialsValidator, CreateSessionOpenId4vpResponseValidator ]);
|
|
225
|
+
|
|
226
|
+
v__namespace.object({
|
|
227
|
+
sessionId: v__namespace.string(),
|
|
228
|
+
sessionKey: v__namespace.string(),
|
|
229
|
+
apiBaseUrl: v__namespace.string()
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
v__namespace.object({
|
|
207
233
|
sessionId: v__namespace.string(),
|
|
208
|
-
|
|
234
|
+
sessionKey: v__namespace.string()
|
|
209
235
|
});
|
|
210
236
|
|
|
237
|
+
const GetSessionStatusResponseValidator = v__namespace.union([ v__namespace.object({
|
|
238
|
+
status: v__namespace.picklist([ PresentationStatusCode.ResultReady ]),
|
|
239
|
+
responseCode: v__namespace.optional(v__namespace.string())
|
|
240
|
+
}), v__namespace.object({
|
|
241
|
+
status: v__namespace.string()
|
|
242
|
+
}) ]);
|
|
243
|
+
|
|
211
244
|
var LocalStorageKey;
|
|
212
245
|
|
|
213
246
|
(function(LocalStorageKey) {
|
|
@@ -215,12 +248,9 @@ var LocalStorageKey;
|
|
|
215
248
|
LocalStorageKey["sessionId"] = "mattr_sid";
|
|
216
249
|
})(LocalStorageKey || (LocalStorageKey = {}));
|
|
217
250
|
|
|
218
|
-
|
|
251
|
+
const MATTR_SDK_VERSION_HEADER = "x-mattr-sdk-version";
|
|
219
252
|
|
|
220
|
-
|
|
221
|
-
Mode["sameDevice"] = "sameDevice";
|
|
222
|
-
Mode["crossDevice"] = "crossDevice";
|
|
223
|
-
})(exports.Mode || (exports.Mode = {}));
|
|
253
|
+
const MATTR_SDK_VERSION_VALUE = "2.0.0";
|
|
224
254
|
|
|
225
255
|
var MessageEventDataType;
|
|
226
256
|
|
|
@@ -230,71 +260,210 @@ var MessageEventDataType;
|
|
|
230
260
|
MessageEventDataType["PresentationAbort"] = "PresentationAbort";
|
|
231
261
|
})(MessageEventDataType || (MessageEventDataType = {}));
|
|
232
262
|
|
|
233
|
-
const
|
|
234
|
-
credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
|
|
235
|
-
redirectUri: v__namespace.string(),
|
|
236
|
-
challenge: v__namespace.optional(v__namespace.string()),
|
|
263
|
+
const OpenId4vpConfigSameDeviceOptionsValidator = v__namespace.object({
|
|
237
264
|
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
238
|
-
mode: v__namespace.
|
|
265
|
+
mode: v__namespace.literal(exports.Mode.SameDevice),
|
|
266
|
+
redirectUri: v__namespace.pipe(v__namespace.string(), v__namespace.nonEmpty("Must not be empty"), v__namespace.url())
|
|
239
267
|
});
|
|
240
268
|
|
|
241
|
-
const
|
|
242
|
-
credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
|
|
243
|
-
crossDeviceCallback: v__namespace.object({
|
|
244
|
-
onComplete: v__namespace.function(),
|
|
245
|
-
onFailure: v__namespace.function()
|
|
246
|
-
}),
|
|
247
|
-
challenge: v__namespace.optional(v__namespace.string()),
|
|
269
|
+
const OpenId4vpConfigCrossDeviceOptionsValidator = v__namespace.object({
|
|
248
270
|
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
249
|
-
mode: v__namespace.
|
|
271
|
+
mode: v__namespace.literal(exports.Mode.CrossDevice)
|
|
250
272
|
});
|
|
251
273
|
|
|
252
|
-
const
|
|
253
|
-
credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
|
|
254
|
-
crossDeviceCallback: v__namespace.object({
|
|
255
|
-
onComplete: v__namespace.function(),
|
|
256
|
-
onFailure: v__namespace.function()
|
|
257
|
-
}),
|
|
258
|
-
redirectUri: v__namespace.string(),
|
|
259
|
-
challenge: v__namespace.optional(v__namespace.string()),
|
|
274
|
+
const OpenId4vpConfigAutoDetectOptionsValidator = v__namespace.object({
|
|
260
275
|
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
261
|
-
|
|
276
|
+
redirectUri: v__namespace.pipe(v__namespace.string(), v__namespace.nonEmpty("Must not be empty"), v__namespace.url()),
|
|
277
|
+
mode: v__namespace.optional(v__namespace.picklist([ exports.Mode.CrossDevice, exports.Mode.SameDevice ]))
|
|
262
278
|
});
|
|
263
279
|
|
|
264
|
-
const RequestCredentialsOptionsValidator = v__namespace.
|
|
280
|
+
const RequestCredentialsOptionsValidator = v__namespace.object({
|
|
281
|
+
credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
|
|
282
|
+
challenge: v__namespace.optional(v__namespace.string()),
|
|
283
|
+
openid4vpConfiguration: v__namespace.optional(v__namespace.union([ OpenId4vpConfigSameDeviceOptionsValidator, OpenId4vpConfigCrossDeviceOptionsValidator, OpenId4vpConfigAutoDetectOptionsValidator ]))
|
|
284
|
+
});
|
|
265
285
|
|
|
266
286
|
exports.RequestCredentialsErrorType = void 0;
|
|
267
287
|
|
|
268
288
|
(function(RequestCredentialsErrorType) {
|
|
269
289
|
RequestCredentialsErrorType["RequestCredentialsFailed"] = "RequestCredentialsFailed";
|
|
290
|
+
RequestCredentialsErrorType["Timeout"] = "Timeout";
|
|
291
|
+
RequestCredentialsErrorType["Abort"] = "Abort";
|
|
270
292
|
})(exports.RequestCredentialsErrorType || (exports.RequestCredentialsErrorType = {}));
|
|
271
293
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
294
|
+
var RequestCredentialsErrorMessage;
|
|
295
|
+
|
|
296
|
+
(function(RequestCredentialsErrorMessage) {
|
|
297
|
+
RequestCredentialsErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
|
|
298
|
+
RequestCredentialsErrorMessage["FailedToGetSessionStatus"] = "Failed to get session status";
|
|
299
|
+
RequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
|
|
300
|
+
RequestCredentialsErrorMessage["FailedToVerifyCredentialResponse"] = "Failed to verify credential response";
|
|
301
|
+
RequestCredentialsErrorMessage["MissingOpenId4vpConfig"] = "Identified openid4vp session, but missing openId4vpConfiguration on `requestCredentials`";
|
|
302
|
+
RequestCredentialsErrorMessage["DcApiError"] = "Failed to request credentials with Digital Credentials API";
|
|
303
|
+
RequestCredentialsErrorMessage["DcApiResponseParseError"] = "Failed to parse response from Digital Credentials API";
|
|
304
|
+
RequestCredentialsErrorMessage["Abort"] = "User aborted the session";
|
|
305
|
+
RequestCredentialsErrorMessage["Timeout"] = "User session timeout";
|
|
306
|
+
})(RequestCredentialsErrorMessage || (RequestCredentialsErrorMessage = {}));
|
|
307
|
+
|
|
308
|
+
exports.AbortSessionErrorType = void 0;
|
|
309
|
+
|
|
310
|
+
(function(AbortSessionErrorType) {
|
|
311
|
+
AbortSessionErrorType["AbortSessionFailed"] = "AbortSessionFailed";
|
|
312
|
+
})(exports.AbortSessionErrorType || (exports.AbortSessionErrorType = {}));
|
|
313
|
+
|
|
314
|
+
var AbortSessionErrorMessage;
|
|
315
|
+
|
|
316
|
+
(function(AbortSessionErrorMessage) {
|
|
317
|
+
AbortSessionErrorMessage["FailedToAbortSession"] = "Failed to abort session";
|
|
318
|
+
})(AbortSessionErrorMessage || (AbortSessionErrorMessage = {}));
|
|
319
|
+
|
|
320
|
+
const InitializeOptionsValidator = v__namespace.object({
|
|
321
|
+
apiBaseUrl: v__namespace.pipe(v__namespace.string(), v__namespace.nonEmpty("Must not be empty"), v__namespace.url()),
|
|
322
|
+
applicationId: v__namespace.pipe(v__namespace.string(), v__namespace.nonEmpty("Must not be empty"))
|
|
277
323
|
});
|
|
278
324
|
|
|
279
|
-
|
|
325
|
+
var SafeFetchCommonResponseErrorType;
|
|
326
|
+
|
|
327
|
+
(function(SafeFetchCommonResponseErrorType) {
|
|
328
|
+
SafeFetchCommonResponseErrorType["UnexpectedResponse"] = "UnexpectedResponse";
|
|
329
|
+
})(SafeFetchCommonResponseErrorType || (SafeFetchCommonResponseErrorType = {}));
|
|
330
|
+
|
|
331
|
+
var SafeFetchErrorType;
|
|
332
|
+
|
|
333
|
+
(function(SafeFetchErrorType) {
|
|
334
|
+
SafeFetchErrorType["HttpError"] = "HttpError";
|
|
335
|
+
SafeFetchErrorType["UnknownError"] = "UnknownError";
|
|
336
|
+
})(SafeFetchErrorType || (SafeFetchErrorType = {}));
|
|
337
|
+
|
|
338
|
+
const safeFetch = async (input, init) => {
|
|
339
|
+
try {
|
|
340
|
+
const headers = Object.assign(Object.assign({}, init === null || init === void 0 ? void 0 : init.headers), {
|
|
341
|
+
[MATTR_SDK_VERSION_HEADER]: `verifier-sdk-web/${MATTR_SDK_VERSION_VALUE}`
|
|
342
|
+
});
|
|
343
|
+
const response = await fetch(input, Object.assign(Object.assign({}, init), {
|
|
344
|
+
headers: headers
|
|
345
|
+
}));
|
|
346
|
+
const defaultHttpErrorMessage = `HTTP error, status = ${response.status}`;
|
|
347
|
+
if (response.status >= 400 && response.status < 500) {
|
|
348
|
+
try {
|
|
349
|
+
const errorBody = await response.json();
|
|
350
|
+
if (typeof (errorBody === null || errorBody === void 0 ? void 0 : errorBody.message) === "string") {
|
|
351
|
+
return neverthrow.err({
|
|
352
|
+
type: SafeFetchErrorType.HttpError,
|
|
353
|
+
message: errorBody.message,
|
|
354
|
+
status: response.status
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
} catch (_a) {
|
|
358
|
+
return neverthrow.err({
|
|
359
|
+
type: SafeFetchErrorType.HttpError,
|
|
360
|
+
message: defaultHttpErrorMessage,
|
|
361
|
+
status: response.status
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (response.status > 299 || response.status < 200) {
|
|
366
|
+
return neverthrow.err({
|
|
367
|
+
type: SafeFetchErrorType.HttpError,
|
|
368
|
+
message: defaultHttpErrorMessage,
|
|
369
|
+
status: response.status
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
return neverthrow.ok(response);
|
|
373
|
+
} catch (error) {
|
|
374
|
+
return neverthrow.err({
|
|
375
|
+
type: SafeFetchErrorType.UnknownError,
|
|
376
|
+
message: "Unknown error",
|
|
377
|
+
cause: error
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
let initializeOptions = undefined;
|
|
383
|
+
|
|
384
|
+
var InitializeErrorMessage;
|
|
385
|
+
|
|
386
|
+
(function(InitializeErrorMessage) {
|
|
387
|
+
InitializeErrorMessage["SdkNotInitialized"] = "SDK not initialized";
|
|
388
|
+
})(InitializeErrorMessage || (InitializeErrorMessage = {}));
|
|
389
|
+
|
|
390
|
+
const initialize = options => {
|
|
391
|
+
assertType(InitializeOptionsValidator, "Invalid initialize options")(options);
|
|
392
|
+
const {apiBaseUrl: apiBaseUrl} = options;
|
|
393
|
+
const trimmedApiBaseUrl = apiBaseUrl.trim();
|
|
394
|
+
initializeOptions = {
|
|
395
|
+
apiBaseUrl: trimmedApiBaseUrl,
|
|
396
|
+
applicationId: options.applicationId
|
|
397
|
+
};
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
const getInitializeOptions = () => initializeOptions;
|
|
401
|
+
|
|
402
|
+
let sessionAbortController = undefined;
|
|
403
|
+
|
|
404
|
+
let _sessionId = undefined;
|
|
405
|
+
|
|
406
|
+
let _sessionKey = undefined;
|
|
280
407
|
|
|
281
|
-
|
|
408
|
+
let _sessionTimeoutId = undefined;
|
|
282
409
|
|
|
283
|
-
(
|
|
284
|
-
|
|
285
|
-
|
|
410
|
+
const getActiveSession = () => {
|
|
411
|
+
const sessionId = _sessionId;
|
|
412
|
+
const sessionKey = _sessionKey;
|
|
413
|
+
const sessionTimeoutId = _sessionTimeoutId;
|
|
414
|
+
if (sessionId) {
|
|
415
|
+
return {
|
|
416
|
+
sessionId: sessionId,
|
|
417
|
+
sessionKey: sessionKey,
|
|
418
|
+
sessionTimeoutId: sessionTimeoutId
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
return undefined;
|
|
422
|
+
};
|
|
286
423
|
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
424
|
+
const setActiveSession = session => {
|
|
425
|
+
const {sessionId: sessionId, sessionKey: sessionKey, sessionTimeoutId: sessionTimeoutId} = session;
|
|
426
|
+
_sessionId = sessionId;
|
|
427
|
+
_sessionKey = sessionKey;
|
|
428
|
+
_sessionTimeoutId = sessionTimeoutId;
|
|
429
|
+
const abortController = new AbortController;
|
|
430
|
+
sessionAbortController = abortController;
|
|
431
|
+
return abortController;
|
|
290
432
|
};
|
|
291
433
|
|
|
292
|
-
const
|
|
434
|
+
const removeActiveSession = () => {
|
|
435
|
+
sessionAbortController === null || sessionAbortController === void 0 ? void 0 : sessionAbortController.abort();
|
|
436
|
+
if (_sessionTimeoutId) {
|
|
437
|
+
window.clearTimeout(_sessionTimeoutId);
|
|
438
|
+
}
|
|
439
|
+
sessionAbortController = undefined;
|
|
440
|
+
_sessionKey = undefined;
|
|
441
|
+
_sessionId = undefined;
|
|
442
|
+
_sessionTimeoutId = undefined;
|
|
443
|
+
};
|
|
293
444
|
|
|
294
445
|
const defaultRetryDelay = attempt => Math.pow(2, attempt) * 1e3;
|
|
295
446
|
|
|
296
447
|
const defaultRetry = 2;
|
|
297
448
|
|
|
449
|
+
const withRetry = async (fn, options) => {
|
|
450
|
+
const {retries: retries = defaultRetry, retryDelay: retryDelay = defaultRetryDelay, attempt: attempt = 0} = options;
|
|
451
|
+
try {
|
|
452
|
+
return await fn();
|
|
453
|
+
} catch (err) {
|
|
454
|
+
if (retries > 0) {
|
|
455
|
+
const delay = typeof retryDelay === "function" ? retryDelay(attempt) : retryDelay;
|
|
456
|
+
await new Promise((resolve => setTimeout(resolve, delay)));
|
|
457
|
+
return await withRetry(fn, Object.assign(Object.assign({}, options), {
|
|
458
|
+
retries: retries - 1,
|
|
459
|
+
retryDelay: retryDelay,
|
|
460
|
+
attempt: attempt + 1
|
|
461
|
+
}));
|
|
462
|
+
}
|
|
463
|
+
throw err;
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
|
|
298
467
|
const withRetrySafeFetch = async (fn, options) => {
|
|
299
468
|
const {retries: retries = defaultRetry, retryDelay: retryDelay = defaultRetryDelay, attempt: attempt = 0, retryHttpStatus: retryHttpStatus} = options;
|
|
300
469
|
const result = await fn();
|
|
@@ -323,17 +492,15 @@ const getHashParamValue = (hash, param) => {
|
|
|
323
492
|
return urlParams.get(param);
|
|
324
493
|
};
|
|
325
494
|
|
|
326
|
-
const createSession = async ({credentialQuery: credentialQuery, challenge: challenge, redirectUri: redirectUri, apiBaseUrl: apiBaseUrl,
|
|
327
|
-
const postData =
|
|
495
|
+
const createSession = async ({credentialQuery: credentialQuery, challenge: challenge, redirectUri: redirectUri, apiBaseUrl: apiBaseUrl, walletProviderId: walletProviderId, dcApiSupported: dcApiSupported, applicationId: applicationId}) => {
|
|
496
|
+
const postData = {
|
|
328
497
|
credentialQuery: credentialQuery,
|
|
329
|
-
challenge: challenge
|
|
330
|
-
|
|
331
|
-
redirectUri: redirectUri
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
walletProviderId: walletProviderId
|
|
336
|
-
} : {});
|
|
498
|
+
challenge: challenge,
|
|
499
|
+
applicationId: applicationId,
|
|
500
|
+
redirectUri: redirectUri,
|
|
501
|
+
walletProviderId: walletProviderId,
|
|
502
|
+
dcApiSupported: dcApiSupported
|
|
503
|
+
};
|
|
337
504
|
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions`, {
|
|
338
505
|
method: "POST",
|
|
339
506
|
headers: {
|
|
@@ -347,94 +514,53 @@ const createSession = async ({credentialQuery: credentialQuery, challenge: chall
|
|
|
347
514
|
const data = await responseResult.value.json();
|
|
348
515
|
if (!isType(CreateSessionResponseValidator)(data)) {
|
|
349
516
|
return neverthrow.err({
|
|
350
|
-
type:
|
|
351
|
-
message: "Create session
|
|
517
|
+
type: SafeFetchCommonResponseErrorType.UnexpectedResponse,
|
|
518
|
+
message: "Create session returned unsupported response"
|
|
352
519
|
});
|
|
353
520
|
}
|
|
354
521
|
return neverthrow.ok(data);
|
|
355
522
|
};
|
|
356
523
|
|
|
357
|
-
const
|
|
358
|
-
const
|
|
359
|
-
challenge: challenge,
|
|
360
|
-
responseCode: responseCode
|
|
361
|
-
};
|
|
362
|
-
const fetchResultFn = async () => await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/result`, {
|
|
524
|
+
const abortSession = async ({apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey}) => {
|
|
525
|
+
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/abort`, {
|
|
363
526
|
method: "POST",
|
|
364
527
|
headers: {
|
|
365
|
-
"Content-Type": "application/json"
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
});
|
|
369
|
-
const responseResult = await withRetrySafeFetch(fetchResultFn, {
|
|
370
|
-
retries: 2,
|
|
371
|
-
retryHttpStatus: 404
|
|
528
|
+
"Content-Type": "application/json",
|
|
529
|
+
Authorization: `Bearer ${sessionKey}`
|
|
530
|
+
}
|
|
372
531
|
});
|
|
373
532
|
if (responseResult.isErr()) {
|
|
374
533
|
return neverthrow.err(responseResult.error);
|
|
375
534
|
}
|
|
376
|
-
|
|
377
|
-
if (!isType(PresentationResultRelaxValidator)(data)) {
|
|
378
|
-
return neverthrow.err({
|
|
379
|
-
type: SafeFetchCommonRespondErrorType.UnexpectedRespond,
|
|
380
|
-
message: "Exchange session result return unsupported response",
|
|
381
|
-
details: {
|
|
382
|
-
data: data
|
|
383
|
-
}
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
return neverthrow.ok(data);
|
|
535
|
+
return neverthrow.ok(undefined);
|
|
387
536
|
};
|
|
388
537
|
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
const isDigitalCredentialsApiSupported = () => {
|
|
395
|
-
var _a;
|
|
396
|
-
try {
|
|
397
|
-
return typeof ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.identity) === null || _a === void 0 ? void 0 : _a.get) === "function";
|
|
398
|
-
} catch (error) {
|
|
399
|
-
return false;
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
const createDigitalCredentialsApiSession = async ({credentialQuery: credentialQuery, challenge: challenge, apiBaseUrl: apiBaseUrl, protocol: protocol}) => {
|
|
404
|
-
const postData = Object.assign({
|
|
405
|
-
credentialQuery: credentialQuery,
|
|
406
|
-
challenge: challenge
|
|
407
|
-
}, protocol && {
|
|
408
|
-
protocol: protocol
|
|
409
|
-
});
|
|
410
|
-
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/web/request`, {
|
|
411
|
-
method: "POST",
|
|
538
|
+
const getSessionStatus = async ({apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey}) => {
|
|
539
|
+
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/status`, {
|
|
540
|
+
method: "GET",
|
|
412
541
|
headers: {
|
|
413
|
-
|
|
414
|
-
}
|
|
415
|
-
body: JSON.stringify(postData)
|
|
542
|
+
Authorization: `Bearer ${sessionKey}`
|
|
543
|
+
}
|
|
416
544
|
});
|
|
417
545
|
if (responseResult.isErr()) {
|
|
418
546
|
return neverthrow.err(responseResult.error);
|
|
419
547
|
}
|
|
420
548
|
const data = await responseResult.value.json();
|
|
421
|
-
if (!isType(
|
|
549
|
+
if (!isType(GetSessionStatusResponseValidator)(data)) {
|
|
422
550
|
return neverthrow.err({
|
|
423
|
-
type:
|
|
424
|
-
message: "
|
|
551
|
+
type: SafeFetchCommonResponseErrorType.UnexpectedResponse,
|
|
552
|
+
message: "Get session status return unsupported response"
|
|
425
553
|
});
|
|
426
554
|
}
|
|
427
555
|
return neverthrow.ok(data);
|
|
428
556
|
};
|
|
429
557
|
|
|
430
|
-
const
|
|
558
|
+
const exchangeSessionResult = async ({challenge: challenge, responseCode: responseCode, sessionId: sessionId, apiBaseUrl: apiBaseUrl}) => {
|
|
431
559
|
const postData = {
|
|
432
560
|
challenge: challenge,
|
|
433
|
-
|
|
434
|
-
response: response,
|
|
435
|
-
protocol: protocol
|
|
561
|
+
responseCode: responseCode
|
|
436
562
|
};
|
|
437
|
-
const fetchResultFn = async () => await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/
|
|
563
|
+
const fetchResultFn = async () => await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/result`, {
|
|
438
564
|
method: "POST",
|
|
439
565
|
headers: {
|
|
440
566
|
"Content-Type": "application/json"
|
|
@@ -449,25 +575,24 @@ const getDigitalCredentialsApiSessionResult = async ({challenge: challenge, sess
|
|
|
449
575
|
return neverthrow.err(responseResult.error);
|
|
450
576
|
}
|
|
451
577
|
const data = await responseResult.value.json();
|
|
578
|
+
if (!isType(PresentationResultRelaxValidator)(data)) {
|
|
579
|
+
return neverthrow.err({
|
|
580
|
+
type: SafeFetchCommonResponseErrorType.UnexpectedResponse,
|
|
581
|
+
message: "Exchange session result return unsupported response",
|
|
582
|
+
details: {
|
|
583
|
+
data: data
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
452
587
|
return neverthrow.ok(data);
|
|
453
588
|
};
|
|
454
589
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
CrossDeviceCallbackErrorType["Abort"] = "Abort";
|
|
460
|
-
CrossDeviceCallbackErrorType["RequestCredentialsFailed"] = "RequestCredentialsFailed";
|
|
461
|
-
})(exports.CrossDeviceCallbackErrorType || (exports.CrossDeviceCallbackErrorType = {}));
|
|
462
|
-
|
|
463
|
-
var CrossDeviceRequestCredentialsErrorMessage;
|
|
590
|
+
const isMobileDetect = userAgent => isMobile.isMobile({
|
|
591
|
+
ua: userAgent,
|
|
592
|
+
tablet: false
|
|
593
|
+
});
|
|
464
594
|
|
|
465
|
-
(
|
|
466
|
-
CrossDeviceRequestCredentialsErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
|
|
467
|
-
CrossDeviceRequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
|
|
468
|
-
CrossDeviceRequestCredentialsErrorMessage["Abort"] = "User aborted the session";
|
|
469
|
-
CrossDeviceRequestCredentialsErrorMessage["Timeout"] = "User session timeout";
|
|
470
|
-
})(CrossDeviceRequestCredentialsErrorMessage || (CrossDeviceRequestCredentialsErrorMessage = {}));
|
|
595
|
+
const getVersion = () => MATTR_SDK_VERSION_VALUE;
|
|
471
596
|
|
|
472
597
|
var WindowEventListenerType;
|
|
473
598
|
|
|
@@ -475,10 +600,13 @@ var WindowEventListenerType;
|
|
|
475
600
|
WindowEventListenerType["message"] = "message";
|
|
476
601
|
})(WindowEventListenerType || (WindowEventListenerType = {}));
|
|
477
602
|
|
|
478
|
-
let listener;
|
|
603
|
+
let listener = undefined;
|
|
479
604
|
|
|
480
605
|
const removeWindowMessageEventListener = () => {
|
|
481
|
-
|
|
606
|
+
if (listener) {
|
|
607
|
+
window.removeEventListener(WindowEventListenerType.message, listener, false);
|
|
608
|
+
}
|
|
609
|
+
listener = undefined;
|
|
482
610
|
};
|
|
483
611
|
|
|
484
612
|
const closeCrossDeviceModal = options => {
|
|
@@ -490,8 +618,7 @@ const closeCrossDeviceModal = options => {
|
|
|
490
618
|
};
|
|
491
619
|
|
|
492
620
|
const receiveMessageHandler = options => async event => {
|
|
493
|
-
const {
|
|
494
|
-
const {onComplete: onComplete, onFailure: onFailure} = crossDeviceCallback;
|
|
621
|
+
const {onComplete: onComplete, onFailure: onFailure, container: container, sessionId: sessionId, apiBaseUrl: apiBaseUrl, challenge: challenge} = options;
|
|
495
622
|
if (event.origin !== apiBaseUrl) {
|
|
496
623
|
return;
|
|
497
624
|
}
|
|
@@ -505,8 +632,8 @@ const receiveMessageHandler = options => async event => {
|
|
|
505
632
|
});
|
|
506
633
|
if (result.isErr()) {
|
|
507
634
|
onFailure({
|
|
508
|
-
type: exports.
|
|
509
|
-
message:
|
|
635
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
636
|
+
message: RequestCredentialsErrorMessage.FailedToGetSessionResult
|
|
510
637
|
});
|
|
511
638
|
closeCrossDeviceModal({
|
|
512
639
|
container: container
|
|
@@ -514,8 +641,9 @@ const receiveMessageHandler = options => async event => {
|
|
|
514
641
|
return;
|
|
515
642
|
}
|
|
516
643
|
onComplete({
|
|
517
|
-
result: result.value,
|
|
518
|
-
sessionId: result.value.sessionId
|
|
644
|
+
result: "challenge" in result.value ? result.value : undefined,
|
|
645
|
+
sessionId: result.value.sessionId,
|
|
646
|
+
sessionCompletedInRedirect: false
|
|
519
647
|
});
|
|
520
648
|
closeCrossDeviceModal({
|
|
521
649
|
container: container
|
|
@@ -524,8 +652,8 @@ const receiveMessageHandler = options => async event => {
|
|
|
524
652
|
}
|
|
525
653
|
if (event.data.type === MessageEventDataType.PresentationTimeout) {
|
|
526
654
|
onFailure({
|
|
527
|
-
type: exports.
|
|
528
|
-
message:
|
|
655
|
+
type: exports.RequestCredentialsErrorType.Timeout,
|
|
656
|
+
message: RequestCredentialsErrorMessage.Timeout
|
|
529
657
|
});
|
|
530
658
|
closeCrossDeviceModal({
|
|
531
659
|
container: container
|
|
@@ -534,8 +662,8 @@ const receiveMessageHandler = options => async event => {
|
|
|
534
662
|
}
|
|
535
663
|
if (event.data.type === MessageEventDataType.PresentationAbort) {
|
|
536
664
|
onFailure({
|
|
537
|
-
type: exports.
|
|
538
|
-
message:
|
|
665
|
+
type: exports.RequestCredentialsErrorType.Abort,
|
|
666
|
+
message: RequestCredentialsErrorMessage.Abort
|
|
539
667
|
});
|
|
540
668
|
closeCrossDeviceModal({
|
|
541
669
|
container: container
|
|
@@ -560,82 +688,202 @@ const openCrossDeviceModal = options => {
|
|
|
560
688
|
return modalContainer;
|
|
561
689
|
};
|
|
562
690
|
|
|
563
|
-
const
|
|
564
|
-
const {challenge: challenge,
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
691
|
+
const requestCredentialsWithCrossDevice = async options => {
|
|
692
|
+
const {challenge: challenge, apiBaseUrl: apiBaseUrl, sessionUrl: sessionUrl, sessionId: sessionId, sessionKey: sessionKey} = options;
|
|
693
|
+
const container = openCrossDeviceModal({
|
|
694
|
+
sessionUrl: sessionUrl
|
|
695
|
+
});
|
|
696
|
+
return await new Promise((resolve => {
|
|
697
|
+
const abortController = setActiveSession({
|
|
698
|
+
sessionId: sessionId,
|
|
699
|
+
sessionKey: sessionKey
|
|
700
|
+
});
|
|
701
|
+
abortController.signal.addEventListener("abort", (() => {
|
|
702
|
+
closeCrossDeviceModal({
|
|
703
|
+
container: container
|
|
704
|
+
});
|
|
705
|
+
resolve(neverthrow.err({
|
|
706
|
+
type: exports.RequestCredentialsErrorType.Abort,
|
|
707
|
+
message: RequestCredentialsErrorMessage.Abort
|
|
708
|
+
}));
|
|
709
|
+
}));
|
|
710
|
+
removeWindowMessageEventListener();
|
|
711
|
+
listener = receiveMessageHandler({
|
|
712
|
+
container: container,
|
|
713
|
+
sessionId: sessionId,
|
|
714
|
+
apiBaseUrl: apiBaseUrl,
|
|
715
|
+
challenge: challenge,
|
|
716
|
+
onComplete: data => resolve(neverthrow.ok(data)),
|
|
717
|
+
onFailure: error => resolve(neverthrow.err(error))
|
|
718
|
+
});
|
|
719
|
+
window.addEventListener(WindowEventListenerType.message, listener, false);
|
|
720
|
+
}));
|
|
721
|
+
};
|
|
722
|
+
|
|
723
|
+
const abortCredentialRequest = async () => {
|
|
724
|
+
const initializeOptions = getInitializeOptions();
|
|
725
|
+
if (!initializeOptions) {
|
|
726
|
+
throw new Exception(InitializeErrorMessage.SdkNotInitialized);
|
|
727
|
+
}
|
|
728
|
+
const {apiBaseUrl: apiBaseUrl} = initializeOptions;
|
|
729
|
+
const session = getActiveSession();
|
|
730
|
+
if (!session || !session.sessionKey) {
|
|
731
|
+
return neverthrow.ok(undefined);
|
|
732
|
+
}
|
|
733
|
+
const {sessionId: sessionId, sessionKey: sessionKey} = session;
|
|
734
|
+
removeActiveSession();
|
|
735
|
+
const abortSessionResult = await abortSession({
|
|
569
736
|
apiBaseUrl: apiBaseUrl,
|
|
570
|
-
|
|
571
|
-
|
|
737
|
+
sessionId: sessionId,
|
|
738
|
+
sessionKey: sessionKey
|
|
572
739
|
});
|
|
573
|
-
if (
|
|
740
|
+
if (abortSessionResult.isErr()) {
|
|
574
741
|
return neverthrow.err({
|
|
575
|
-
type: exports.
|
|
576
|
-
message:
|
|
577
|
-
cause:
|
|
742
|
+
type: exports.AbortSessionErrorType.AbortSessionFailed,
|
|
743
|
+
message: AbortSessionErrorMessage.FailedToAbortSession,
|
|
744
|
+
cause: abortSessionResult.error
|
|
578
745
|
});
|
|
579
746
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
container: container,
|
|
747
|
+
return neverthrow.ok(undefined);
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
const requestCredentialsWithDigitalCredentialsApi = async options => {
|
|
751
|
+
const {apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey, challenge: challenge, request: request, sessionTtl: sessionTtl} = options;
|
|
752
|
+
const sessionTimeoutId = window.setTimeout((() => removeActiveSession()), sessionTtl * 1e3);
|
|
753
|
+
const abortController = setActiveSession({
|
|
588
754
|
sessionId: sessionId,
|
|
755
|
+
sessionKey: sessionKey,
|
|
756
|
+
sessionTimeoutId: sessionTimeoutId
|
|
757
|
+
});
|
|
758
|
+
const credentialResponseResult = await getCredentials(request, abortController);
|
|
759
|
+
if (credentialResponseResult.isErr()) {
|
|
760
|
+
await abortCredentialRequest();
|
|
761
|
+
return neverthrow.err(credentialResponseResult.error);
|
|
762
|
+
}
|
|
763
|
+
const credentialResponse = credentialResponseResult.value;
|
|
764
|
+
const parsedCredentialResponseResult = parseCredentialResponse(credentialResponse);
|
|
765
|
+
if (parsedCredentialResponseResult.isErr()) {
|
|
766
|
+
await abortCredentialRequest();
|
|
767
|
+
return neverthrow.err(parsedCredentialResponseResult.error);
|
|
768
|
+
}
|
|
769
|
+
const parsedCredentialResponse = parsedCredentialResponseResult.value;
|
|
770
|
+
const credentialVerificationResult = await verifyCredentialResponse({
|
|
589
771
|
apiBaseUrl: apiBaseUrl,
|
|
590
|
-
|
|
772
|
+
sessionId: sessionId,
|
|
773
|
+
sessionKey: sessionKey,
|
|
774
|
+
challenge: challenge,
|
|
775
|
+
protocol: parsedCredentialResponse.protocol,
|
|
776
|
+
data: parsedCredentialResponse.data
|
|
591
777
|
});
|
|
592
|
-
|
|
778
|
+
if (credentialVerificationResult.isErr()) {
|
|
779
|
+
return neverthrow.err({
|
|
780
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
781
|
+
message: RequestCredentialsErrorMessage.FailedToVerifyCredentialResponse,
|
|
782
|
+
cause: credentialVerificationResult.error
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
const verificationResult = credentialVerificationResult.value;
|
|
593
786
|
return neverthrow.ok({
|
|
787
|
+
result: "challenge" in verificationResult ? verificationResult : undefined,
|
|
594
788
|
sessionId: sessionId
|
|
595
789
|
});
|
|
596
790
|
};
|
|
597
791
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
(
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const requestCredentialsSameDevice = async options => {
|
|
606
|
-
const {challenge: challenge, credentialQuery: credentialQuery, redirectUri: redirectUri, walletProviderId: walletProviderId, initialiseOptions: initialiseOptions} = options;
|
|
607
|
-
const {apiBaseUrl: apiBaseUrl, applicationId: applicationId} = initialiseOptions;
|
|
608
|
-
window.localStorage.setItem(LocalStorageKey.challenge, challenge);
|
|
609
|
-
const storedChallenge = window.localStorage.getItem(LocalStorageKey.challenge);
|
|
610
|
-
if (!storedChallenge) {
|
|
792
|
+
const getCredentials = async (request, abortController) => {
|
|
793
|
+
try {
|
|
794
|
+
const credentialResponse = await navigator.credentials.get(Object.assign(Object.assign({}, request), {
|
|
795
|
+
signal: abortController.signal
|
|
796
|
+
}));
|
|
797
|
+
return neverthrow.ok(credentialResponse);
|
|
798
|
+
} catch (exception) {
|
|
611
799
|
return neverthrow.err({
|
|
612
800
|
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
613
|
-
message:
|
|
801
|
+
message: RequestCredentialsErrorMessage.DcApiError,
|
|
802
|
+
cause: exception
|
|
614
803
|
});
|
|
615
804
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
apiBaseUrl: apiBaseUrl,
|
|
621
|
-
applicationId: applicationId,
|
|
622
|
-
walletProviderId: walletProviderId
|
|
623
|
-
});
|
|
624
|
-
if (createSessionResult.isErr()) {
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
const parseCredentialResponse = credentialResponse => {
|
|
808
|
+
if (!credentialResponse) {
|
|
625
809
|
return neverthrow.err({
|
|
626
810
|
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
627
|
-
message:
|
|
628
|
-
|
|
811
|
+
message: RequestCredentialsErrorMessage.DcApiResponseParseError,
|
|
812
|
+
details: {
|
|
813
|
+
response: credentialResponse
|
|
814
|
+
}
|
|
629
815
|
});
|
|
630
816
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
817
|
+
if (typeof credentialResponse === "object") {
|
|
818
|
+
return neverthrow.ok(credentialResponse);
|
|
819
|
+
}
|
|
820
|
+
if (typeof credentialResponse === "string") {
|
|
821
|
+
try {
|
|
822
|
+
const parsed = JSON.parse(credentialResponse);
|
|
823
|
+
return neverthrow.ok(parsed);
|
|
824
|
+
} catch (_a) {
|
|
825
|
+
return neverthrow.err({
|
|
826
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
827
|
+
message: RequestCredentialsErrorMessage.DcApiResponseParseError,
|
|
828
|
+
details: {
|
|
829
|
+
response: credentialResponse
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
return neverthrow.err({
|
|
835
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
836
|
+
message: RequestCredentialsErrorMessage.DcApiResponseParseError,
|
|
837
|
+
details: {
|
|
838
|
+
response: credentialResponse
|
|
839
|
+
}
|
|
636
840
|
});
|
|
637
841
|
};
|
|
638
842
|
|
|
843
|
+
const verifyCredentialResponse = async options => {
|
|
844
|
+
const {apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey, challenge: challenge, protocol: protocol, data: data} = options;
|
|
845
|
+
const requestBody = {
|
|
846
|
+
protocol: protocol,
|
|
847
|
+
data: data,
|
|
848
|
+
challenge: challenge
|
|
849
|
+
};
|
|
850
|
+
const credentialVerificationResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/dc-api/response`, {
|
|
851
|
+
method: "POST",
|
|
852
|
+
headers: {
|
|
853
|
+
"Content-Type": "application/json",
|
|
854
|
+
Authorization: `Bearer ${sessionKey}`
|
|
855
|
+
},
|
|
856
|
+
body: JSON.stringify(requestBody)
|
|
857
|
+
});
|
|
858
|
+
if (credentialVerificationResult.isErr()) {
|
|
859
|
+
return neverthrow.err(credentialVerificationResult.error);
|
|
860
|
+
}
|
|
861
|
+
const credentialVerificationResponse = await credentialVerificationResult.value.json();
|
|
862
|
+
if (!isType(PresentationResultRelaxValidator)(credentialVerificationResponse)) {
|
|
863
|
+
return neverthrow.err({
|
|
864
|
+
type: SafeFetchCommonResponseErrorType.UnexpectedResponse,
|
|
865
|
+
message: "Verify credential returned unsupported response",
|
|
866
|
+
details: {
|
|
867
|
+
response: credentialVerificationResponse
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
return neverthrow.ok(credentialVerificationResponse);
|
|
872
|
+
};
|
|
873
|
+
|
|
874
|
+
const isDigitalCredentialsApiSupported = () => {
|
|
875
|
+
var _a;
|
|
876
|
+
return "DigitalCredential" in window && typeof window.DigitalCredential === "function" && typeof ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.credentials) === null || _a === void 0 ? void 0 : _a.get) === "function";
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
const sleep = ms => new Promise((resolve => setTimeout(resolve, ms)));
|
|
880
|
+
|
|
881
|
+
const SESSION_STATUS_POLLING_MAX_RETRY = 1e3;
|
|
882
|
+
|
|
883
|
+
const SESSION_STATUS_POLLING_INTERVAL_MS = 3e3;
|
|
884
|
+
|
|
885
|
+
const SESSION_STATUS_POLLING_INITIAL_DELAY_MS = 3e3;
|
|
886
|
+
|
|
639
887
|
var SameDeviceRequestCredentialsErrorMessage;
|
|
640
888
|
|
|
641
889
|
(function(SameDeviceRequestCredentialsErrorMessage) {
|
|
@@ -643,110 +891,136 @@ var SameDeviceRequestCredentialsErrorMessage;
|
|
|
643
891
|
SameDeviceRequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
|
|
644
892
|
})(SameDeviceRequestCredentialsErrorMessage || (SameDeviceRequestCredentialsErrorMessage = {}));
|
|
645
893
|
|
|
646
|
-
const
|
|
647
|
-
const {challenge: challenge,
|
|
648
|
-
const
|
|
894
|
+
const requestCredentialsSameDevice = async options => {
|
|
895
|
+
const {challenge: challenge, apiBaseUrl: apiBaseUrl, applicationId: applicationId, sessionUrl: sessionUrl, sessionKey: sessionKey, sessionId: sessionId} = options;
|
|
896
|
+
const abortController = setActiveSession({
|
|
897
|
+
sessionId: sessionId,
|
|
898
|
+
sessionKey: sessionKey
|
|
899
|
+
});
|
|
900
|
+
window.localStorage.setItem(LocalStorageKey.sessionId, sessionId);
|
|
649
901
|
window.localStorage.setItem(LocalStorageKey.challenge, challenge);
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
902
|
+
window.location.assign(sessionUrl);
|
|
903
|
+
await sleep(SESSION_STATUS_POLLING_INITIAL_DELAY_MS);
|
|
904
|
+
const checkResult = await withRetry((async () => {
|
|
905
|
+
const statusResult = await getSessionStatus({
|
|
906
|
+
apiBaseUrl: apiBaseUrl,
|
|
907
|
+
applicationId: applicationId,
|
|
908
|
+
sessionId: sessionId,
|
|
909
|
+
sessionKey: sessionKey
|
|
655
910
|
});
|
|
911
|
+
if (abortController.signal.aborted) {
|
|
912
|
+
return neverthrow.err({
|
|
913
|
+
type: exports.RequestCredentialsErrorType.Abort,
|
|
914
|
+
message: RequestCredentialsErrorMessage.Abort
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
if (statusResult.isErr()) {
|
|
918
|
+
if (statusResult.error.status === 404) {
|
|
919
|
+
return neverthrow.err({
|
|
920
|
+
type: exports.RequestCredentialsErrorType.Timeout,
|
|
921
|
+
message: RequestCredentialsErrorMessage.Timeout
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
throw Error("Unexpected status response. Retry");
|
|
925
|
+
}
|
|
926
|
+
if (statusResult.value.status !== PresentationStatusCode.ResultReady) {
|
|
927
|
+
throw Error("Result is not ready. Retry");
|
|
928
|
+
}
|
|
929
|
+
return neverthrow.ok(undefined);
|
|
930
|
+
}), {
|
|
931
|
+
retries: SESSION_STATUS_POLLING_MAX_RETRY,
|
|
932
|
+
retryDelay: SESSION_STATUS_POLLING_INTERVAL_MS
|
|
933
|
+
});
|
|
934
|
+
if (checkResult.isErr()) {
|
|
935
|
+
return neverthrow.err(checkResult.error);
|
|
936
|
+
}
|
|
937
|
+
window.close();
|
|
938
|
+
return neverthrow.ok({
|
|
939
|
+
sessionId: sessionId,
|
|
940
|
+
sessionCompletedInRedirect: true
|
|
941
|
+
});
|
|
942
|
+
};
|
|
943
|
+
|
|
944
|
+
const requestCredentials = async options => {
|
|
945
|
+
var _a;
|
|
946
|
+
const initializeOptions = getInitializeOptions();
|
|
947
|
+
if (!initializeOptions) {
|
|
948
|
+
throw new Exception(InitializeErrorMessage.SdkNotInitialized);
|
|
656
949
|
}
|
|
657
|
-
|
|
950
|
+
assertType(RequestCredentialsOptionsValidator, "Invalid request credential options")(options);
|
|
951
|
+
const {apiBaseUrl: apiBaseUrl, applicationId: applicationId} = initializeOptions;
|
|
952
|
+
const {challenge: challenge = generateChallenge(), credentialQuery: credentialQuery, openid4vpConfiguration: openid4vpConfiguration} = options;
|
|
953
|
+
const dcApiSupported = isDigitalCredentialsApiSupported();
|
|
954
|
+
const openId4VpRedirectUri = deriveOpenId4vpRedirectUri(openid4vpConfiguration);
|
|
955
|
+
const createSessionResult = await createSession({
|
|
658
956
|
credentialQuery: credentialQuery,
|
|
659
|
-
challenge:
|
|
957
|
+
challenge: challenge,
|
|
958
|
+
redirectUri: openId4VpRedirectUri,
|
|
959
|
+
walletProviderId: (_a = openid4vpConfiguration === null || openid4vpConfiguration === void 0 ? void 0 : openid4vpConfiguration.walletProviderId) !== null && _a !== void 0 ? _a : undefined,
|
|
660
960
|
apiBaseUrl: apiBaseUrl,
|
|
661
|
-
|
|
961
|
+
applicationId: applicationId,
|
|
962
|
+
dcApiSupported: dcApiSupported
|
|
662
963
|
});
|
|
663
964
|
if (createSessionResult.isErr()) {
|
|
664
965
|
return neverthrow.err({
|
|
665
966
|
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
666
|
-
message:
|
|
967
|
+
message: RequestCredentialsErrorMessage.FailedToCreateSession,
|
|
667
968
|
cause: createSessionResult.error
|
|
668
969
|
});
|
|
669
970
|
}
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
971
|
+
const session = createSessionResult.value;
|
|
972
|
+
const {sessionKey: sessionKey, sessionId: sessionId} = session;
|
|
973
|
+
if (session.type === SessionType.DigitalCredentialsApi) {
|
|
974
|
+
const {request: request, sessionTtl: sessionTtl} = session;
|
|
975
|
+
return await requestCredentialsWithDigitalCredentialsApi({
|
|
976
|
+
apiBaseUrl: apiBaseUrl,
|
|
977
|
+
request: request,
|
|
978
|
+
sessionId: sessionId,
|
|
979
|
+
sessionKey: sessionKey,
|
|
980
|
+
challenge: challenge,
|
|
981
|
+
sessionTtl: sessionTtl
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
if (!openid4vpConfiguration) {
|
|
676
985
|
return neverthrow.err({
|
|
677
986
|
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
678
|
-
message:
|
|
987
|
+
message: RequestCredentialsErrorMessage.MissingOpenId4vpConfig
|
|
679
988
|
});
|
|
680
989
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
990
|
+
const {sessionUrl: sessionUrl} = session;
|
|
991
|
+
if (openId4VpRedirectUri) {
|
|
992
|
+
return await requestCredentialsSameDevice({
|
|
993
|
+
challenge: challenge,
|
|
994
|
+
apiBaseUrl: apiBaseUrl,
|
|
995
|
+
applicationId: applicationId,
|
|
996
|
+
sessionUrl: sessionUrl,
|
|
997
|
+
sessionKey: sessionKey,
|
|
998
|
+
sessionId: sessionId
|
|
999
|
+
});
|
|
686
1000
|
}
|
|
687
|
-
|
|
1001
|
+
return await requestCredentialsWithCrossDevice({
|
|
688
1002
|
challenge: challenge,
|
|
689
|
-
sessionId: sessionId,
|
|
690
|
-
response: response,
|
|
691
1003
|
apiBaseUrl: apiBaseUrl,
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
return neverthrow.ok({
|
|
696
|
-
sessionId: sessionId,
|
|
697
|
-
result: result.value
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
return neverthrow.err({
|
|
701
|
-
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
702
|
-
message: "Invalid response from digital credentials api"
|
|
1004
|
+
sessionUrl: sessionUrl,
|
|
1005
|
+
sessionKey: sessionKey,
|
|
1006
|
+
sessionId: sessionId
|
|
703
1007
|
});
|
|
704
1008
|
};
|
|
705
1009
|
|
|
706
|
-
const
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
if (!initialiseOptions) {
|
|
710
|
-
throw new Exception(InitialiseErrorMessage.SdkNotInitialised);
|
|
1010
|
+
const deriveOpenId4vpRedirectUri = openid4vpConfiguration => {
|
|
1011
|
+
if (!openid4vpConfiguration) {
|
|
1012
|
+
return undefined;
|
|
711
1013
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
return await requestCredentialsDigitalCredentialsApi(Object.assign(Object.assign({}, options), {
|
|
718
|
-
initialiseOptions: initialiseOptions,
|
|
719
|
-
challenge: challenge
|
|
720
|
-
}));
|
|
721
|
-
} else if (initialiseOptions.enableDigitalCredentialsApiCrossDeviceFlow) {
|
|
722
|
-
console.log("Digital Credentials API support not found, falling back to OpenID4VP");
|
|
723
|
-
}
|
|
724
|
-
if (initialiseOptions.enableDigitalCredentialsApiSameDeviceFlow && isDigitalCredentialsApiSupported() && mode === exports.Mode.sameDevice) {
|
|
725
|
-
console.log("Digital Credentials API support found, proceeding with request using API in same device flow");
|
|
726
|
-
return await requestCredentialsDigitalCredentialsApi(Object.assign(Object.assign({}, options), {
|
|
727
|
-
initialiseOptions: initialiseOptions,
|
|
728
|
-
challenge: challenge
|
|
729
|
-
}));
|
|
730
|
-
} else if (initialiseOptions.enableDigitalCredentialsApiSameDeviceFlow) {
|
|
731
|
-
console.log("Digital Credentials API support not found, falling back to OpenID4VP");
|
|
1014
|
+
let detectedMode;
|
|
1015
|
+
if (openid4vpConfiguration && openid4vpConfiguration.mode) {
|
|
1016
|
+
detectedMode = openid4vpConfiguration.mode;
|
|
1017
|
+
} else {
|
|
1018
|
+
detectedMode = isMobileDetect(navigator.userAgent) ? exports.Mode.SameDevice : exports.Mode.CrossDevice;
|
|
732
1019
|
}
|
|
733
|
-
if (
|
|
734
|
-
return
|
|
735
|
-
initialiseOptions: initialiseOptions,
|
|
736
|
-
challenge: challenge,
|
|
737
|
-
mode: mode
|
|
738
|
-
}));
|
|
1020
|
+
if (detectedMode === exports.Mode.SameDevice && !isType(OpenId4vpConfigCrossDeviceOptionsValidator)(openid4vpConfiguration) && openid4vpConfiguration.redirectUri) {
|
|
1021
|
+
return openid4vpConfiguration.redirectUri.trim();
|
|
739
1022
|
}
|
|
740
|
-
|
|
741
|
-
return await requestCredentialsCrossDevice(Object.assign(Object.assign({}, options), {
|
|
742
|
-
initialiseOptions: initialiseOptions,
|
|
743
|
-
challenge: challenge,
|
|
744
|
-
mode: mode
|
|
745
|
-
}));
|
|
746
|
-
}
|
|
747
|
-
throw new Exception("Invalid request credential options", {
|
|
748
|
-
data: options
|
|
749
|
-
});
|
|
1023
|
+
return undefined;
|
|
750
1024
|
};
|
|
751
1025
|
|
|
752
1026
|
exports.HandleRedirectCallbackErrorType = void 0;
|
|
@@ -760,16 +1034,16 @@ var HandleRedirectCallbackErrorMessage;
|
|
|
760
1034
|
(function(HandleRedirectCallbackErrorMessage) {
|
|
761
1035
|
HandleRedirectCallbackErrorMessage["FailedToFindResponseCode"] = "Failed to find response code";
|
|
762
1036
|
HandleRedirectCallbackErrorMessage["FailedToFindChallenge"] = "Failed to find challenge";
|
|
763
|
-
HandleRedirectCallbackErrorMessage["
|
|
1037
|
+
HandleRedirectCallbackErrorMessage["FailedToFindActiveSession"] = "Failed to find active session";
|
|
764
1038
|
HandleRedirectCallbackErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
|
|
765
1039
|
})(HandleRedirectCallbackErrorMessage || (HandleRedirectCallbackErrorMessage = {}));
|
|
766
1040
|
|
|
767
1041
|
const handleRedirectCallback = async () => {
|
|
768
|
-
const
|
|
769
|
-
if (!
|
|
770
|
-
throw new Exception(
|
|
1042
|
+
const initializeOptions = getInitializeOptions();
|
|
1043
|
+
if (!initializeOptions) {
|
|
1044
|
+
throw new Exception(InitializeErrorMessage.SdkNotInitialized);
|
|
771
1045
|
}
|
|
772
|
-
const {apiBaseUrl: apiBaseUrl} =
|
|
1046
|
+
const {apiBaseUrl: apiBaseUrl} = initializeOptions;
|
|
773
1047
|
const responseCode = getHashParamValue(window.location.hash, "response_code");
|
|
774
1048
|
if (!responseCode) {
|
|
775
1049
|
return neverthrow.err({
|
|
@@ -777,18 +1051,12 @@ const handleRedirectCallback = async () => {
|
|
|
777
1051
|
message: HandleRedirectCallbackErrorMessage.FailedToFindResponseCode
|
|
778
1052
|
});
|
|
779
1053
|
}
|
|
780
|
-
const challenge = window.localStorage.getItem(LocalStorageKey.challenge);
|
|
781
|
-
if (!challenge) {
|
|
782
|
-
return neverthrow.err({
|
|
783
|
-
type: exports.HandleRedirectCallbackErrorType.HandleRedirectCallbackFailed,
|
|
784
|
-
message: HandleRedirectCallbackErrorMessage.FailedToFindChallenge
|
|
785
|
-
});
|
|
786
|
-
}
|
|
787
1054
|
const sessionId = window.localStorage.getItem(LocalStorageKey.sessionId);
|
|
788
|
-
|
|
1055
|
+
const challenge = window.localStorage.getItem(LocalStorageKey.challenge);
|
|
1056
|
+
if (!sessionId || !challenge) {
|
|
789
1057
|
return neverthrow.err({
|
|
790
1058
|
type: exports.HandleRedirectCallbackErrorType.HandleRedirectCallbackFailed,
|
|
791
|
-
message: HandleRedirectCallbackErrorMessage.
|
|
1059
|
+
message: HandleRedirectCallbackErrorMessage.FailedToFindActiveSession
|
|
792
1060
|
});
|
|
793
1061
|
}
|
|
794
1062
|
const result = await exchangeSessionResult({
|
|
@@ -805,20 +1073,24 @@ const handleRedirectCallback = async () => {
|
|
|
805
1073
|
});
|
|
806
1074
|
}
|
|
807
1075
|
return neverthrow.ok({
|
|
808
|
-
result: result.value,
|
|
1076
|
+
result: "challenge" in result.value ? result.value : undefined,
|
|
809
1077
|
sessionId: result.value.sessionId
|
|
810
1078
|
});
|
|
811
1079
|
};
|
|
812
1080
|
|
|
813
1081
|
const utils = {
|
|
814
1082
|
generateChallenge: generateChallenge,
|
|
815
|
-
|
|
816
|
-
|
|
1083
|
+
getVersion: getVersion,
|
|
1084
|
+
unwrap: unwrap
|
|
817
1085
|
};
|
|
818
1086
|
|
|
1087
|
+
exports.abortCredentialRequest = abortCredentialRequest;
|
|
1088
|
+
|
|
819
1089
|
exports.handleRedirectCallback = handleRedirectCallback;
|
|
820
1090
|
|
|
821
|
-
exports.
|
|
1091
|
+
exports.initialize = initialize;
|
|
1092
|
+
|
|
1093
|
+
exports.isDigitalCredentialsApiSupported = isDigitalCredentialsApiSupported;
|
|
822
1094
|
|
|
823
1095
|
exports.requestCredentials = requestCredentials;
|
|
824
1096
|
|