@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,71 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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;AAiEhD;;;;;;;;;;;;;;;;;;;;;;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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
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
|
+
/** VC Data Model 2.0 context URL. */
|
|
38
|
+
const CREDENTIALS_CONTEXT_V2_URL = 'https://www.w3.org/ns/credentials/v2';
|
|
39
|
+
/** Returns true if a JSON-LD `@context` value contains the given URL. */
|
|
40
|
+
function contextIncludes(context, url) {
|
|
41
|
+
if (typeof context === 'string') {
|
|
42
|
+
return context === url;
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(context)) {
|
|
45
|
+
return context.includes(url);
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Normalizes an `acceptedCryptosuites` list to cryptosuite name strings,
|
|
51
|
+
* accepting both the VCALM `{ cryptosuite }` object form and the bare string
|
|
52
|
+
* form verifiers send in practice.
|
|
53
|
+
*
|
|
54
|
+
* @param [accepted] {IAcceptedCryptosuites}
|
|
55
|
+
* @returns {string[]}
|
|
56
|
+
*/
|
|
57
|
+
function cryptosuiteNames(accepted) {
|
|
58
|
+
if (!Array.isArray(accepted)) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
return accepted
|
|
62
|
+
.map(entry => (typeof entry === 'string' ? entry : entry?.cryptosuite))
|
|
63
|
+
.filter((name) => typeof name === 'string');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Every cryptosuite a query offers, in the order the verifier stated them. A
|
|
67
|
+
* `QueryByExample` may carry the preference on the query itself (VCALM) or
|
|
68
|
+
* inside each of its `credentialQuery` details (what verifiers send in
|
|
69
|
+
* practice); both are collected.
|
|
70
|
+
*
|
|
71
|
+
* @param query {IVPRQuery}
|
|
72
|
+
* @returns {string[]}
|
|
73
|
+
*/
|
|
74
|
+
function acceptedCryptosuitesOf(query) {
|
|
75
|
+
const onQuery = 'acceptedCryptosuites' in query
|
|
76
|
+
? cryptosuiteNames(query.acceptedCryptosuites)
|
|
77
|
+
: [];
|
|
78
|
+
if (query.type !== 'QueryByExample') {
|
|
79
|
+
return onQuery;
|
|
80
|
+
}
|
|
81
|
+
const onDetails = credentialQueriesOf(query).flatMap(({ acceptedCryptosuites }) => cryptosuiteNames(acceptedCryptosuites));
|
|
82
|
+
return [...onQuery, ...onDetails];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Decides the cryptosuite the wallet should sign a presentation with, in two
|
|
86
|
+
* tiers:
|
|
87
|
+
*
|
|
88
|
+
* 1. The explicit, spec-sanctioned signal: an `acceptedCryptosuites` preference
|
|
89
|
+
* (allowed on DIDAuthentication and QueryByExample queries, and on a
|
|
90
|
+
* QueryByExample's individual `credentialQuery` details). The verifier's
|
|
91
|
+
* stated order is honored, picking the first listed suite the wallet
|
|
92
|
+
* supports. If the verifier listed suites but none are supported, the wallet
|
|
93
|
+
* falls back to its default rather than overriding their explicit choice with
|
|
94
|
+
* the heuristic below.
|
|
95
|
+
* 2. A fallback heuristic when no `acceptedCryptosuites` is given: if a
|
|
96
|
+
* QueryByExample asks for a VC 2.0 example credential, infer the verifier
|
|
97
|
+
* wants a VC 2.0 `DataIntegrityProof` (eddsa-rdfc-2022) response.
|
|
98
|
+
*
|
|
99
|
+
* Returns `undefined` when neither tier yields a supported suite, signalling
|
|
100
|
+
* that the caller should sign with the wallet default (Ed25519Signature2020,
|
|
101
|
+
* VC 1.0).
|
|
102
|
+
*
|
|
103
|
+
* @param queries {IVPRQuery[]}
|
|
104
|
+
* @returns {string | undefined}
|
|
105
|
+
* @see https://w3c.github.io/vcalm/ -- the `acceptedCryptosuites` query field
|
|
106
|
+
*/
|
|
107
|
+
export function negotiateCryptosuite(queries) {
|
|
108
|
+
const accepted = queries.flatMap(query => acceptedCryptosuitesOf(query));
|
|
109
|
+
if (accepted.length > 0) {
|
|
110
|
+
return accepted.find(cryptosuite => SUPPORTED_CRYPTOSUITES.includes(cryptosuite));
|
|
111
|
+
}
|
|
112
|
+
// Fallback: a QueryByExample requesting a VC 2.0 example credential implies
|
|
113
|
+
// the verifier operates in the VC 2.0 data model, so respond in kind.
|
|
114
|
+
const requestsV2Example = queries.some(query => query.type === 'QueryByExample' &&
|
|
115
|
+
credentialQueriesOf(query).some(({ example }) => contextIncludes(example?.['@context'], CREDENTIALS_CONTEXT_V2_URL)));
|
|
116
|
+
return requestsV2Example ? EDDSA_RDFC_2022 : undefined;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Builds the proof suite and the VC Data Model version to use for a presentation
|
|
120
|
+
* proof. The negotiated `eddsa-rdfc-2022` cryptosuite emits a
|
|
121
|
+
* `DataIntegrityProof` and requires the VC 2.0 context (which defines
|
|
122
|
+
* `challenge`/`domain` only within the `DataIntegrityProof` scope); the default
|
|
123
|
+
* `Ed25519Signature2020` suite uses the VC 1.0 context.
|
|
124
|
+
*
|
|
125
|
+
* @param options {object}
|
|
126
|
+
* @param options.signer {ISigner}
|
|
127
|
+
* @param [options.cryptosuite] {string}
|
|
128
|
+
* @returns {{ suite: DataIntegrityProof, version: number }}
|
|
129
|
+
*/
|
|
130
|
+
export function presentationSuiteFor({ signer, cryptosuite }) {
|
|
131
|
+
if (cryptosuite === EDDSA_RDFC_2022) {
|
|
132
|
+
return {
|
|
133
|
+
suite: new DataIntegrityProof({ signer, cryptosuite: eddsaRdfc2022 }),
|
|
134
|
+
version: 2.0
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return { suite: new Ed25519Signature2020({ signer }), version: 1.0 };
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=presentationSuite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentationSuite.js","sourceRoot":"","sources":["../../src/request/presentationSuite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { IVerifiableCredential, IVPRDetails, PresentationSigner, RequestProcessors, WalletResponse } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Domain-binding check (VCALM §3.4.3 advisement): a DID-Auth `domain` MUST match
|
|
4
|
+
* the channel the request arrived on, otherwise a dishonest verifier could relay
|
|
5
|
+
* the challenge from another origin and replay the response.
|
|
6
|
+
*
|
|
7
|
+
* @param options {object}
|
|
8
|
+
* @param options.domain {string} - The `domain` from the request.
|
|
9
|
+
* @param [options.origin] {string} - The channel origin (for CHAPI,
|
|
10
|
+
* `event.credentialRequestOrigin`).
|
|
11
|
+
* @returns {boolean}
|
|
12
|
+
*/
|
|
13
|
+
export declare function domainMatchesOrigin({ domain, origin }: {
|
|
14
|
+
domain: string;
|
|
15
|
+
origin?: string;
|
|
16
|
+
}): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Processes a Verifiable Presentation Request and composes the wallet's
|
|
19
|
+
* response. Assumes the user has already consented and (for VC sharing) picked
|
|
20
|
+
* which credentials to send.
|
|
21
|
+
*
|
|
22
|
+
* @param options {object}
|
|
23
|
+
* @param options.request {IVPRDetails} - The VPR body.
|
|
24
|
+
* @param options.presentationSigner {PresentationSigner} - Authentication signer
|
|
25
|
+
* and holder DID.
|
|
26
|
+
* @param [options.selectedVCs] {IVerifiableCredential[]} - VCs the user chose to
|
|
27
|
+
* share (empty for a DID-Auth-only or zcap-only response).
|
|
28
|
+
* @param [options.credentialRequestOrigin] {string} - Channel origin, used for
|
|
29
|
+
* the domain-binding check and required by the App Connect branch.
|
|
30
|
+
* @param [options.processors] {RequestProcessors} - App-side capability /
|
|
31
|
+
* App Connect processors.
|
|
32
|
+
* @param [options.cryptosuite] {string} - Cryptosuite override; when absent it
|
|
33
|
+
* is negotiated from the request's `acceptedCryptosuites`.
|
|
34
|
+
* @param [options.vocabBaseIri] {string} - Vocabulary base IRI passed through to
|
|
35
|
+
* {@link composeVp} for embedded-grant term definitions.
|
|
36
|
+
* @returns {Promise<WalletResponse>} The response VP (and any granted zcaps), or
|
|
37
|
+
* `{}` when there is nothing to send.
|
|
38
|
+
*/
|
|
39
|
+
export declare function processRequest({ request, presentationSigner, selectedVCs, credentialRequestOrigin, processors, cryptosuite, vocabBaseIri }: {
|
|
40
|
+
request: IVPRDetails;
|
|
41
|
+
presentationSigner: PresentationSigner;
|
|
42
|
+
selectedVCs?: IVerifiableCredential[];
|
|
43
|
+
credentialRequestOrigin?: string;
|
|
44
|
+
processors?: RequestProcessors;
|
|
45
|
+
cryptosuite?: string;
|
|
46
|
+
vocabBaseIri?: string;
|
|
47
|
+
}): Promise<WalletResponse>;
|
|
48
|
+
//# sourceMappingURL=processRequest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processRequest.d.ts","sourceRoot":"","sources":["../../src/request/processRequest.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,qBAAqB,EACrB,WAAW,EAEX,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAA;AAkBnB;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,MAAM,EACP,EAAE;IACD,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAOV;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,cAAc,CAAC,EACnC,OAAO,EACP,kBAAkB,EAClB,WAAgB,EAChB,uBAAuB,EACvB,UAAU,EACV,WAAW,EACX,YAAY,EACb,EAAE;IACD,OAAO,EAAE,WAAW,CAAA;IACpB,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAA;IACrC,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GAAG,OAAO,CAAC,cAAc,CAAC,CA0E1B"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Framework-agnostic request processing: turns a classified VPR body plus the
|
|
6
|
+
* user's VC selection into a {@link WalletResponse} (a possibly-signed VP, plus
|
|
7
|
+
* any delegated zcaps). The response channel (CHAPI `respondWith`, an
|
|
8
|
+
* exchange-URL POST) stays with the caller -- this function only returns data,
|
|
9
|
+
* and assumes the user has already consented and picked which credentials to
|
|
10
|
+
* send.
|
|
11
|
+
*
|
|
12
|
+
* Ported from Freewallet's `src/lib/walletRequest/processRequest.ts` (the pure
|
|
13
|
+
* shape). The two app-specific side effects -- capability delegation and the App
|
|
14
|
+
* Connect branch -- are injected as {@link RequestProcessors} rather than
|
|
15
|
+
* imported, so this layer carries no session / grant-resolution machinery. The
|
|
16
|
+
* signer and holder DID are injected as a {@link PresentationSigner}.
|
|
17
|
+
*/
|
|
18
|
+
import { classifyRequest, queriesOf } from './classify.js';
|
|
19
|
+
import { composeVp } from './composeVp.js';
|
|
20
|
+
import { negotiateCryptosuite } from './presentationSuite.js';
|
|
21
|
+
/**
|
|
22
|
+
* Extracts the host (`host:port`) from a value that may be a full URL or a bare
|
|
23
|
+
* host / host:port. Returns undefined if it cannot be parsed.
|
|
24
|
+
*/
|
|
25
|
+
function hostOf(value) {
|
|
26
|
+
try {
|
|
27
|
+
const url = value.includes('://')
|
|
28
|
+
? new URL(value)
|
|
29
|
+
: new URL(`https://${value}`);
|
|
30
|
+
return url.host;
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.warn(`Could not parse host from "${value}":`, err);
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Domain-binding check (VCALM §3.4.3 advisement): a DID-Auth `domain` MUST match
|
|
39
|
+
* the channel the request arrived on, otherwise a dishonest verifier could relay
|
|
40
|
+
* the challenge from another origin and replay the response.
|
|
41
|
+
*
|
|
42
|
+
* @param options {object}
|
|
43
|
+
* @param options.domain {string} - The `domain` from the request.
|
|
44
|
+
* @param [options.origin] {string} - The channel origin (for CHAPI,
|
|
45
|
+
* `event.credentialRequestOrigin`).
|
|
46
|
+
* @returns {boolean}
|
|
47
|
+
*/
|
|
48
|
+
export function domainMatchesOrigin({ domain, origin }) {
|
|
49
|
+
if (!origin) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const originHost = hostOf(origin);
|
|
53
|
+
const domainHost = hostOf(domain);
|
|
54
|
+
return !!originHost && originHost === domainHost;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Processes a Verifiable Presentation Request and composes the wallet's
|
|
58
|
+
* response. Assumes the user has already consented and (for VC sharing) picked
|
|
59
|
+
* which credentials to send.
|
|
60
|
+
*
|
|
61
|
+
* @param options {object}
|
|
62
|
+
* @param options.request {IVPRDetails} - The VPR body.
|
|
63
|
+
* @param options.presentationSigner {PresentationSigner} - Authentication signer
|
|
64
|
+
* and holder DID.
|
|
65
|
+
* @param [options.selectedVCs] {IVerifiableCredential[]} - VCs the user chose to
|
|
66
|
+
* share (empty for a DID-Auth-only or zcap-only response).
|
|
67
|
+
* @param [options.credentialRequestOrigin] {string} - Channel origin, used for
|
|
68
|
+
* the domain-binding check and required by the App Connect branch.
|
|
69
|
+
* @param [options.processors] {RequestProcessors} - App-side capability /
|
|
70
|
+
* App Connect processors.
|
|
71
|
+
* @param [options.cryptosuite] {string} - Cryptosuite override; when absent it
|
|
72
|
+
* is negotiated from the request's `acceptedCryptosuites`.
|
|
73
|
+
* @param [options.vocabBaseIri] {string} - Vocabulary base IRI passed through to
|
|
74
|
+
* {@link composeVp} for embedded-grant term definitions.
|
|
75
|
+
* @returns {Promise<WalletResponse>} The response VP (and any granted zcaps), or
|
|
76
|
+
* `{}` when there is nothing to send.
|
|
77
|
+
*/
|
|
78
|
+
export async function processRequest({ request, presentationSigner, selectedVCs = [], credentialRequestOrigin, processors, cryptosuite, vocabBaseIri }) {
|
|
79
|
+
const { didAuth, zcapRequests } = classifyRequest(request);
|
|
80
|
+
const queries = queriesOf(request);
|
|
81
|
+
const { challenge, domain } = request;
|
|
82
|
+
// Honor any cryptosuite the verifier asks for (VCALM `acceptedCryptosuites`),
|
|
83
|
+
// unless the caller pinned one.
|
|
84
|
+
const negotiatedCryptosuite = cryptosuite ?? negotiateCryptosuite(queries);
|
|
85
|
+
// Security: never sign an authentication proof bound to a domain the request
|
|
86
|
+
// did not actually arrive from. Enforced whenever a `domain` is present,
|
|
87
|
+
// including a zcap-only request whose (unsigned) VP still names an origin.
|
|
88
|
+
if (domain &&
|
|
89
|
+
!domainMatchesOrigin({ domain, origin: credentialRequestOrigin })) {
|
|
90
|
+
throw new Error(`DID Auth domain "${domain}" does not match request origin ` +
|
|
91
|
+
`"${credentialRequestOrigin}".`);
|
|
92
|
+
}
|
|
93
|
+
// An App Connect request (a Freewallet-only query kind) takes its own
|
|
94
|
+
// single-round branch, handled entirely by the injected processor. The
|
|
95
|
+
// requesting origin is what the app key is bound to, so it is required.
|
|
96
|
+
// `AppConnectQuery` is a Freewallet-side extension to the VPR query union, so
|
|
97
|
+
// it is matched by its `type` string rather than a union member here.
|
|
98
|
+
const appConnectRequested = queries.some(q => q.type === 'AppConnectQuery');
|
|
99
|
+
if (appConnectRequested) {
|
|
100
|
+
if (!processors?.processAppConnect) {
|
|
101
|
+
throw new Error('An App Connect request was received but no processAppConnect ' +
|
|
102
|
+
'processor was provided.');
|
|
103
|
+
}
|
|
104
|
+
if (!credentialRequestOrigin) {
|
|
105
|
+
throw new Error('An App Connect request requires a requesting origin.');
|
|
106
|
+
}
|
|
107
|
+
return processors.processAppConnect({
|
|
108
|
+
request,
|
|
109
|
+
origin: credentialRequestOrigin,
|
|
110
|
+
challenge,
|
|
111
|
+
domain,
|
|
112
|
+
didAuthRequested: didAuth,
|
|
113
|
+
cryptosuite: negotiatedCryptosuite
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// Delegate the approved capabilities first, then embed them in the VP.
|
|
117
|
+
const zcaps = zcapRequests.length > 0 && processors?.processZcaps
|
|
118
|
+
? await processors.processZcaps({ zcapRequests })
|
|
119
|
+
: [];
|
|
120
|
+
if (!didAuth && selectedVCs.length === 0 && zcaps.length === 0) {
|
|
121
|
+
// Nothing to send: no DID Auth, no VCs, and no satisfiable grants.
|
|
122
|
+
return {};
|
|
123
|
+
}
|
|
124
|
+
const verifiablePresentation = await composeVp({
|
|
125
|
+
presentationSigner,
|
|
126
|
+
selectedVcs: selectedVCs,
|
|
127
|
+
challenge,
|
|
128
|
+
domain,
|
|
129
|
+
didAuthRequested: didAuth,
|
|
130
|
+
cryptosuite: negotiatedCryptosuite,
|
|
131
|
+
zcaps,
|
|
132
|
+
...(vocabBaseIri !== undefined && { vocabBaseIri })
|
|
133
|
+
});
|
|
134
|
+
// Return the delegated capabilities alongside the VP so the caller can log
|
|
135
|
+
// exactly what was granted from these objects, rather than reading them back
|
|
136
|
+
// off the composed VP.
|
|
137
|
+
return { verifiablePresentation, zcaps };
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=processRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processRequest.js","sourceRoot":"","sources":["../../src/request/processRequest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Shared types for the `@interop/wallet-core/request` subpath. The Verifiable
|
|
6
|
+
* Presentation Request (VPR) vocabulary itself is owned by
|
|
7
|
+
* `@interop/data-integrity-core` (its `VPR` module) and re-exported here so a
|
|
8
|
+
* request consumer imports one package; this file adds only the request-local
|
|
9
|
+
* types the app sources carried alongside that vocabulary: the CHAPI event
|
|
10
|
+
* shapes, the VC-API exchange reply shape, the classified-request profile, and
|
|
11
|
+
* the injection-seam types (`PresentationSigner`, `FetchLike`,
|
|
12
|
+
* `RequestProcessors`) that keep this layer free of any single app's session /
|
|
13
|
+
* network / consent machinery.
|
|
14
|
+
*
|
|
15
|
+
* Ported from DCW's `app/lib/walletRequestApi.ts` and Freewallet's
|
|
16
|
+
* `src/lib/walletRequest/{types,classify}.ts`.
|
|
17
|
+
*
|
|
18
|
+
* The VPR vocabulary (and the loose-shape guards in `classify` / `matching`) is
|
|
19
|
+
* imported from the `@interop/data-integrity-core/vpr` and `/guards` subpaths
|
|
20
|
+
* rather than the package root: the vocabulary was added to data-integrity-core
|
|
21
|
+
* without a version bump, so the package root can dedup onto an older cached
|
|
22
|
+
* build that predates it, whereas the subpath entry points resolve only against
|
|
23
|
+
* the current build that defines them.
|
|
24
|
+
*/
|
|
25
|
+
import type { ISigner } from '@interop/data-integrity-core';
|
|
26
|
+
import type { IVerifiableCredential, IVerifiablePresentation, IZcap } from '@interop/data-integrity-core';
|
|
27
|
+
import type { ICapabilityQueryDetail, IQueryByExample, IVPRDetails, WalletResponse } from '@interop/data-integrity-core/vpr';
|
|
28
|
+
export type { IVPRequest, IVPOffer, IIssueRequest, IExchangeInvitation, IOid4VCIOffer, IVPRDetails, IVPRInteract, IVPRQuery, IQueryByExample, ICredentialQuery, IAcceptedCryptosuites, IDIDAuthenticationQuery, IZcapQuery, ICapabilityQueryDetail, IInvocationTarget, IAllowedAction, WalletApiMessage, WalletResponse, IVpRequest, IVpOffer, IVprDetails, IVprQuery, IDidAuthenticationQuery } from '@interop/data-integrity-core/vpr';
|
|
29
|
+
export type { IVerifiableCredential, IVerifiablePresentation, IZcap } from '@interop/data-integrity-core';
|
|
30
|
+
/**
|
|
31
|
+
* The protocol handles a verifier offers alongside a CHAPI request. Only
|
|
32
|
+
* `vcapi` (and the newer `interact` meta-protocol) are acted on; `OID4VP` /
|
|
33
|
+
* `OID4VCI` are recognized but unused.
|
|
34
|
+
*/
|
|
35
|
+
export interface CHAPIProtocols {
|
|
36
|
+
vcapi?: string;
|
|
37
|
+
interact?: string;
|
|
38
|
+
OID4VP?: string;
|
|
39
|
+
OID4VCI?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Raw CHAPI credential-get event. The `VerifiablePresentation` object CHAPI
|
|
43
|
+
* hands us *is* the VPR body (`query` / `challenge` / `domain`); classification
|
|
44
|
+
* rewraps it as an `IVPRequest`. When the verifier names a `protocols` handle
|
|
45
|
+
* it sends that body empty instead, and the VPR must be fetched from the
|
|
46
|
+
* protocol exchange (see `exchangeClient.ts`).
|
|
47
|
+
*/
|
|
48
|
+
export interface CHAPIGetEvent {
|
|
49
|
+
credentialRequestOrigin: string;
|
|
50
|
+
credentialRequestOptions?: {
|
|
51
|
+
web?: {
|
|
52
|
+
VerifiablePresentation?: IVPRDetails;
|
|
53
|
+
protocols?: CHAPIProtocols;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
respondWith(promise: Promise<{
|
|
57
|
+
dataType: string;
|
|
58
|
+
data: unknown;
|
|
59
|
+
} | null>): void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Raw CHAPI credential-store event. `credential.data` is the offered payload,
|
|
63
|
+
* and `credential.dataType` names its shape: issuers may offer either a
|
|
64
|
+
* `VerifiablePresentation` wrapping the credential(s), or a bare
|
|
65
|
+
* `VerifiableCredential` (what vcplayground.org sends). An issuer that names a
|
|
66
|
+
* `protocols` handle in `credential.options` sends `data` empty instead, and
|
|
67
|
+
* the offered credentials must be fetched from the protocol exchange (see
|
|
68
|
+
* `exchangeClient.ts`).
|
|
69
|
+
*/
|
|
70
|
+
export interface CHAPIStoreEvent {
|
|
71
|
+
credentialRequestOrigin?: string;
|
|
72
|
+
credential: {
|
|
73
|
+
dataType?: string;
|
|
74
|
+
data: IVerifiablePresentation | IVerifiableCredential;
|
|
75
|
+
options?: {
|
|
76
|
+
protocols?: CHAPIProtocols;
|
|
77
|
+
recommendedHandlerOrigins?: string[];
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
respondWith(promise: Promise<{
|
|
81
|
+
dataType: string;
|
|
82
|
+
data: unknown;
|
|
83
|
+
} | null>): void;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The exchange's reply to either wallet call. A multi-step exchange answers a
|
|
87
|
+
* submitted presentation with another `verifiablePresentationRequest`; a
|
|
88
|
+
* finished one answers with nothing, or with credentials it issued, or with a
|
|
89
|
+
* `redirectUrl` for the user to land on.
|
|
90
|
+
*/
|
|
91
|
+
export interface VCAPIExchangeResponse {
|
|
92
|
+
verifiablePresentationRequest?: IVPRDetails;
|
|
93
|
+
verifiablePresentation?: IVerifiablePresentation;
|
|
94
|
+
redirectUrl?: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* A VP Request classified on independent axes: whether DID Authentication is
|
|
98
|
+
* requested, what credentials are asked for (`vcQueries`), and what capability
|
|
99
|
+
* delegations are asked for (`zcapRequests`). Any combination is valid,
|
|
100
|
+
* including zcap-only. An app that layers additional query kinds on top (e.g.
|
|
101
|
+
* Freewallet's App Connect) extends this shape with its own field.
|
|
102
|
+
*/
|
|
103
|
+
export interface WalletRequestProfile {
|
|
104
|
+
didAuth: boolean;
|
|
105
|
+
vcQueries: IQueryByExample[];
|
|
106
|
+
zcapRequests: ICapabilityQueryDetail[];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The authentication signer plus the DID to name as the VP `holder`. Each app
|
|
110
|
+
* resolves this from its own key material (DCW from the selected profile's
|
|
111
|
+
* `authentication` signer + DID; Freewallet from the KMS did:web key or the
|
|
112
|
+
* passphrase-derived root key) before handing it to the shared compose path.
|
|
113
|
+
*/
|
|
114
|
+
export interface PresentationSigner {
|
|
115
|
+
signer: ISigner;
|
|
116
|
+
holder: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Injected network transport. Defaults to `globalThis.fetch`; DCW passes its
|
|
120
|
+
* `fetchWithTimeout`, Freewallet its CORS-proxy fetch.
|
|
121
|
+
*/
|
|
122
|
+
export type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;
|
|
123
|
+
/**
|
|
124
|
+
* App-side processors injected into {@link processRequest}. Both are optional:
|
|
125
|
+
* a wallet that grants no capabilities omits `processZcaps`, and a wallet
|
|
126
|
+
* without an App Connect flow omits `processAppConnect` (the branch is then
|
|
127
|
+
* inert).
|
|
128
|
+
*/
|
|
129
|
+
export interface RequestProcessors {
|
|
130
|
+
/**
|
|
131
|
+
* Delegates the approved capabilities and returns the minted zcaps.
|
|
132
|
+
* Freewallet supplies `processZcaps(session)`; DCW supplies a no-op / `[]`.
|
|
133
|
+
*/
|
|
134
|
+
processZcaps?: (args: {
|
|
135
|
+
zcapRequests: ICapabilityQueryDetail[];
|
|
136
|
+
}) => Promise<IZcap[]>;
|
|
137
|
+
/**
|
|
138
|
+
* Handles the App Connect single-round branch (Freewallet only). Invoked when
|
|
139
|
+
* the request carries an `AppConnectQuery`; absent for DCW.
|
|
140
|
+
*/
|
|
141
|
+
processAppConnect?: (args: {
|
|
142
|
+
request: IVPRDetails;
|
|
143
|
+
origin: string;
|
|
144
|
+
challenge?: string;
|
|
145
|
+
domain?: string;
|
|
146
|
+
didAuthRequested: boolean;
|
|
147
|
+
cryptosuite?: string;
|
|
148
|
+
}) => Promise<WalletResponse>;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/request/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/request/types.ts"],"names":[],"mappings":""}
|
package/dist/sync/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,0BAA0B,CAAA;AACjC,YAAY,EACV,IAAI,EACJ,cAAc,EACd,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,EACV,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAK,EACV,IAAI,EACJ,WAAW,EACX,cAAc,EACd,OAAO,EACR,MAAM,0BAA0B,CAAA;AAEjC;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;CAClB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,0BAA0B,CAAA;AACjC,YAAY,EACV,IAAI,EACJ,cAAc,EACd,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,EACV,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAK,EACV,IAAI,EACJ,WAAW,EACX,cAAc,EACd,OAAO,EACR,MAAM,0BAA0B,CAAA;AAEjC;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;CAClB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAC1B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3E;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;CAClB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEnB;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,gFAAgF;IAChF,aAAa,IAAI,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAA;IAEpD,sCAAsC;IACtC,YAAY,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAA;IAEpC;;;;;OAKG;IACH,eAAe,CAAC,OAAO,EAAE;QACvB,SAAS,EAAE,OAAO,EAAE,CAAA;QACpB,UAAU,EAAE,cAAc,CAAA;QAC1B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;KAC3C,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjB;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEpE;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3E;;;;;OAKG;IACH,WAAW,CAAC,OAAO,EAAE;QACnB,EAAE,EAAE,MAAM,CAAA;QACV,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;QAC1B,UAAU,EAAE,gBAAgB,CAAA;KAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClB"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interop/wallet-core",
|
|
3
3
|
"description": "Shared wallet-domain logic (WAS sync engine core and wallet Space layout contracts) for Interop wallet apps.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "pnpm run clear && tsc",
|
|
@@ -41,6 +41,24 @@
|
|
|
41
41
|
"react-native": "./dist/space/index.js",
|
|
42
42
|
"import": "./dist/space/index.js",
|
|
43
43
|
"default": "./dist/space/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./identity": {
|
|
46
|
+
"types": "./dist/identity/index.d.ts",
|
|
47
|
+
"react-native": "./dist/identity/index.js",
|
|
48
|
+
"import": "./dist/identity/index.js",
|
|
49
|
+
"default": "./dist/identity/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./request": {
|
|
52
|
+
"types": "./dist/request/index.d.ts",
|
|
53
|
+
"react-native": "./dist/request/index.js",
|
|
54
|
+
"import": "./dist/request/index.js",
|
|
55
|
+
"default": "./dist/request/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./display": {
|
|
58
|
+
"types": "./dist/display/index.d.ts",
|
|
59
|
+
"react-native": "./dist/display/index.js",
|
|
60
|
+
"import": "./dist/display/index.js",
|
|
61
|
+
"default": "./dist/display/index.js"
|
|
44
62
|
}
|
|
45
63
|
},
|
|
46
64
|
"module": "dist/index.js",
|
|
@@ -48,11 +66,21 @@
|
|
|
48
66
|
"types": "dist/index.d.ts",
|
|
49
67
|
"sideEffects": false,
|
|
50
68
|
"dependencies": {
|
|
51
|
-
"@interop/
|
|
52
|
-
"@
|
|
69
|
+
"@interop/data-integrity-core": "^8.4.0",
|
|
70
|
+
"@interop/data-integrity-proof": "^3.4.2",
|
|
71
|
+
"@interop/ed25519-signature": "^7.1.4",
|
|
72
|
+
"@interop/ezcap": "^7.4.1",
|
|
73
|
+
"@interop/security-document-loader": "^9.4.4",
|
|
74
|
+
"@interop/vc": "^11.0.5",
|
|
75
|
+
"@interop/was-client": "^0.20.0",
|
|
76
|
+
"@interop/webkms-client": "^14.7.1",
|
|
77
|
+
"@interop/x25519-key-agreement-key": "^5.2.1",
|
|
78
|
+
"@scure/base": "^1.2.1",
|
|
79
|
+
"jsonpath-plus": "^10.3.0"
|
|
53
80
|
},
|
|
54
81
|
"devDependencies": {
|
|
55
82
|
"@eslint/js": "^10.0.1",
|
|
83
|
+
"@interop/ed25519-verification-key": "^8.0.3",
|
|
56
84
|
"@playwright/test": "^1.60.0",
|
|
57
85
|
"@types/node": "^26.0.1",
|
|
58
86
|
"@vitest/coverage-v8": "^4.1.7",
|