@interop/wallet-core 0.69.0 → 0.71.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 +22 -36
- package/dist/clientAnnex/ladder.d.ts +103 -57
- package/dist/clientAnnex/ladder.d.ts.map +1 -1
- package/dist/clientAnnex/ladder.js +254 -335
- package/dist/clientAnnex/ladder.js.map +1 -1
- package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/ladderAnchored.js +10 -5
- package/dist/clientAnnex/ladderAnchored.js.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts +3 -15
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.js +22 -3
- package/dist/clientAnnex/recoveryLadderAnchored.js.map +1 -1
- package/dist/clientAnnex/selfEnroll.js +1 -1
- package/dist/clientAnnex/selfEnroll.js.map +1 -1
- package/dist/clientAnnex/zcap.js +1 -1
- package/dist/clientAnnex/zcap.js.map +1 -1
- package/dist/clients/grantState.d.ts +67 -0
- package/dist/clients/grantState.d.ts.map +1 -0
- package/dist/clients/grantState.js +72 -0
- package/dist/clients/grantState.js.map +1 -0
- package/dist/clients/index.d.ts +7 -0
- package/dist/clients/index.d.ts.map +1 -1
- package/dist/clients/index.js +6 -0
- package/dist/clients/index.js.map +1 -1
- package/dist/enrollment/connectCode.d.ts +4 -3
- package/dist/enrollment/connectCode.d.ts.map +1 -1
- package/dist/enrollment/connectCode.js +4 -3
- package/dist/enrollment/connectCode.js.map +1 -1
- package/dist/enrollment/enrollment.js +1 -1
- package/dist/enrollment/enrollment.js.map +1 -1
- package/dist/enrollment/index.d.ts +2 -2
- package/dist/enrollment/index.js +2 -2
- package/dist/enrollment/onboardingInvite.d.ts +1 -1
- package/dist/enrollment/onboardingInvite.js +1 -1
- package/dist/enrollment/onboardingResponse.js +1 -1
- package/dist/index.d.ts +4 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -11
- package/dist/index.js.map +1 -1
- package/dist/keyring/index.d.ts +1 -1
- package/dist/keyring/index.js +1 -1
- package/dist/keyring/kdf.d.ts +34 -20
- package/dist/keyring/kdf.d.ts.map +1 -1
- package/dist/keyring/kdf.js +37 -26
- package/dist/keyring/kdf.js.map +1 -1
- package/dist/keys/userKey.js +1 -1
- package/dist/keys/userKey.js.map +1 -1
- package/dist/recovery/continuation.d.ts +5 -4
- package/dist/recovery/continuation.d.ts.map +1 -1
- package/dist/recovery/continuation.js +14 -13
- package/dist/recovery/continuation.js.map +1 -1
- package/dist/resourceLog/document.d.ts +10 -2
- package/dist/resourceLog/document.d.ts.map +1 -1
- package/dist/resourceLog/document.js +1 -2
- package/dist/resourceLog/document.js.map +1 -1
- package/dist/space/index.d.ts +4 -2
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +4 -2
- package/dist/space/index.js.map +1 -1
- package/dist/space/wasLink.d.ts +13 -2
- package/dist/space/wasLink.d.ts.map +1 -1
- package/dist/space/wasLink.js +28 -2
- package/dist/space/wasLink.js.map +1 -1
- package/dist/unlock/index.d.ts +1 -1
- package/dist/unlock/index.d.ts.map +1 -1
- package/dist/unlock/index.js.map +1 -1
- package/dist/unlock/standingClient.d.ts +1 -1
- package/dist/unlock/standingClient.d.ts.map +1 -1
- package/dist/unlock/standingClient.js +3 -3
- package/dist/unlock/standingClient.js.map +1 -1
- package/dist/unlock/standingWebvh.d.ts +81 -19
- package/dist/unlock/standingWebvh.d.ts.map +1 -1
- package/dist/unlock/standingWebvh.js +170 -30
- package/dist/unlock/standingWebvh.js.map +1 -1
- package/dist/webvh/did.d.ts +2 -4
- package/dist/webvh/did.d.ts.map +1 -1
- package/dist/webvh/did.js +2 -4
- package/dist/webvh/did.js.map +1 -1
- package/dist/webvh/didWebvh.d.ts +3 -2
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +2 -1
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/index.d.ts +1 -1
- package/dist/webvh/index.js +1 -1
- package/dist/webvh/revokeClient.d.ts +13 -7
- package/dist/webvh/revokeClient.d.ts.map +1 -1
- package/dist/webvh/revokeClient.js +14 -7
- package/dist/webvh/revokeClient.js.map +1 -1
- package/dist/webvh/zcap.js +1 -1
- package/dist/webvh/zcap.js.map +1 -1
- package/package.json +2 -23
- package/dist/identity/agents.d.ts +0 -100
- package/dist/identity/agents.d.ts.map +0 -1
- package/dist/identity/agents.js +0 -120
- package/dist/identity/agents.js.map +0 -1
- package/dist/identity/index.d.ts +0 -24
- package/dist/identity/index.d.ts.map +0 -1
- package/dist/identity/index.js +0 -23
- package/dist/identity/index.js.map +0 -1
- package/dist/identity/keyResolver.d.ts +0 -30
- package/dist/identity/keyResolver.d.ts.map +0 -1
- package/dist/identity/keyResolver.js +0 -25
- package/dist/identity/keyResolver.js.map +0 -1
- package/dist/request/appKey.d.ts +0 -295
- package/dist/request/appKey.d.ts.map +0 -1
- package/dist/request/appKey.js +0 -516
- package/dist/request/appKey.js.map +0 -1
- package/dist/request/capabilityRequest.d.ts +0 -41
- package/dist/request/capabilityRequest.d.ts.map +0 -1
- package/dist/request/capabilityRequest.js +0 -46
- package/dist/request/capabilityRequest.js.map +0 -1
- package/dist/request/classify.d.ts +0 -226
- package/dist/request/classify.d.ts.map +0 -1
- package/dist/request/classify.js +0 -416
- package/dist/request/classify.js.map +0 -1
- package/dist/request/composeVp.d.ts +0 -52
- package/dist/request/composeVp.d.ts.map +0 -1
- package/dist/request/composeVp.js +0 -176
- package/dist/request/composeVp.js.map +0 -1
- package/dist/request/ephemeralExchange.d.ts +0 -100
- package/dist/request/ephemeralExchange.d.ts.map +0 -1
- package/dist/request/ephemeralExchange.js +0 -230
- package/dist/request/ephemeralExchange.js.map +0 -1
- package/dist/request/exchangeClient.d.ts +0 -142
- package/dist/request/exchangeClient.d.ts.map +0 -1
- package/dist/request/exchangeClient.js +0 -241
- package/dist/request/exchangeClient.js.map +0 -1
- package/dist/request/index.d.ts +0 -59
- package/dist/request/index.d.ts.map +0 -1
- package/dist/request/index.js +0 -59
- package/dist/request/index.js.map +0 -1
- package/dist/request/interactionRequest.d.ts +0 -23
- package/dist/request/interactionRequest.d.ts.map +0 -1
- package/dist/request/interactionRequest.js +0 -46
- package/dist/request/interactionRequest.js.map +0 -1
- package/dist/request/interactionUrl.d.ts +0 -42
- package/dist/request/interactionUrl.d.ts.map +0 -1
- package/dist/request/interactionUrl.js +0 -104
- package/dist/request/interactionUrl.js.map +0 -1
- package/dist/request/matching.d.ts +0 -95
- package/dist/request/matching.d.ts.map +0 -1
- package/dist/request/matching.js +0 -205
- package/dist/request/matching.js.map +0 -1
- package/dist/request/onboarding.d.ts +0 -94
- package/dist/request/onboarding.d.ts.map +0 -1
- package/dist/request/onboarding.js +0 -167
- package/dist/request/onboarding.js.map +0 -1
- package/dist/request/parse.d.ts +0 -63
- package/dist/request/parse.d.ts.map +0 -1
- package/dist/request/parse.js +0 -153
- package/dist/request/parse.js.map +0 -1
- package/dist/request/presentationSuite.d.ts +0 -71
- package/dist/request/presentationSuite.d.ts.map +0 -1
- package/dist/request/presentationSuite.js +0 -143
- package/dist/request/presentationSuite.js.map +0 -1
- package/dist/request/processRequest.d.ts +0 -45
- package/dist/request/processRequest.d.ts.map +0 -1
- package/dist/request/processRequest.js +0 -147
- package/dist/request/processRequest.js.map +0 -1
- package/dist/request/queryPredicates.d.ts +0 -98
- package/dist/request/queryPredicates.d.ts.map +0 -1
- package/dist/request/queryPredicates.js +0 -107
- package/dist/request/queryPredicates.js.map +0 -1
- package/dist/request/types.d.ts +0 -257
- package/dist/request/types.d.ts.map +0 -1
- package/dist/request/types.js +0 -2
- package/dist/request/types.js.map +0 -1
- package/dist/request/walletInput.d.ts +0 -93
- package/dist/request/walletInput.d.ts.map +0 -1
- package/dist/request/walletInput.js +0 -179
- package/dist/request/walletInput.js.map +0 -1
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* The `WalletOnboardingQuery` transport vocabulary: the VPR half of "connect a
|
|
6
|
-
* new wallet client over an exchange". An already-enrolled client (the
|
|
7
|
-
* inviter) composes a request body carrying the query and stores it on an
|
|
8
|
-
* ephemeral exchange; a fresh wallet (the enrollee) scans the exchange's
|
|
9
|
-
* interaction URL, classifies the query here, and answers with the onboarding
|
|
10
|
-
* response envelope (`@interop/wallet-core/enrollment`).
|
|
11
|
-
*
|
|
12
|
-
* Vocabulary only -- the enrollment ceremony itself is untouched, and nothing
|
|
13
|
-
* secret crosses the channel: connect-code public halves travel one way, the
|
|
14
|
-
* account pointer and controller the other. The query carries the account's
|
|
15
|
-
* did:webvh `did`, its `spaceId` and `host` (together the account pointer),
|
|
16
|
-
* and the account controller did:key, so the enrollee locates the account
|
|
17
|
-
* without being asked for the account passphrase -- which a passkey-only
|
|
18
|
-
* account does not even have. The inviter already holds all four values.
|
|
19
|
-
*
|
|
20
|
-
* The query names the account but authorizes nothing. A holder of the QR or
|
|
21
|
-
* capability URL gains a world-readable DID log and nothing else; every act on
|
|
22
|
-
* the Space still requires zcaps they do not have, and the rendezvous server
|
|
23
|
-
* that sees the pointer is the same WAS server that hosts the Space and
|
|
24
|
-
* already knows the account DID. Injection by a URL holder remains the real
|
|
25
|
-
* threat, and remains covered by the ceremony's fingerprint / confirmation-
|
|
26
|
-
* code comparison: nothing is authorized before that human check.
|
|
27
|
-
*
|
|
28
|
-
* A wallet that predates the query type finds nothing it can satisfy in such a
|
|
29
|
-
* request (`classifyRequest` reports no DID Auth, no credential queries, and
|
|
30
|
-
* no capability requests) and refuses, rather than degrading into a partial
|
|
31
|
-
* generic flow.
|
|
32
|
-
*/
|
|
33
|
-
import { isWebvhDid } from '../webvh/did.js';
|
|
34
|
-
import { isAppConnectQuery, isWalletOnboardingQuery, isZcapQuery, parsedAbsoluteUrl, singletonQueryOf } from './queryPredicates.js';
|
|
35
|
-
/**
|
|
36
|
-
* Validates a wallet-onboarding `host` and returns its serialized form. The
|
|
37
|
-
* value must parse as an absolute URL and must be `http:` or `https:` (it is
|
|
38
|
-
* dereferenced as a WAS server base URL) and must not carry a fragment; any
|
|
39
|
-
* violation throws. Compose and classification share this one rule, so the
|
|
40
|
-
* spelling the inviter publishes is the spelling the enrollee resolves, and
|
|
41
|
-
* URLs differing only in a default port, percent-encoding case, or dot
|
|
42
|
-
* segments do not name distinct servers.
|
|
43
|
-
*
|
|
44
|
-
* There is no attested origin to compare against here -- an exchange has no
|
|
45
|
-
* CHAPI requesting origin -- so unlike an App Connect `appUrl` the check is
|
|
46
|
-
* shape only. The channel's trust comes from the point-to-point fingerprint
|
|
47
|
-
* comparison of the enrollment ceremony, not from this value.
|
|
48
|
-
*
|
|
49
|
-
* The fragment check reads the serialized URL rather than `url.hash`: a bare
|
|
50
|
-
* trailing `#` sets an empty (non-null) fragment that `hash` reports as `''`.
|
|
51
|
-
*
|
|
52
|
-
* @param options {object}
|
|
53
|
-
* @param options.host {string} - The query's `host`.
|
|
54
|
-
* @returns {string} The parsed URL's serialization.
|
|
55
|
-
*/
|
|
56
|
-
export function serializedOnboardingHost({ host }) {
|
|
57
|
-
const url = parsedAbsoluteUrl({
|
|
58
|
-
value: host,
|
|
59
|
-
notAbsoluteMessage: `A WalletOnboardingQuery "host" must be an absolute URL (got "${host}").`,
|
|
60
|
-
fragmentMessage: `A WalletOnboardingQuery "host" must not carry a fragment (got ` +
|
|
61
|
-
`"${host}").`
|
|
62
|
-
});
|
|
63
|
-
if (url.protocol !== 'https:' && url.protocol !== 'http:') {
|
|
64
|
-
throw new Error(`A WalletOnboardingQuery "host" must be an http(s) URL (got "${host}").`);
|
|
65
|
-
}
|
|
66
|
-
return url.href;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Validates the account members a `WalletOnboardingQuery` carries and returns
|
|
70
|
-
* them in the classified form: the account's did:webvh `did`, its `spaceId`,
|
|
71
|
-
* the serialized `host`, and the account controller did:key. Compose and
|
|
72
|
-
* classification share this one rule, so the two sides cannot drift.
|
|
73
|
-
*
|
|
74
|
-
* The `did` must be a did:webvh id: only a promoted account (one whose Space
|
|
75
|
-
* controller is its published did:webvh) has the world-readable log the
|
|
76
|
-
* enrollee verifies its approval from. The `controller` check is shape only
|
|
77
|
-
* (a non-empty `did:key:` string) -- it is a discovery value the enrollee
|
|
78
|
-
* stores, and the channel's trust comes from the ceremony's confirmation-code
|
|
79
|
-
* comparison, not from any member of the query.
|
|
80
|
-
*
|
|
81
|
-
* @param options {object}
|
|
82
|
-
* @param options.did {string | undefined} the account's did:webvh id.
|
|
83
|
-
* @param options.spaceId {string | undefined} the account's Space id.
|
|
84
|
-
* @param options.host {string | undefined} the WAS server base URL.
|
|
85
|
-
* @param options.controller {string | undefined} the account controller
|
|
86
|
-
* did:key.
|
|
87
|
-
* @returns {IWalletOnboardingRequest}
|
|
88
|
-
*/
|
|
89
|
-
export function validatedOnboardingAccount({ did, spaceId, host, controller }) {
|
|
90
|
-
if (!isWebvhDid(did)) {
|
|
91
|
-
throw new Error('A WalletOnboardingQuery "did" must be the account\'s did:webvh id ' +
|
|
92
|
-
`(got "${String(did)}") -- only a promoted account can onboard ` +
|
|
93
|
-
'another wallet.');
|
|
94
|
-
}
|
|
95
|
-
if (typeof spaceId !== 'string' || spaceId.length === 0) {
|
|
96
|
-
throw new Error('A WalletOnboardingQuery "spaceId" must be a non-empty string (got ' +
|
|
97
|
-
`"${String(spaceId)}").`);
|
|
98
|
-
}
|
|
99
|
-
if (typeof host !== 'string') {
|
|
100
|
-
throw new Error('A WalletOnboardingQuery is missing its host.');
|
|
101
|
-
}
|
|
102
|
-
if (typeof controller !== 'string' || !controller.startsWith('did:key:')) {
|
|
103
|
-
throw new Error('A WalletOnboardingQuery "controller" must be a did:key string (got ' +
|
|
104
|
-
`"${String(controller)}").`);
|
|
105
|
-
}
|
|
106
|
-
return {
|
|
107
|
-
host: serializedOnboardingHost({ host }),
|
|
108
|
-
did,
|
|
109
|
-
spaceId,
|
|
110
|
-
controller
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* INVITER: the VPR details body to store on the ephemeral exchange -- one
|
|
115
|
-
* `WalletOnboardingQuery` and nothing else, since the query is one mental
|
|
116
|
-
* model per exchange. The account members are validated by
|
|
117
|
-
* {@link validatedOnboardingAccount} and the `host` is stored in its
|
|
118
|
-
* serialized form ({@link serializedOnboardingHost}).
|
|
119
|
-
*
|
|
120
|
-
* @param options {object}
|
|
121
|
-
* @param options.pointer {object} the account pointer (keyring's
|
|
122
|
-
* `AccountPointer` shape: the inviter passes its session pointer straight
|
|
123
|
-
* in), whose `did` must already be the promoted did:webvh id.
|
|
124
|
-
* @param options.controller {string} the account controller did:key.
|
|
125
|
-
* @returns {IVPRDetails}
|
|
126
|
-
*/
|
|
127
|
-
export function composeWalletOnboardingRequest({ pointer, controller }) {
|
|
128
|
-
const query = {
|
|
129
|
-
type: 'WalletOnboardingQuery',
|
|
130
|
-
...validatedOnboardingAccount({ ...pointer, controller })
|
|
131
|
-
};
|
|
132
|
-
return { query: [query] };
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* ENROLLEE: extracts the wallet-onboarding request from a query set, when one
|
|
136
|
-
* is present. Like an `AppConnectQuery`, a `WalletOnboardingQuery` is one
|
|
137
|
-
* mental model per exchange: at most one may appear, and it must not be
|
|
138
|
-
* combined with `QueryByExample`, standalone capability queries, or an
|
|
139
|
-
* `AppConnectQuery` (a screen that asks the person to connect a wallet must
|
|
140
|
-
* not simultaneously ask them to share credentials or grant capabilities).
|
|
141
|
-
* Its account members must satisfy {@link validatedOnboardingAccount} (so a
|
|
142
|
-
* query missing the pointer or the controller is malformed), and its `host` is
|
|
143
|
-
* rewritten to its serialized form. Violations throw; classification-time
|
|
144
|
-
* callers surface the throw as a malformed-request state.
|
|
145
|
-
*
|
|
146
|
-
* @param options {object}
|
|
147
|
-
* @param options.queries {IVPRQuery[]}
|
|
148
|
-
* @returns {IWalletOnboardingRequest | null}
|
|
149
|
-
*/
|
|
150
|
-
export function walletOnboardingRequestOf({ queries }) {
|
|
151
|
-
const onboardingQuery = singletonQueryOf({
|
|
152
|
-
queries,
|
|
153
|
-
isSingleton: isWalletOnboardingQuery,
|
|
154
|
-
isExcluded: query => query.type === 'QueryByExample' ||
|
|
155
|
-
isZcapQuery(query) ||
|
|
156
|
-
isAppConnectQuery(query),
|
|
157
|
-
typeName: 'WalletOnboardingQuery',
|
|
158
|
-
mixedMessage: 'A WalletOnboardingQuery cannot be combined with QueryByExample, ' +
|
|
159
|
-
'standalone capability queries, or an AppConnectQuery.'
|
|
160
|
-
});
|
|
161
|
-
if (onboardingQuery === null) {
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
const { host, did, spaceId, controller } = onboardingQuery;
|
|
165
|
-
return validatedOnboardingAccount({ host, did, spaceId, controller });
|
|
166
|
-
}
|
|
167
|
-
//# sourceMappingURL=onboarding.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../src/request/onboarding.ts"],"names":[],"mappings":"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"}
|
package/dist/request/parse.d.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import type { IVPRQuery, IZcapQuery, WalletApiMessage } from './types.js';
|
|
2
|
-
export { isDIDAuthRequested as isDidAuthRequested } from './classify.js';
|
|
3
|
-
/**
|
|
4
|
-
* Whether a JSON string is a recognized wallet API message: an exchange
|
|
5
|
-
* invitation, a presentation request, a presentation offer, or an issuance
|
|
6
|
-
* request. Malformed JSON is not a message.
|
|
7
|
-
*
|
|
8
|
-
* @param text {string}
|
|
9
|
-
* @returns {boolean}
|
|
10
|
-
*/
|
|
11
|
-
export declare function isWalletApiMessage(text: string): boolean;
|
|
12
|
-
/**
|
|
13
|
-
* Classifies a parsed message object into one of the wallet API message types
|
|
14
|
-
* by its discriminating property. Returns `undefined` for an unrecognized
|
|
15
|
-
* shape. Throws when a presentation request carries more than one
|
|
16
|
-
* `DIDAuthentication` query.
|
|
17
|
-
*
|
|
18
|
-
* @param options {object}
|
|
19
|
-
* @param options.messageObject {object}
|
|
20
|
-
* @returns {WalletApiMessage | undefined}
|
|
21
|
-
*/
|
|
22
|
-
export declare function parseWalletApiMessage({ messageObject }: {
|
|
23
|
-
messageObject: object;
|
|
24
|
-
}): WalletApiMessage | undefined;
|
|
25
|
-
/**
|
|
26
|
-
* Extracts and parses the wallet API message carried in a deep-link URL's
|
|
27
|
-
* `request` query parameter (`dccrequest://...?request=<json>`). Returns
|
|
28
|
-
* `undefined` when the parameter is absent or its value is not valid JSON.
|
|
29
|
-
*
|
|
30
|
-
* @param options {object}
|
|
31
|
-
* @param options.url {string}
|
|
32
|
-
* @returns {Record<string, unknown> | undefined}
|
|
33
|
-
*/
|
|
34
|
-
export declare function parseWalletApiUrl({ url }: {
|
|
35
|
-
url: string;
|
|
36
|
-
}): Record<string, unknown> | undefined;
|
|
37
|
-
/**
|
|
38
|
-
* Filters an incoming VCALM query set for capability (zcap) requests, returning
|
|
39
|
-
* only those. Recognizes both the canonical `AuthorizationCapabilityQuery` and
|
|
40
|
-
* the legacy `ZcapQuery` type strings.
|
|
41
|
-
*
|
|
42
|
-
* @param options {object}
|
|
43
|
-
* @param options.queries {IVPRQuery[]}
|
|
44
|
-
* @returns {{ zcapRequests?: IZcapQuery[] }}
|
|
45
|
-
*/
|
|
46
|
-
export declare function zcapsRequested({ queries }: {
|
|
47
|
-
queries: IVPRQuery[];
|
|
48
|
-
}): {
|
|
49
|
-
zcapRequests?: IZcapQuery[];
|
|
50
|
-
};
|
|
51
|
-
/**
|
|
52
|
-
* Returns true if the message is a VPR whose only query type is
|
|
53
|
-
* `DIDAuthentication` (i.e. no credential sharing is involved). The query set
|
|
54
|
-
* is read through `queriesOf`, so a `null` or untyped entry is skipped here
|
|
55
|
-
* exactly as classification skips it. Throws when the query set names
|
|
56
|
-
* `DIDAuthentication` more than once, matching what classification would
|
|
57
|
-
* otherwise reject after the request was accepted.
|
|
58
|
-
*
|
|
59
|
-
* @param message {WalletApiMessage}
|
|
60
|
-
* @returns {boolean}
|
|
61
|
-
*/
|
|
62
|
-
export declare function isDIDAuthOnlyRequest(message: WalletApiMessage): boolean;
|
|
63
|
-
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/request/parse.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAKV,SAAS,EACT,UAAU,EACV,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAMnB,OAAO,EAAE,kBAAkB,IAAI,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAExE;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAexD;AAoBD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,aAAa,EACd,EAAE;IACD,aAAa,EAAE,MAAM,CAAA;CACtB,GAAG,gBAAgB,GAAG,SAAS,CAiB/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,CAMA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAUvE"}
|
package/dist/request/parse.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
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 { log } from '../log.js';
|
|
12
|
-
import { isDIDAuthRequested, isZcapQuery, queriesOf } from './classify.js';
|
|
13
|
-
// The DID-Auth query helper is spelled `isDIDAuthRequested` in `classify.ts`;
|
|
14
|
-
// DCW imported it as `isDidAuthRequested`. Both names resolve to one function.
|
|
15
|
-
export { isDIDAuthRequested as isDidAuthRequested } from './classify.js';
|
|
16
|
-
/**
|
|
17
|
-
* Whether a JSON string is a recognized wallet API message: an exchange
|
|
18
|
-
* invitation, a presentation request, a presentation offer, or an issuance
|
|
19
|
-
* request. Malformed JSON is not a message.
|
|
20
|
-
*
|
|
21
|
-
* @param text {string}
|
|
22
|
-
* @returns {boolean}
|
|
23
|
-
*/
|
|
24
|
-
export function isWalletApiMessage(text) {
|
|
25
|
-
let messageObject;
|
|
26
|
-
try {
|
|
27
|
-
messageObject = JSON.parse(text);
|
|
28
|
-
}
|
|
29
|
-
catch (_) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
return (!!messageObject &&
|
|
33
|
-
typeof messageObject === 'object' &&
|
|
34
|
-
('protocols' in messageObject ||
|
|
35
|
-
'verifiablePresentationRequest' in messageObject ||
|
|
36
|
-
'verifiablePresentation' in messageObject ||
|
|
37
|
-
'issueRequest' in messageObject));
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Rejects a presentation request whose query set names `DIDAuthentication` more
|
|
41
|
-
* than once: a single DID-Auth proof answers the request, so a duplicate is
|
|
42
|
-
* malformed. Enforced here at the parse boundary so a request that would later
|
|
43
|
-
* fail classification never reaches the consent screen as accepted.
|
|
44
|
-
*
|
|
45
|
-
* @param request {IVPRequest}
|
|
46
|
-
* @returns {void}
|
|
47
|
-
*/
|
|
48
|
-
function assertSingleDIDAuthQuery(request) {
|
|
49
|
-
const details = request.verifiablePresentationRequest;
|
|
50
|
-
if (!details || typeof details !== 'object') {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
// Throws when more than one DIDAuthentication query is present.
|
|
54
|
-
isDIDAuthRequested({ queries: queriesOf(details) });
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Classifies a parsed message object into one of the wallet API message types
|
|
58
|
-
* by its discriminating property. Returns `undefined` for an unrecognized
|
|
59
|
-
* shape. Throws when a presentation request carries more than one
|
|
60
|
-
* `DIDAuthentication` query.
|
|
61
|
-
*
|
|
62
|
-
* @param options {object}
|
|
63
|
-
* @param options.messageObject {object}
|
|
64
|
-
* @returns {WalletApiMessage | undefined}
|
|
65
|
-
*/
|
|
66
|
-
export function parseWalletApiMessage({ messageObject }) {
|
|
67
|
-
if ('protocols' in messageObject) {
|
|
68
|
-
return messageObject;
|
|
69
|
-
}
|
|
70
|
-
if ('verifiablePresentationRequest' in messageObject) {
|
|
71
|
-
const request = messageObject;
|
|
72
|
-
assertSingleDIDAuthQuery(request);
|
|
73
|
-
return request;
|
|
74
|
-
}
|
|
75
|
-
if ('verifiablePresentation' in messageObject) {
|
|
76
|
-
return messageObject;
|
|
77
|
-
}
|
|
78
|
-
if ('issueRequest' in messageObject) {
|
|
79
|
-
return messageObject;
|
|
80
|
-
}
|
|
81
|
-
// Message not recognized / not supported, return undefined.
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Extracts and parses the wallet API message carried in a deep-link URL's
|
|
86
|
-
* `request` query parameter (`dccrequest://...?request=<json>`). Returns
|
|
87
|
-
* `undefined` when the parameter is absent or its value is not valid JSON.
|
|
88
|
-
*
|
|
89
|
-
* @param options {object}
|
|
90
|
-
* @param options.url {string}
|
|
91
|
-
* @returns {Record<string, unknown> | undefined}
|
|
92
|
-
*/
|
|
93
|
-
export function parseWalletApiUrl({ url }) {
|
|
94
|
-
let messageText;
|
|
95
|
-
try {
|
|
96
|
-
messageText = new URL(url).searchParams.get('request');
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
if (messageText === null) {
|
|
102
|
-
// URL does not contain a "request" parameter.
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|
|
105
|
-
try {
|
|
106
|
-
// `URLSearchParams.get` has already percent-decoded the value.
|
|
107
|
-
return JSON.parse(messageText);
|
|
108
|
-
}
|
|
109
|
-
catch (err) {
|
|
110
|
-
log.error('Error parsing incoming wallet API message', {
|
|
111
|
-
messageText,
|
|
112
|
-
err
|
|
113
|
-
});
|
|
114
|
-
return undefined;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Filters an incoming VCALM query set for capability (zcap) requests, returning
|
|
119
|
-
* only those. Recognizes both the canonical `AuthorizationCapabilityQuery` and
|
|
120
|
-
* the legacy `ZcapQuery` type strings.
|
|
121
|
-
*
|
|
122
|
-
* @param options {object}
|
|
123
|
-
* @param options.queries {IVPRQuery[]}
|
|
124
|
-
* @returns {{ zcapRequests?: IZcapQuery[] }}
|
|
125
|
-
*/
|
|
126
|
-
export function zcapsRequested({ queries }) {
|
|
127
|
-
const zcapRequests = queries.filter(isZcapQuery);
|
|
128
|
-
if (zcapRequests.length > 0) {
|
|
129
|
-
return { zcapRequests };
|
|
130
|
-
}
|
|
131
|
-
return {};
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Returns true if the message is a VPR whose only query type is
|
|
135
|
-
* `DIDAuthentication` (i.e. no credential sharing is involved). The query set
|
|
136
|
-
* is read through `queriesOf`, so a `null` or untyped entry is skipped here
|
|
137
|
-
* exactly as classification skips it. Throws when the query set names
|
|
138
|
-
* `DIDAuthentication` more than once, matching what classification would
|
|
139
|
-
* otherwise reject after the request was accepted.
|
|
140
|
-
*
|
|
141
|
-
* @param message {WalletApiMessage}
|
|
142
|
-
* @returns {boolean}
|
|
143
|
-
*/
|
|
144
|
-
export function isDIDAuthOnlyRequest(message) {
|
|
145
|
-
if (!('verifiablePresentationRequest' in message)) {
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
assertSingleDIDAuthQuery(message);
|
|
149
|
-
const queries = queriesOf(message.verifiablePresentationRequest);
|
|
150
|
-
return (queries.length > 0 &&
|
|
151
|
-
queries.every(entry => entry.type === 'DIDAuthentication'));
|
|
152
|
-
}
|
|
153
|
-
//# sourceMappingURL=parse.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/request/parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Cryptosuite negotiation and proof-suite construction for signed Verifiable
|
|
6
|
-
* Presentations. `negotiateCryptosuite` decides which cryptosuite the wallet
|
|
7
|
-
* signs a presentation with (honoring a verifier's `acceptedCryptosuites`
|
|
8
|
-
* preference, or inferring VC 2.0 from a QueryByExample); `presentationSuiteFor`
|
|
9
|
-
* builds the matching proof suite and VC data-model version.
|
|
10
|
-
*
|
|
11
|
-
* Ported from Freewallet's `src/lib/walletRequest/presentationSuite.ts` (the
|
|
12
|
-
* superset of DCW's `app/lib/presentationSuite.ts`): it accepts both the VCALM
|
|
13
|
-
* `{ cryptosuite }` object form and the bare cryptosuite-string form verifiers
|
|
14
|
-
* send in practice, and reads `acceptedCryptosuites` from a QueryByExample's
|
|
15
|
-
* individual `credentialQuery` details as well as the query itself.
|
|
16
|
-
*/
|
|
17
|
-
import { DataIntegrityProof } from '@interop/data-integrity-proof';
|
|
18
|
-
import type { ISigner } from '@interop/data-integrity-core';
|
|
19
|
-
import type { IVPRQuery } from './types.js';
|
|
20
|
-
/**
|
|
21
|
-
* VCALM cryptosuite identifier for the modern EdDSA Data Integrity proof. This
|
|
22
|
-
* is what a verifier lists in `acceptedCryptosuites` to ask for a
|
|
23
|
-
* `DataIntegrityProof` (VC 2.0) presentation instead of the legacy default.
|
|
24
|
-
*
|
|
25
|
-
* @see https://www.w3.org/TR/vc-data-integrity/
|
|
26
|
-
*/
|
|
27
|
-
export declare const EDDSA_RDFC_2022 = "eddsa-rdfc-2022";
|
|
28
|
-
/**
|
|
29
|
-
* Decides the cryptosuite the wallet should sign a presentation with, in two
|
|
30
|
-
* tiers:
|
|
31
|
-
*
|
|
32
|
-
* 1. The explicit, spec-sanctioned signal: an `acceptedCryptosuites` preference
|
|
33
|
-
* (allowed on DIDAuthentication and QueryByExample queries, and on a
|
|
34
|
-
* QueryByExample's individual `credentialQuery` details). The verifier's
|
|
35
|
-
* stated order is honored, picking the first listed suite the wallet
|
|
36
|
-
* supports. If the verifier listed suites but none are supported, the wallet
|
|
37
|
-
* falls back to its default rather than overriding their explicit choice with
|
|
38
|
-
* the heuristic below.
|
|
39
|
-
* 2. A fallback heuristic when no `acceptedCryptosuites` is given: if a
|
|
40
|
-
* QueryByExample asks for a VC 2.0 example credential, infer the verifier
|
|
41
|
-
* wants a VC 2.0 `DataIntegrityProof` (eddsa-rdfc-2022) response.
|
|
42
|
-
*
|
|
43
|
-
* Returns `undefined` when neither tier yields a supported suite, signalling
|
|
44
|
-
* that the caller should sign with the wallet default (Ed25519Signature2020,
|
|
45
|
-
* VC 1.0).
|
|
46
|
-
*
|
|
47
|
-
* @param queries {IVPRQuery[]}
|
|
48
|
-
* @returns {string | undefined}
|
|
49
|
-
* @see https://w3c.github.io/vcalm/ -- the `acceptedCryptosuites` query field
|
|
50
|
-
*/
|
|
51
|
-
export declare function negotiateCryptosuite(queries: IVPRQuery[]): string | undefined;
|
|
52
|
-
/**
|
|
53
|
-
* Builds the proof suite and the VC Data Model version to use for a presentation
|
|
54
|
-
* proof. The negotiated `eddsa-rdfc-2022` cryptosuite emits a
|
|
55
|
-
* `DataIntegrityProof` and requires the VC 2.0 context (which defines
|
|
56
|
-
* `challenge`/`domain` only within the `DataIntegrityProof` scope); the default
|
|
57
|
-
* `Ed25519Signature2020` suite uses the VC 1.0 context.
|
|
58
|
-
*
|
|
59
|
-
* @param options {object}
|
|
60
|
-
* @param options.signer {ISigner}
|
|
61
|
-
* @param [options.cryptosuite] {string}
|
|
62
|
-
* @returns {{ suite: DataIntegrityProof, version: number }}
|
|
63
|
-
*/
|
|
64
|
-
export declare function presentationSuiteFor({ signer, cryptosuite }: {
|
|
65
|
-
signer: ISigner;
|
|
66
|
-
cryptosuite?: string;
|
|
67
|
-
}): {
|
|
68
|
-
suite: DataIntegrityProof;
|
|
69
|
-
version: number;
|
|
70
|
-
};
|
|
71
|
-
//# sourceMappingURL=presentationSuite.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"presentationSuite.d.ts","sourceRoot":"","sources":["../../src/request/presentationSuite.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAGlE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AAE3D,OAAO,KAAK,EAAyB,SAAS,EAAE,MAAM,YAAY,CAAA;AAElE;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,oBAAoB,CAAA;AAqEhD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,SAAS,CAkB7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACZ,EAAE;IACD,MAAM,EAAE,OAAO,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAQjD"}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Cryptosuite negotiation and proof-suite construction for signed Verifiable
|
|
6
|
-
* Presentations. `negotiateCryptosuite` decides which cryptosuite the wallet
|
|
7
|
-
* signs a presentation with (honoring a verifier's `acceptedCryptosuites`
|
|
8
|
-
* preference, or inferring VC 2.0 from a QueryByExample); `presentationSuiteFor`
|
|
9
|
-
* builds the matching proof suite and VC data-model version.
|
|
10
|
-
*
|
|
11
|
-
* Ported from Freewallet's `src/lib/walletRequest/presentationSuite.ts` (the
|
|
12
|
-
* superset of DCW's `app/lib/presentationSuite.ts`): it accepts both the VCALM
|
|
13
|
-
* `{ cryptosuite }` object form and the bare cryptosuite-string form verifiers
|
|
14
|
-
* send in practice, and reads `acceptedCryptosuites` from a QueryByExample's
|
|
15
|
-
* individual `credentialQuery` details as well as the query itself.
|
|
16
|
-
*/
|
|
17
|
-
import { DataIntegrityProof } from '@interop/data-integrity-proof';
|
|
18
|
-
import { Ed25519Signature2020 } from '@interop/ed25519-signature';
|
|
19
|
-
import { eddsaRdfc2022 } from '@interop/ed25519-signature/eddsa-rdfc-2022';
|
|
20
|
-
import { credentialQueriesOf } from './classify.js';
|
|
21
|
-
/**
|
|
22
|
-
* VCALM cryptosuite identifier for the modern EdDSA Data Integrity proof. This
|
|
23
|
-
* is what a verifier lists in `acceptedCryptosuites` to ask for a
|
|
24
|
-
* `DataIntegrityProof` (VC 2.0) presentation instead of the legacy default.
|
|
25
|
-
*
|
|
26
|
-
* @see https://www.w3.org/TR/vc-data-integrity/
|
|
27
|
-
*/
|
|
28
|
-
export const EDDSA_RDFC_2022 = 'eddsa-rdfc-2022';
|
|
29
|
-
/**
|
|
30
|
-
* Cryptosuites this wallet can produce for a presentation proof when a verifier
|
|
31
|
-
* offers a choice via VCALM `acceptedCryptosuites`. `Ed25519Signature2020` is
|
|
32
|
-
* deliberately absent: it is the wallet's default, used as a fallback whenever
|
|
33
|
-
* the verifier expresses no (supported) preference, for backwards compatibility
|
|
34
|
-
* with verifiers that predate cryptosuite negotiation.
|
|
35
|
-
*/
|
|
36
|
-
const SUPPORTED_CRYPTOSUITES = [EDDSA_RDFC_2022];
|
|
37
|
-
/**
|
|
38
|
-
* VC Data Model 2.0 context URL.
|
|
39
|
-
*/
|
|
40
|
-
const CREDENTIALS_CONTEXT_V2_URL = 'https://www.w3.org/ns/credentials/v2';
|
|
41
|
-
/**
|
|
42
|
-
* Returns true if a JSON-LD `@context` value contains the given URL.
|
|
43
|
-
*/
|
|
44
|
-
function contextIncludes(context, url) {
|
|
45
|
-
if (typeof context === 'string') {
|
|
46
|
-
return context === url;
|
|
47
|
-
}
|
|
48
|
-
if (Array.isArray(context)) {
|
|
49
|
-
return context.includes(url);
|
|
50
|
-
}
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Normalizes an `acceptedCryptosuites` list to cryptosuite name strings,
|
|
55
|
-
* accepting both the VCALM `{ cryptosuite }` object form and the bare string
|
|
56
|
-
* form verifiers send in practice.
|
|
57
|
-
*
|
|
58
|
-
* @param [accepted] {IAcceptedCryptosuites}
|
|
59
|
-
* @returns {string[]}
|
|
60
|
-
*/
|
|
61
|
-
function cryptosuiteNames(accepted) {
|
|
62
|
-
if (!Array.isArray(accepted)) {
|
|
63
|
-
return [];
|
|
64
|
-
}
|
|
65
|
-
return accepted
|
|
66
|
-
.map(entry => (typeof entry === 'string' ? entry : entry?.cryptosuite))
|
|
67
|
-
.filter((name) => typeof name === 'string');
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Every cryptosuite a query offers, in the order the verifier stated them. A
|
|
71
|
-
* `QueryByExample` may carry the preference on the query itself (VCALM) or
|
|
72
|
-
* inside each of its `credentialQuery` details (what verifiers send in
|
|
73
|
-
* practice); both are collected.
|
|
74
|
-
*
|
|
75
|
-
* @param query {IVPRQuery}
|
|
76
|
-
* @returns {string[]}
|
|
77
|
-
*/
|
|
78
|
-
function acceptedCryptosuitesOf(query) {
|
|
79
|
-
const onQuery = 'acceptedCryptosuites' in query
|
|
80
|
-
? cryptosuiteNames(query.acceptedCryptosuites)
|
|
81
|
-
: [];
|
|
82
|
-
if (query.type !== 'QueryByExample') {
|
|
83
|
-
return onQuery;
|
|
84
|
-
}
|
|
85
|
-
const onDetails = credentialQueriesOf(query).flatMap(({ acceptedCryptosuites }) => cryptosuiteNames(acceptedCryptosuites));
|
|
86
|
-
return [...onQuery, ...onDetails];
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Decides the cryptosuite the wallet should sign a presentation with, in two
|
|
90
|
-
* tiers:
|
|
91
|
-
*
|
|
92
|
-
* 1. The explicit, spec-sanctioned signal: an `acceptedCryptosuites` preference
|
|
93
|
-
* (allowed on DIDAuthentication and QueryByExample queries, and on a
|
|
94
|
-
* QueryByExample's individual `credentialQuery` details). The verifier's
|
|
95
|
-
* stated order is honored, picking the first listed suite the wallet
|
|
96
|
-
* supports. If the verifier listed suites but none are supported, the wallet
|
|
97
|
-
* falls back to its default rather than overriding their explicit choice with
|
|
98
|
-
* the heuristic below.
|
|
99
|
-
* 2. A fallback heuristic when no `acceptedCryptosuites` is given: if a
|
|
100
|
-
* QueryByExample asks for a VC 2.0 example credential, infer the verifier
|
|
101
|
-
* wants a VC 2.0 `DataIntegrityProof` (eddsa-rdfc-2022) response.
|
|
102
|
-
*
|
|
103
|
-
* Returns `undefined` when neither tier yields a supported suite, signalling
|
|
104
|
-
* that the caller should sign with the wallet default (Ed25519Signature2020,
|
|
105
|
-
* VC 1.0).
|
|
106
|
-
*
|
|
107
|
-
* @param queries {IVPRQuery[]}
|
|
108
|
-
* @returns {string | undefined}
|
|
109
|
-
* @see https://w3c.github.io/vcalm/ -- the `acceptedCryptosuites` query field
|
|
110
|
-
*/
|
|
111
|
-
export function negotiateCryptosuite(queries) {
|
|
112
|
-
const accepted = queries.flatMap(query => acceptedCryptosuitesOf(query));
|
|
113
|
-
if (accepted.length > 0) {
|
|
114
|
-
return accepted.find(cryptosuite => SUPPORTED_CRYPTOSUITES.includes(cryptosuite));
|
|
115
|
-
}
|
|
116
|
-
// Fallback: a QueryByExample requesting a VC 2.0 example credential implies
|
|
117
|
-
// the verifier operates in the VC 2.0 data model, so respond in kind.
|
|
118
|
-
const requestsV2Example = queries.some(query => query.type === 'QueryByExample' &&
|
|
119
|
-
credentialQueriesOf(query).some(({ example }) => contextIncludes(example?.['@context'], CREDENTIALS_CONTEXT_V2_URL)));
|
|
120
|
-
return requestsV2Example ? EDDSA_RDFC_2022 : undefined;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Builds the proof suite and the VC Data Model version to use for a presentation
|
|
124
|
-
* proof. The negotiated `eddsa-rdfc-2022` cryptosuite emits a
|
|
125
|
-
* `DataIntegrityProof` and requires the VC 2.0 context (which defines
|
|
126
|
-
* `challenge`/`domain` only within the `DataIntegrityProof` scope); the default
|
|
127
|
-
* `Ed25519Signature2020` suite uses the VC 1.0 context.
|
|
128
|
-
*
|
|
129
|
-
* @param options {object}
|
|
130
|
-
* @param options.signer {ISigner}
|
|
131
|
-
* @param [options.cryptosuite] {string}
|
|
132
|
-
* @returns {{ suite: DataIntegrityProof, version: number }}
|
|
133
|
-
*/
|
|
134
|
-
export function presentationSuiteFor({ signer, cryptosuite }) {
|
|
135
|
-
if (cryptosuite === EDDSA_RDFC_2022) {
|
|
136
|
-
return {
|
|
137
|
-
suite: new DataIntegrityProof({ signer, cryptosuite: eddsaRdfc2022 }),
|
|
138
|
-
version: 2.0
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
return { suite: new Ed25519Signature2020({ signer }), version: 1.0 };
|
|
142
|
-
}
|
|
143
|
-
//# sourceMappingURL=presentationSuite.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"presentationSuite.js","sourceRoot":"","sources":["../../src/request/presentationSuite.ts"],"names":[],"mappings":"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"}
|