@interop/wallet-core 0.1.1 → 0.3.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 +27 -3
- package/dist/display/alignment.d.ts +49 -0
- package/dist/display/alignment.d.ts.map +1 -0
- package/dist/display/alignment.js +114 -0
- package/dist/display/alignment.js.map +1 -0
- package/dist/display/credentialName.d.ts +42 -0
- package/dist/display/credentialName.d.ts.map +1 -0
- package/dist/display/credentialName.js +106 -0
- package/dist/display/credentialName.js.map +1 -0
- package/dist/display/displayFields.d.ts +55 -0
- package/dist/display/displayFields.d.ts.map +1 -0
- package/dist/display/displayFields.js +136 -0
- package/dist/display/displayFields.js.map +1 -0
- package/dist/display/evidence.d.ts +44 -0
- package/dist/display/evidence.d.ts.map +1 -0
- package/dist/display/evidence.js +65 -0
- package/dist/display/evidence.js.map +1 -0
- package/dist/display/image.d.ts +18 -0
- package/dist/display/image.d.ts.map +1 -0
- package/dist/display/image.js +23 -0
- package/dist/display/image.js.map +1 -0
- package/dist/display/index.d.ts +38 -0
- package/dist/display/index.d.ts.map +1 -0
- package/dist/display/index.js +32 -0
- package/dist/display/index.js.map +1 -0
- package/dist/display/issuer.d.ts +97 -0
- package/dist/display/issuer.d.ts.map +1 -0
- package/dist/display/issuer.js +126 -0
- package/dist/display/issuer.js.map +1 -0
- package/dist/display/obv3.d.ts +77 -0
- package/dist/display/obv3.d.ts.map +1 -0
- package/dist/display/obv3.js +127 -0
- package/dist/display/obv3.js.map +1 -0
- package/dist/display/parse.d.ts +62 -0
- package/dist/display/parse.d.ts.map +1 -0
- package/dist/display/parse.js +100 -0
- package/dist/display/parse.js.map +1 -0
- package/dist/display/subject.d.ts +75 -0
- package/dist/display/subject.d.ts.map +1 -0
- package/dist/display/subject.js +122 -0
- package/dist/display/subject.js.map +1 -0
- package/dist/display/text.d.ts +42 -0
- package/dist/display/text.d.ts.map +1 -0
- package/dist/display/text.js +62 -0
- package/dist/display/text.js.map +1 -0
- package/dist/display/types.d.ts +55 -0
- package/dist/display/types.d.ts.map +1 -0
- package/dist/display/types.js +41 -0
- package/dist/display/types.js.map +1 -0
- package/dist/display/validity.d.ts +51 -0
- package/dist/display/validity.d.ts.map +1 -0
- package/dist/display/validity.js +51 -0
- package/dist/display/validity.js.map +1 -0
- package/dist/display/verificationView.d.ts +101 -0
- package/dist/display/verificationView.d.ts.map +1 -0
- package/dist/display/verificationView.js +199 -0
- package/dist/display/verificationView.js.map +1 -0
- package/dist/identity/agents.d.ts +68 -0
- package/dist/identity/agents.d.ts.map +1 -0
- package/dist/identity/agents.js +95 -0
- package/dist/identity/agents.js.map +1 -0
- package/dist/identity/index.d.ts +20 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +19 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/keyResolver.d.ts +30 -0
- package/dist/identity/keyResolver.d.ts.map +1 -0
- package/dist/identity/keyResolver.js +25 -0
- package/dist/identity/keyResolver.js.map +1 -0
- package/dist/index.d.ts +14 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/dist/request/classify.d.ts +112 -0
- package/dist/request/classify.d.ts.map +1 -0
- package/dist/request/classify.js +210 -0
- package/dist/request/classify.js.map +1 -0
- package/dist/request/composeVp.d.ts +52 -0
- package/dist/request/composeVp.d.ts.map +1 -0
- package/dist/request/composeVp.js +177 -0
- package/dist/request/composeVp.js.map +1 -0
- package/dist/request/exchangeClient.d.ts +165 -0
- package/dist/request/exchangeClient.d.ts.map +1 -0
- package/dist/request/exchangeClient.js +212 -0
- package/dist/request/exchangeClient.js.map +1 -0
- package/dist/request/index.d.ts +35 -0
- package/dist/request/index.d.ts.map +1 -0
- package/dist/request/index.js +35 -0
- package/dist/request/index.js.map +1 -0
- package/dist/request/interactionUrl.d.ts +53 -0
- package/dist/request/interactionUrl.d.ts.map +1 -0
- package/dist/request/interactionUrl.js +83 -0
- package/dist/request/interactionUrl.js.map +1 -0
- package/dist/request/matching.d.ts +69 -0
- package/dist/request/matching.d.ts.map +1 -0
- package/dist/request/matching.js +183 -0
- package/dist/request/matching.js.map +1 -0
- package/dist/request/parse.d.ts +68 -0
- package/dist/request/parse.d.ts.map +1 -0
- package/dist/request/parse.js +114 -0
- package/dist/request/parse.js.map +1 -0
- package/dist/request/presentationSuite.d.ts +71 -0
- package/dist/request/presentationSuite.d.ts.map +1 -0
- package/dist/request/presentationSuite.js +139 -0
- package/dist/request/presentationSuite.js.map +1 -0
- package/dist/request/processRequest.d.ts +48 -0
- package/dist/request/processRequest.d.ts.map +1 -0
- package/dist/request/processRequest.js +139 -0
- package/dist/request/processRequest.js.map +1 -0
- package/dist/request/types.d.ts +150 -0
- package/dist/request/types.d.ts.map +1 -0
- package/dist/request/types.js +2 -0
- package/dist/request/types.js.map +1 -0
- package/dist/sync/types.d.ts.map +1 -1
- package/package.json +31 -3
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* VCALM `interaction:` URL handling: detecting an interaction URL, normalizing
|
|
6
|
+
* it to its inner HTTPS URL, and fetching the protocols map it advertises. An
|
|
7
|
+
* interaction URL is a level of indirection a verifier / issuer hands the wallet
|
|
8
|
+
* (over a deep link or QR code) that resolves to a `protocols` map naming the
|
|
9
|
+
* real exchange endpoints.
|
|
10
|
+
*
|
|
11
|
+
* Ported verbatim from DCW's `app/lib/interactionUrl.ts`, with the network
|
|
12
|
+
* transport injected ({@link FetchLike}, default `globalThis.fetch`).
|
|
13
|
+
*/
|
|
14
|
+
import type { FetchLike } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Detects whether a URL is a VCALM interaction URL.
|
|
17
|
+
*
|
|
18
|
+
* Two formats:
|
|
19
|
+
* - `interaction:` scheme: `interaction:https://example.com/path?iuv=1`
|
|
20
|
+
* - HTTPS URL with an `iuv` query param: `https://example.com/path?iuv=1`
|
|
21
|
+
*
|
|
22
|
+
* @param url {string}
|
|
23
|
+
* @returns {boolean}
|
|
24
|
+
*/
|
|
25
|
+
export declare function isInteractionUrl(url: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Normalizes any interaction URL to the inner HTTPS interaction URL. Accepts any
|
|
28
|
+
* URL that passed {@link isInteractionUrl}.
|
|
29
|
+
*
|
|
30
|
+
* - `interaction:https://...?iuv=1` strips the prefix
|
|
31
|
+
* - `interaction:https%3A%2F%2F...` strips the prefix and decodes (URL-encoded
|
|
32
|
+
* after `interaction:` is non-standard, but handled for robustness)
|
|
33
|
+
* - `https://...?iuv=1` is returned as-is
|
|
34
|
+
*
|
|
35
|
+
* @param url {string}
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseInteractionUrl(url: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Fetches the interaction protocols response from a VCALM interaction URL. Sends
|
|
41
|
+
* GET with `Accept: application/json` per the VCALM spec, and returns the
|
|
42
|
+
* protocols map. Logs a warning if the `iuv` param value is not `1`; throws if
|
|
43
|
+
* the response is not ok or the `protocols` key is missing.
|
|
44
|
+
*
|
|
45
|
+
* @param interactionUrl {string}
|
|
46
|
+
* @param [options] {object}
|
|
47
|
+
* @param [options.fetch] {FetchLike}
|
|
48
|
+
* @returns {Promise<Record<string, string>>}
|
|
49
|
+
*/
|
|
50
|
+
export declare function fetchInteractionProtocols(interactionUrl: string, { fetch }?: {
|
|
51
|
+
fetch?: FetchLike;
|
|
52
|
+
}): Promise<Record<string, string>>;
|
|
53
|
+
//# sourceMappingURL=interactionUrl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactionUrl.d.ts","sourceRoot":"","sources":["../../src/request/interactionUrl.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAI3C;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWvD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAC7C,cAAc,EAAE,MAAM,EACtB,EAAE,KAAwB,EAAE,GAAE;IAAE,KAAK,CAAC,EAAE,SAAS,CAAA;CAAO,GACvD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA+BjC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const INTERACTION_SCHEME_PREFIX = 'interaction:';
|
|
2
|
+
/**
|
|
3
|
+
* Detects whether a URL is a VCALM interaction URL.
|
|
4
|
+
*
|
|
5
|
+
* Two formats:
|
|
6
|
+
* - `interaction:` scheme: `interaction:https://example.com/path?iuv=1`
|
|
7
|
+
* - HTTPS URL with an `iuv` query param: `https://example.com/path?iuv=1`
|
|
8
|
+
*
|
|
9
|
+
* @param url {string}
|
|
10
|
+
* @returns {boolean}
|
|
11
|
+
*/
|
|
12
|
+
export function isInteractionUrl(url) {
|
|
13
|
+
if (url.startsWith(INTERACTION_SCHEME_PREFIX)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const parsed = new URL(url);
|
|
18
|
+
return parsed.searchParams.has('iuv');
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Normalizes any interaction URL to the inner HTTPS interaction URL. Accepts any
|
|
26
|
+
* URL that passed {@link isInteractionUrl}.
|
|
27
|
+
*
|
|
28
|
+
* - `interaction:https://...?iuv=1` strips the prefix
|
|
29
|
+
* - `interaction:https%3A%2F%2F...` strips the prefix and decodes (URL-encoded
|
|
30
|
+
* after `interaction:` is non-standard, but handled for robustness)
|
|
31
|
+
* - `https://...?iuv=1` is returned as-is
|
|
32
|
+
*
|
|
33
|
+
* @param url {string}
|
|
34
|
+
* @returns {string}
|
|
35
|
+
*/
|
|
36
|
+
export function parseInteractionUrl(url) {
|
|
37
|
+
if (!url.startsWith(INTERACTION_SCHEME_PREFIX)) {
|
|
38
|
+
return url;
|
|
39
|
+
}
|
|
40
|
+
const inner = url.slice(INTERACTION_SCHEME_PREFIX.length);
|
|
41
|
+
// Non-standard: the inner URL may be URL-encoded after the `interaction:`
|
|
42
|
+
// prefix.
|
|
43
|
+
if (inner.startsWith('http%3A') || inner.startsWith('https%3A')) {
|
|
44
|
+
return decodeURIComponent(inner);
|
|
45
|
+
}
|
|
46
|
+
return inner;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Fetches the interaction protocols response from a VCALM interaction URL. Sends
|
|
50
|
+
* GET with `Accept: application/json` per the VCALM spec, and returns the
|
|
51
|
+
* protocols map. Logs a warning if the `iuv` param value is not `1`; throws if
|
|
52
|
+
* the response is not ok or the `protocols` key is missing.
|
|
53
|
+
*
|
|
54
|
+
* @param interactionUrl {string}
|
|
55
|
+
* @param [options] {object}
|
|
56
|
+
* @param [options.fetch] {FetchLike}
|
|
57
|
+
* @returns {Promise<Record<string, string>>}
|
|
58
|
+
*/
|
|
59
|
+
export async function fetchInteractionProtocols(interactionUrl, { fetch = globalThis.fetch } = {}) {
|
|
60
|
+
try {
|
|
61
|
+
const parsed = new URL(interactionUrl);
|
|
62
|
+
const iuv = parsed.searchParams.get('iuv');
|
|
63
|
+
if (iuv && iuv !== '1') {
|
|
64
|
+
console.warn(`[fetchInteractionProtocols] Unexpected iuv value "${iuv}" ` +
|
|
65
|
+
'(expected "1"). Proceeding anyway.');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
throw new Error(`Invalid interaction URL: ${interactionUrl}`);
|
|
70
|
+
}
|
|
71
|
+
const response = await fetch(interactionUrl, {
|
|
72
|
+
headers: { Accept: 'application/json' }
|
|
73
|
+
});
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
throw new Error(`Interaction URL fetch failed: ${response.status} ${response.statusText}`);
|
|
76
|
+
}
|
|
77
|
+
const body = await response.json();
|
|
78
|
+
if (!body.protocols || typeof body.protocols !== 'object') {
|
|
79
|
+
throw new Error('Interaction URL response missing "protocols" map.');
|
|
80
|
+
}
|
|
81
|
+
return body.protocols;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=interactionUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactionUrl.js","sourceRoot":"","sources":["../../src/request/interactionUrl.ts"],"names":[],"mappings":"AAeA,MAAM,yBAAyB,GAAG,cAAc,CAAA;AAEhD;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,GAAG,CAAC,UAAU,CAAC,yBAAyB,CAAC,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,OAAO,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,yBAAyB,CAAC,EAAE,CAAC;QAC/C,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAA;IACzD,0EAA0E;IAC1E,UAAU;IACV,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAChE,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,cAAsB,EACtB,EAAE,KAAK,GAAG,UAAU,CAAC,KAAK,KAA4B,EAAE;IAExD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAA;QACtC,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAC1C,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CACV,qDAAqD,GAAG,IAAI;gBAC1D,oCAAoC,CACvC,CAAA;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,4BAA4B,cAAc,EAAE,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,cAAc,EAAE;QAC3C,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;KACxC,CAAC,CAAA;IAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,iCAAiC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAC1E,CAAA;IACH,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IAElC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACtE,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAA;AACvB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { IVerifiableCredential } from './types.js';
|
|
2
|
+
import type { IQueryByExample } from './types.js';
|
|
3
|
+
export { issuerId, typeArray } from '@interop/data-integrity-core/guards';
|
|
4
|
+
/**
|
|
5
|
+
* Whether a credential matches a QueryByExample `example` object, by the DCW
|
|
6
|
+
* deep-matching algorithm: every key of the example is resolved as a JSONPath
|
|
7
|
+
* against the credential and compared. Array example values require the
|
|
8
|
+
* credential to contain (at least) every listed value; object example values
|
|
9
|
+
* recurse; literal example values compare by strict equality. An empty example
|
|
10
|
+
* matches any credential.
|
|
11
|
+
*
|
|
12
|
+
* @param vprExample {Record<string, unknown>} - The QueryByExample `example`.
|
|
13
|
+
* @param credential {IVerifiableCredential} - The stored credential to test.
|
|
14
|
+
* @param [credentialPath] {string} - JSONPath root into the credential
|
|
15
|
+
* (defaults to `$`); used internally when recursing into nested objects.
|
|
16
|
+
* @returns {boolean}
|
|
17
|
+
*/
|
|
18
|
+
export declare function credentialMatchesVprExampleQuery(vprExample: Record<string, unknown>, credential: IVerifiableCredential, credentialPath?: string): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Filters credentials to those matching a `QueryByExample`, using the deep
|
|
21
|
+
* matcher. Each of the query's `credentialQuery` details contributes its
|
|
22
|
+
* `example`; a credential is included when it matches any of them. A malformed
|
|
23
|
+
* query with no example matches nothing.
|
|
24
|
+
*
|
|
25
|
+
* @param credentials {IVerifiableCredential[]}
|
|
26
|
+
* @param query {IQueryByExample}
|
|
27
|
+
* @returns {IVerifiableCredential[]}
|
|
28
|
+
*/
|
|
29
|
+
export declare function filterCredentialsByExample(credentials: IVerifiableCredential[], query: IQueryByExample): IVerifiableCredential[];
|
|
30
|
+
/**
|
|
31
|
+
* The credentials matching any of the given QueryByExample queries by the
|
|
32
|
+
* type-and-issuer algorithm. Only queries whose `example` carries a `type`
|
|
33
|
+
* constrain the result; a query with no example type matches nothing here (the
|
|
34
|
+
* caller keeps its list-all behavior when *no* query specifies a type).
|
|
35
|
+
*
|
|
36
|
+
* @param options {object}
|
|
37
|
+
* @param options.credentials {IVerifiableCredential[]}
|
|
38
|
+
* @param options.queries {IQueryByExample[]}
|
|
39
|
+
* @returns {IVerifiableCredential[]}
|
|
40
|
+
*/
|
|
41
|
+
export declare function vcMatchesFor({ credentials, queries }: {
|
|
42
|
+
credentials: IVerifiableCredential[];
|
|
43
|
+
queries: IQueryByExample[];
|
|
44
|
+
}): IVerifiableCredential[];
|
|
45
|
+
/**
|
|
46
|
+
* Whether any of the QueryByExample queries pins an example `type` (and so
|
|
47
|
+
* should filter the share list). When false, the caller keeps showing all
|
|
48
|
+
* stored credentials.
|
|
49
|
+
*
|
|
50
|
+
* @param queries {IQueryByExample[]}
|
|
51
|
+
* @returns {boolean}
|
|
52
|
+
*/
|
|
53
|
+
export declare function hasTypedExample(queries: IQueryByExample[]): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Whether any typed example in the query set explicitly lists the given
|
|
56
|
+
* credential `type`. Lets the caller distinguish a request that actually asks
|
|
57
|
+
* for a particular type (e.g. a LoginCredential) from a generic, untyped "any
|
|
58
|
+
* VC" request.
|
|
59
|
+
*
|
|
60
|
+
* @param options {object}
|
|
61
|
+
* @param options.queries {IQueryByExample[]}
|
|
62
|
+
* @param options.type {string}
|
|
63
|
+
* @returns {boolean}
|
|
64
|
+
*/
|
|
65
|
+
export declare function requestsCredentialType({ queries, type }: {
|
|
66
|
+
queries: IQueryByExample[];
|
|
67
|
+
type: string;
|
|
68
|
+
}): boolean;
|
|
69
|
+
//# sourceMappingURL=matching.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matching.d.ts","sourceRoot":"","sources":["../../src/request/matching.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,KAAK,EAAoB,eAAe,EAAE,MAAM,YAAY,CAAA;AAMnE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAEzE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gCAAgC,CAC9C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,UAAU,EAAE,qBAAqB,EACjC,cAAc,SAAM,GACnB,OAAO,CAoCT;AAeD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,qBAAqB,EAAE,EACpC,KAAK,EAAE,eAAe,GACrB,qBAAqB,EAAE,CAgBzB;AAiCD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAC3B,WAAW,EACX,OAAO,EACR,EAAE;IACD,WAAW,EAAE,qBAAqB,EAAE,CAAA;IACpC,OAAO,EAAE,eAAe,EAAE,CAAA;CAC3B,GAAG,qBAAqB,EAAE,CAQ1B;AAqBD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,OAAO,CAEnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,IAAI,EACL,EAAE;IACD,OAAO,EAAE,eAAe,EAAE,CAAA;IAC1B,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAIV"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* QueryByExample matching: which stored credentials satisfy a verifier's
|
|
6
|
+
* `QueryByExample` request. Two independent algorithms ship here because the two
|
|
7
|
+
* apps genuinely differ, and each wallet matches only its own local store (no
|
|
8
|
+
* cross-replica agreement is required):
|
|
9
|
+
*
|
|
10
|
+
* - `credentialMatchesVprExampleQuery` / `filterCredentialsByExample` -- DCW's
|
|
11
|
+
* jsonpath-plus deep matcher, which walks the example object and matches any
|
|
12
|
+
* nested field (arrays, nested objects, literals) against the credential.
|
|
13
|
+
* - `vcMatchesFor` / `hasTypedExample` / `requestsCredentialType` --
|
|
14
|
+
* Freewallet's type-and-issuer matcher, which constrains only on the
|
|
15
|
+
* example's `type` (and, when pinned, `issuer`).
|
|
16
|
+
*
|
|
17
|
+
* Both operate on plain `IVerifiableCredential`s; each app maps its own record
|
|
18
|
+
* type down to the credential before calling. Ported from DCW's
|
|
19
|
+
* `app/lib/credentialMatching.ts` and Freewallet's
|
|
20
|
+
* `src/lib/walletRequest/vcMatches.ts`.
|
|
21
|
+
*/
|
|
22
|
+
import { JSONPath } from 'jsonpath-plus';
|
|
23
|
+
import { credentialQueriesOf } from './classify.js';
|
|
24
|
+
import { issuerId, typeArray } from '@interop/data-integrity-core/guards';
|
|
25
|
+
// The loose-field normalizers are owned by data-integrity-core; re-export them
|
|
26
|
+
// here so a matching consumer imports one module.
|
|
27
|
+
export { issuerId, typeArray } from '@interop/data-integrity-core/guards';
|
|
28
|
+
/**
|
|
29
|
+
* Whether a credential matches a QueryByExample `example` object, by the DCW
|
|
30
|
+
* deep-matching algorithm: every key of the example is resolved as a JSONPath
|
|
31
|
+
* against the credential and compared. Array example values require the
|
|
32
|
+
* credential to contain (at least) every listed value; object example values
|
|
33
|
+
* recurse; literal example values compare by strict equality. An empty example
|
|
34
|
+
* matches any credential.
|
|
35
|
+
*
|
|
36
|
+
* @param vprExample {Record<string, unknown>} - The QueryByExample `example`.
|
|
37
|
+
* @param credential {IVerifiableCredential} - The stored credential to test.
|
|
38
|
+
* @param [credentialPath] {string} - JSONPath root into the credential
|
|
39
|
+
* (defaults to `$`); used internally when recursing into nested objects.
|
|
40
|
+
* @returns {boolean}
|
|
41
|
+
*/
|
|
42
|
+
export function credentialMatchesVprExampleQuery(vprExample, credential, credentialPath = '$') {
|
|
43
|
+
const matches = [];
|
|
44
|
+
for (const [vprExampleKey, vprExampleValue] of Object.entries(vprExample)) {
|
|
45
|
+
const nextPath = extendPath(credentialPath, vprExampleKey);
|
|
46
|
+
// The result is always dumped into a single-element array.
|
|
47
|
+
const [credentialScope] = JSONPath({ path: nextPath, json: credential });
|
|
48
|
+
if (Array.isArray(vprExampleValue)) {
|
|
49
|
+
// Array query values require that the matching credential contains at
|
|
50
|
+
// least every value specified. This assumes each element is a literal.
|
|
51
|
+
if (!Array.isArray(credentialScope)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (credentialScope.length < vprExampleValue.length) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
matches.push(vprExampleValue.every(exVal => credentialScope.includes(exVal)));
|
|
58
|
+
}
|
|
59
|
+
else if (typeof vprExampleValue === 'object' &&
|
|
60
|
+
vprExampleValue !== null) {
|
|
61
|
+
// Object query values recurse, to handle nested queries.
|
|
62
|
+
matches.push(credentialMatchesVprExampleQuery(vprExampleValue, credential, nextPath));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Literal query values compare directly.
|
|
66
|
+
matches.push(credentialScope === vprExampleValue);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return matches.every(m => m);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extends a JSONPath by a literal key, escaping any JSONPath-reserved
|
|
73
|
+
* characters in the key (jsonpath-plus escapes a reserved char by prefixing it
|
|
74
|
+
* with a backtick).
|
|
75
|
+
*/
|
|
76
|
+
function extendPath(path, extension) {
|
|
77
|
+
const reserved = /[$@*()[\].:?]/g;
|
|
78
|
+
if (reserved.test(extension)) {
|
|
79
|
+
extension = extension.replace(reserved, match => '`' + match);
|
|
80
|
+
}
|
|
81
|
+
return `${path}.${extension}`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Filters credentials to those matching a `QueryByExample`, using the deep
|
|
85
|
+
* matcher. Each of the query's `credentialQuery` details contributes its
|
|
86
|
+
* `example`; a credential is included when it matches any of them. A malformed
|
|
87
|
+
* query with no example matches nothing.
|
|
88
|
+
*
|
|
89
|
+
* @param credentials {IVerifiableCredential[]}
|
|
90
|
+
* @param query {IQueryByExample}
|
|
91
|
+
* @returns {IVerifiableCredential[]}
|
|
92
|
+
*/
|
|
93
|
+
export function filterCredentialsByExample(credentials, query) {
|
|
94
|
+
const examples = credentialQueriesOf(query)
|
|
95
|
+
.map(({ example }) => example)
|
|
96
|
+
.filter((example) => !!example);
|
|
97
|
+
if (examples.length === 0) {
|
|
98
|
+
// Malformed request: no example to match against.
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
return credentials.filter(credential => examples.some(example => credentialMatchesVprExampleQuery(example, credential)));
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Whether a credential matches a single QueryByExample `example` by the
|
|
105
|
+
* type-and-issuer algorithm: every type listed in `example.type` must appear in
|
|
106
|
+
* the credential's `type`, and -- when the example pins an `issuer` -- the
|
|
107
|
+
* credential's issuer must equal it.
|
|
108
|
+
*
|
|
109
|
+
* @param options {object}
|
|
110
|
+
* @param options.credential {IVerifiableCredential}
|
|
111
|
+
* @param options.example {ICredentialQuery['example']}
|
|
112
|
+
* @returns {boolean}
|
|
113
|
+
*/
|
|
114
|
+
function matchesExample({ credential, example }) {
|
|
115
|
+
const wantedTypes = typeArray(example.type);
|
|
116
|
+
const credentialTypes = typeArray(credential.type);
|
|
117
|
+
const typesMatch = wantedTypes.every(type => credentialTypes.includes(type));
|
|
118
|
+
if (!typesMatch) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
const wantedIssuer = issuerId(example.issuer);
|
|
122
|
+
if (wantedIssuer) {
|
|
123
|
+
return issuerId(credential.issuer) === wantedIssuer;
|
|
124
|
+
}
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The credentials matching any of the given QueryByExample queries by the
|
|
129
|
+
* type-and-issuer algorithm. Only queries whose `example` carries a `type`
|
|
130
|
+
* constrain the result; a query with no example type matches nothing here (the
|
|
131
|
+
* caller keeps its list-all behavior when *no* query specifies a type).
|
|
132
|
+
*
|
|
133
|
+
* @param options {object}
|
|
134
|
+
* @param options.credentials {IVerifiableCredential[]}
|
|
135
|
+
* @param options.queries {IQueryByExample[]}
|
|
136
|
+
* @returns {IVerifiableCredential[]}
|
|
137
|
+
*/
|
|
138
|
+
export function vcMatchesFor({ credentials, queries }) {
|
|
139
|
+
const examples = typedExamplesOf(queries);
|
|
140
|
+
if (examples.length === 0) {
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
return credentials.filter(credential => examples.some(example => matchesExample({ credential, example })));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The example credential shapes pinned by a query set: every `credentialQuery`
|
|
147
|
+
* detail carrying an example `type`. Only these constrain the share list.
|
|
148
|
+
*
|
|
149
|
+
* @param queries {IQueryByExample[]}
|
|
150
|
+
* @returns {Array<ICredentialQuery['example']>}
|
|
151
|
+
*/
|
|
152
|
+
function typedExamplesOf(queries) {
|
|
153
|
+
return queries
|
|
154
|
+
.flatMap(query => credentialQueriesOf(query))
|
|
155
|
+
.map(({ example }) => example)
|
|
156
|
+
.filter((example) => !!example && typeArray(example.type).length > 0);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Whether any of the QueryByExample queries pins an example `type` (and so
|
|
160
|
+
* should filter the share list). When false, the caller keeps showing all
|
|
161
|
+
* stored credentials.
|
|
162
|
+
*
|
|
163
|
+
* @param queries {IQueryByExample[]}
|
|
164
|
+
* @returns {boolean}
|
|
165
|
+
*/
|
|
166
|
+
export function hasTypedExample(queries) {
|
|
167
|
+
return typedExamplesOf(queries).length > 0;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Whether any typed example in the query set explicitly lists the given
|
|
171
|
+
* credential `type`. Lets the caller distinguish a request that actually asks
|
|
172
|
+
* for a particular type (e.g. a LoginCredential) from a generic, untyped "any
|
|
173
|
+
* VC" request.
|
|
174
|
+
*
|
|
175
|
+
* @param options {object}
|
|
176
|
+
* @param options.queries {IQueryByExample[]}
|
|
177
|
+
* @param options.type {string}
|
|
178
|
+
* @returns {boolean}
|
|
179
|
+
*/
|
|
180
|
+
export function requestsCredentialType({ queries, type }) {
|
|
181
|
+
return typedExamplesOf(queries).some(example => typeArray(example.type).includes(type));
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=matching.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matching.js","sourceRoot":"","sources":["../../src/request/matching.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Parsing of incoming wallet/VC API messages that arrive as JSON text or a
|
|
6
|
+
* deep-link URL (`dccrequest://...?request=<json>`), plus the small
|
|
7
|
+
* query-inspection helpers a caller runs over a parsed VPR body. Ported from
|
|
8
|
+
* DCW's `app/lib/walletRequestApi.ts`; the `query-string` dependency is dropped
|
|
9
|
+
* in favor of the native `URL` / `URLSearchParams`.
|
|
10
|
+
*/
|
|
11
|
+
import type { IVPRQuery, IZcapQuery, WalletApiMessage } from './types.js';
|
|
12
|
+
export { isDIDAuthRequested as isDidAuthRequested } from './classify.js';
|
|
13
|
+
/**
|
|
14
|
+
* Whether a JSON string is a recognized wallet API message: an exchange
|
|
15
|
+
* invitation, a presentation request, a presentation offer, or an issuance
|
|
16
|
+
* request. Malformed JSON is not a message.
|
|
17
|
+
*
|
|
18
|
+
* @param text {string}
|
|
19
|
+
* @returns {boolean}
|
|
20
|
+
*/
|
|
21
|
+
export declare function isWalletApiMessage(text: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Classifies a parsed message object into one of the wallet API message types
|
|
24
|
+
* by its discriminating property. Returns `undefined` for an unrecognized
|
|
25
|
+
* shape.
|
|
26
|
+
*
|
|
27
|
+
* @param options {object}
|
|
28
|
+
* @param options.messageObject {object}
|
|
29
|
+
* @returns {WalletApiMessage | undefined}
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseWalletApiMessage({ messageObject }: {
|
|
32
|
+
messageObject: object;
|
|
33
|
+
}): WalletApiMessage | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Extracts and parses the wallet API message carried in a deep-link URL's
|
|
36
|
+
* `request` query parameter (`dccrequest://...?request=<json>`). Returns
|
|
37
|
+
* `undefined` when the parameter is absent or its value is not valid JSON.
|
|
38
|
+
*
|
|
39
|
+
* @param options {object}
|
|
40
|
+
* @param options.url {string}
|
|
41
|
+
* @returns {Record<string, unknown> | undefined}
|
|
42
|
+
*/
|
|
43
|
+
export declare function parseWalletApiUrl({ url }: {
|
|
44
|
+
url: string;
|
|
45
|
+
}): Record<string, unknown> | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Filters an incoming VCALM query set for capability (zcap) requests, returning
|
|
48
|
+
* only those. Recognizes both the canonical `AuthorizationCapabilityQuery` and
|
|
49
|
+
* the legacy `ZcapQuery` type strings.
|
|
50
|
+
*
|
|
51
|
+
* @param options {object}
|
|
52
|
+
* @param options.queries {IVPRQuery[]}
|
|
53
|
+
* @returns {{ zcapRequests?: IZcapQuery[] }}
|
|
54
|
+
*/
|
|
55
|
+
export declare function zcapsRequested({ queries }: {
|
|
56
|
+
queries: IVPRQuery[];
|
|
57
|
+
}): {
|
|
58
|
+
zcapRequests?: IZcapQuery[];
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Returns true if the message is a VPR whose only query type is
|
|
62
|
+
* `DIDAuthentication` (i.e. no credential sharing is involved).
|
|
63
|
+
*
|
|
64
|
+
* @param message {WalletApiMessage}
|
|
65
|
+
* @returns {boolean}
|
|
66
|
+
*/
|
|
67
|
+
export declare function isDIDAuthOnlyRequest(message: WalletApiMessage): boolean;
|
|
68
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/request/parse.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;GAMG;AACH,OAAO,KAAK,EAKV,SAAS,EACT,UAAU,EACV,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAInB,OAAO,EAAE,kBAAkB,IAAI,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAExE;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAexD;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,aAAa,EACd,EAAE;IACD,aAAa,EAAE,MAAM,CAAA;CACtB,GAAG,gBAAgB,GAAG,SAAS,CAe/B;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACJ,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAqBtC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,SAAS,EAAE,CAAA;CAAE,GAAG;IACrE,YAAY,CAAC,EAAE,UAAU,EAAE,CAAA;CAC5B,CASA;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAUvE"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// The DID-Auth query helper is spelled `isDIDAuthRequested` in `classify.ts`;
|
|
2
|
+
// DCW imported it as `isDidAuthRequested`. Both names resolve to one function.
|
|
3
|
+
export { isDIDAuthRequested as isDidAuthRequested } from './classify.js';
|
|
4
|
+
/**
|
|
5
|
+
* Whether a JSON string is a recognized wallet API message: an exchange
|
|
6
|
+
* invitation, a presentation request, a presentation offer, or an issuance
|
|
7
|
+
* request. Malformed JSON is not a message.
|
|
8
|
+
*
|
|
9
|
+
* @param text {string}
|
|
10
|
+
* @returns {boolean}
|
|
11
|
+
*/
|
|
12
|
+
export function isWalletApiMessage(text) {
|
|
13
|
+
let messageObject;
|
|
14
|
+
try {
|
|
15
|
+
messageObject = JSON.parse(text);
|
|
16
|
+
}
|
|
17
|
+
catch (_) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return (!!messageObject &&
|
|
21
|
+
typeof messageObject === 'object' &&
|
|
22
|
+
('protocols' in messageObject ||
|
|
23
|
+
'verifiablePresentationRequest' in messageObject ||
|
|
24
|
+
'verifiablePresentation' in messageObject ||
|
|
25
|
+
'issueRequest' in messageObject));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Classifies a parsed message object into one of the wallet API message types
|
|
29
|
+
* by its discriminating property. Returns `undefined` for an unrecognized
|
|
30
|
+
* shape.
|
|
31
|
+
*
|
|
32
|
+
* @param options {object}
|
|
33
|
+
* @param options.messageObject {object}
|
|
34
|
+
* @returns {WalletApiMessage | undefined}
|
|
35
|
+
*/
|
|
36
|
+
export function parseWalletApiMessage({ messageObject }) {
|
|
37
|
+
if ('protocols' in messageObject) {
|
|
38
|
+
return messageObject;
|
|
39
|
+
}
|
|
40
|
+
if ('verifiablePresentationRequest' in messageObject) {
|
|
41
|
+
return messageObject;
|
|
42
|
+
}
|
|
43
|
+
if ('verifiablePresentation' in messageObject) {
|
|
44
|
+
return messageObject;
|
|
45
|
+
}
|
|
46
|
+
if ('issueRequest' in messageObject) {
|
|
47
|
+
return messageObject;
|
|
48
|
+
}
|
|
49
|
+
// Message not recognized / not supported, return undefined.
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Extracts and parses the wallet API message carried in a deep-link URL's
|
|
54
|
+
* `request` query parameter (`dccrequest://...?request=<json>`). Returns
|
|
55
|
+
* `undefined` when the parameter is absent or its value is not valid JSON.
|
|
56
|
+
*
|
|
57
|
+
* @param options {object}
|
|
58
|
+
* @param options.url {string}
|
|
59
|
+
* @returns {Record<string, unknown> | undefined}
|
|
60
|
+
*/
|
|
61
|
+
export function parseWalletApiUrl({ url }) {
|
|
62
|
+
let messageText;
|
|
63
|
+
try {
|
|
64
|
+
messageText = new URL(url).searchParams.get('request');
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
if (messageText === null) {
|
|
70
|
+
// URL does not contain a "request" parameter.
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
// `URLSearchParams.get` has already percent-decoded the value.
|
|
75
|
+
return JSON.parse(messageText);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
console.error(`Error parsing incoming wallet API message: "${messageText}"`, err);
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Filters an incoming VCALM query set for capability (zcap) requests, returning
|
|
84
|
+
* only those. Recognizes both the canonical `AuthorizationCapabilityQuery` and
|
|
85
|
+
* the legacy `ZcapQuery` type strings.
|
|
86
|
+
*
|
|
87
|
+
* @param options {object}
|
|
88
|
+
* @param options.queries {IVPRQuery[]}
|
|
89
|
+
* @returns {{ zcapRequests?: IZcapQuery[] }}
|
|
90
|
+
*/
|
|
91
|
+
export function zcapsRequested({ queries }) {
|
|
92
|
+
const zcapRequests = queries.filter((q) => q.type === 'ZcapQuery' || q.type === 'AuthorizationCapabilityQuery');
|
|
93
|
+
if (zcapRequests.length > 0) {
|
|
94
|
+
return { zcapRequests };
|
|
95
|
+
}
|
|
96
|
+
return {};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Returns true if the message is a VPR whose only query type is
|
|
100
|
+
* `DIDAuthentication` (i.e. no credential sharing is involved).
|
|
101
|
+
*
|
|
102
|
+
* @param message {WalletApiMessage}
|
|
103
|
+
* @returns {boolean}
|
|
104
|
+
*/
|
|
105
|
+
export function isDIDAuthOnlyRequest(message) {
|
|
106
|
+
if (!('verifiablePresentationRequest' in message)) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const { query } = message.verifiablePresentationRequest;
|
|
110
|
+
const queries = Array.isArray(query) ? query : [query];
|
|
111
|
+
return (queries.length > 0 &&
|
|
112
|
+
queries.every(q => !!q && q.type === 'DIDAuthentication'));
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/request/parse.ts"],"names":[],"mappings":"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"}
|