@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.
Files changed (115) hide show
  1. package/README.md +27 -3
  2. package/dist/display/alignment.d.ts +49 -0
  3. package/dist/display/alignment.d.ts.map +1 -0
  4. package/dist/display/alignment.js +114 -0
  5. package/dist/display/alignment.js.map +1 -0
  6. package/dist/display/credentialName.d.ts +42 -0
  7. package/dist/display/credentialName.d.ts.map +1 -0
  8. package/dist/display/credentialName.js +106 -0
  9. package/dist/display/credentialName.js.map +1 -0
  10. package/dist/display/displayFields.d.ts +55 -0
  11. package/dist/display/displayFields.d.ts.map +1 -0
  12. package/dist/display/displayFields.js +136 -0
  13. package/dist/display/displayFields.js.map +1 -0
  14. package/dist/display/evidence.d.ts +44 -0
  15. package/dist/display/evidence.d.ts.map +1 -0
  16. package/dist/display/evidence.js +65 -0
  17. package/dist/display/evidence.js.map +1 -0
  18. package/dist/display/image.d.ts +18 -0
  19. package/dist/display/image.d.ts.map +1 -0
  20. package/dist/display/image.js +23 -0
  21. package/dist/display/image.js.map +1 -0
  22. package/dist/display/index.d.ts +38 -0
  23. package/dist/display/index.d.ts.map +1 -0
  24. package/dist/display/index.js +32 -0
  25. package/dist/display/index.js.map +1 -0
  26. package/dist/display/issuer.d.ts +97 -0
  27. package/dist/display/issuer.d.ts.map +1 -0
  28. package/dist/display/issuer.js +126 -0
  29. package/dist/display/issuer.js.map +1 -0
  30. package/dist/display/obv3.d.ts +77 -0
  31. package/dist/display/obv3.d.ts.map +1 -0
  32. package/dist/display/obv3.js +127 -0
  33. package/dist/display/obv3.js.map +1 -0
  34. package/dist/display/parse.d.ts +62 -0
  35. package/dist/display/parse.d.ts.map +1 -0
  36. package/dist/display/parse.js +100 -0
  37. package/dist/display/parse.js.map +1 -0
  38. package/dist/display/subject.d.ts +75 -0
  39. package/dist/display/subject.d.ts.map +1 -0
  40. package/dist/display/subject.js +122 -0
  41. package/dist/display/subject.js.map +1 -0
  42. package/dist/display/text.d.ts +42 -0
  43. package/dist/display/text.d.ts.map +1 -0
  44. package/dist/display/text.js +62 -0
  45. package/dist/display/text.js.map +1 -0
  46. package/dist/display/types.d.ts +55 -0
  47. package/dist/display/types.d.ts.map +1 -0
  48. package/dist/display/types.js +41 -0
  49. package/dist/display/types.js.map +1 -0
  50. package/dist/display/validity.d.ts +51 -0
  51. package/dist/display/validity.d.ts.map +1 -0
  52. package/dist/display/validity.js +51 -0
  53. package/dist/display/validity.js.map +1 -0
  54. package/dist/display/verificationView.d.ts +101 -0
  55. package/dist/display/verificationView.d.ts.map +1 -0
  56. package/dist/display/verificationView.js +199 -0
  57. package/dist/display/verificationView.js.map +1 -0
  58. package/dist/identity/agents.d.ts +68 -0
  59. package/dist/identity/agents.d.ts.map +1 -0
  60. package/dist/identity/agents.js +95 -0
  61. package/dist/identity/agents.js.map +1 -0
  62. package/dist/identity/index.d.ts +20 -0
  63. package/dist/identity/index.d.ts.map +1 -0
  64. package/dist/identity/index.js +19 -0
  65. package/dist/identity/index.js.map +1 -0
  66. package/dist/identity/keyResolver.d.ts +30 -0
  67. package/dist/identity/keyResolver.d.ts.map +1 -0
  68. package/dist/identity/keyResolver.js +25 -0
  69. package/dist/identity/keyResolver.js.map +1 -0
  70. package/dist/index.d.ts +14 -2
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +14 -2
  73. package/dist/index.js.map +1 -1
  74. package/dist/request/classify.d.ts +112 -0
  75. package/dist/request/classify.d.ts.map +1 -0
  76. package/dist/request/classify.js +210 -0
  77. package/dist/request/classify.js.map +1 -0
  78. package/dist/request/composeVp.d.ts +52 -0
  79. package/dist/request/composeVp.d.ts.map +1 -0
  80. package/dist/request/composeVp.js +177 -0
  81. package/dist/request/composeVp.js.map +1 -0
  82. package/dist/request/exchangeClient.d.ts +165 -0
  83. package/dist/request/exchangeClient.d.ts.map +1 -0
  84. package/dist/request/exchangeClient.js +212 -0
  85. package/dist/request/exchangeClient.js.map +1 -0
  86. package/dist/request/index.d.ts +35 -0
  87. package/dist/request/index.d.ts.map +1 -0
  88. package/dist/request/index.js +35 -0
  89. package/dist/request/index.js.map +1 -0
  90. package/dist/request/interactionUrl.d.ts +53 -0
  91. package/dist/request/interactionUrl.d.ts.map +1 -0
  92. package/dist/request/interactionUrl.js +83 -0
  93. package/dist/request/interactionUrl.js.map +1 -0
  94. package/dist/request/matching.d.ts +69 -0
  95. package/dist/request/matching.d.ts.map +1 -0
  96. package/dist/request/matching.js +183 -0
  97. package/dist/request/matching.js.map +1 -0
  98. package/dist/request/parse.d.ts +68 -0
  99. package/dist/request/parse.d.ts.map +1 -0
  100. package/dist/request/parse.js +114 -0
  101. package/dist/request/parse.js.map +1 -0
  102. package/dist/request/presentationSuite.d.ts +71 -0
  103. package/dist/request/presentationSuite.d.ts.map +1 -0
  104. package/dist/request/presentationSuite.js +139 -0
  105. package/dist/request/presentationSuite.js.map +1 -0
  106. package/dist/request/processRequest.d.ts +48 -0
  107. package/dist/request/processRequest.d.ts.map +1 -0
  108. package/dist/request/processRequest.js +139 -0
  109. package/dist/request/processRequest.js.map +1 -0
  110. package/dist/request/types.d.ts +150 -0
  111. package/dist/request/types.d.ts.map +1 -0
  112. package/dist/request/types.js +2 -0
  113. package/dist/request/types.js.map +1 -0
  114. package/dist/sync/types.d.ts.map +1 -1
  115. package/package.json +31 -3
@@ -0,0 +1,30 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * A single-key `IKeyResolver` factory. Wallet key agreement happens against one
6
+ * known KAK at a time (for example the vault KAK for the data identity, or an
7
+ * unlock KAK for a keyring), so the resolver only ever needs to answer for that
8
+ * one key. Any other key id is an error.
9
+ */
10
+ import type { IKeyResolver } from '@interop/data-integrity-core';
11
+ /**
12
+ * Builds an `IKeyResolver` that resolves exactly one key -- the supplied key
13
+ * agreement key -- and throws for any other id.
14
+ *
15
+ * @param options {object}
16
+ * @param options.keyAgreementKey {object} the one KAK this resolver answers
17
+ * for; only its `id`, `type`, and `publicKeyMultibase` are read
18
+ * @param [options.keyAgreementKey.id] {string}
19
+ * @param [options.keyAgreementKey.type] {string}
20
+ * @param [options.keyAgreementKey.publicKeyMultibase] {string}
21
+ * @returns {IKeyResolver}
22
+ */
23
+ export declare function singleKeyResolver({ keyAgreementKey }: {
24
+ keyAgreementKey: {
25
+ id?: string;
26
+ type?: string;
27
+ publicKeyMultibase?: string;
28
+ };
29
+ }): IKeyResolver;
30
+ //# sourceMappingURL=keyResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyResolver.d.ts","sourceRoot":"","sources":["../../src/identity/keyResolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAEhE;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,eAAe,EAChB,EAAE;IACD,eAAe,EAAE;QACf,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,kBAAkB,CAAC,EAAE,MAAM,CAAA;KAC5B,CAAA;CACF,GAAG,YAAY,CAWf"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Builds an `IKeyResolver` that resolves exactly one key -- the supplied key
3
+ * agreement key -- and throws for any other id.
4
+ *
5
+ * @param options {object}
6
+ * @param options.keyAgreementKey {object} the one KAK this resolver answers
7
+ * for; only its `id`, `type`, and `publicKeyMultibase` are read
8
+ * @param [options.keyAgreementKey.id] {string}
9
+ * @param [options.keyAgreementKey.type] {string}
10
+ * @param [options.keyAgreementKey.publicKeyMultibase] {string}
11
+ * @returns {IKeyResolver}
12
+ */
13
+ export function singleKeyResolver({ keyAgreementKey }) {
14
+ return async ({ id }) => {
15
+ if (id !== keyAgreementKey.id) {
16
+ throw new Error(`Unknown key id "${id}".`);
17
+ }
18
+ return {
19
+ id: keyAgreementKey.id,
20
+ type: keyAgreementKey.type,
21
+ publicKeyMultibase: keyAgreementKey.publicKeyMultibase
22
+ };
23
+ };
24
+ }
25
+ //# sourceMappingURL=keyResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyResolver.js","sourceRoot":"","sources":["../../src/identity/keyResolver.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAChC,eAAe,EAOhB;IACC,OAAO,KAAK,EAAE,EAAE,EAAE,EAAmB,EAAE,EAAE;QACvC,IAAI,EAAE,KAAK,eAAe,CAAC,EAAE,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAA;QAC5C,CAAC;QACD,OAAO;YACL,EAAE,EAAE,eAAe,CAAC,EAAE;YACtB,IAAI,EAAE,eAAe,CAAC,IAAI;YAC1B,kBAAkB,EAAE,eAAe,CAAC,kBAAkB;SACvD,CAAA;IACH,CAAC,CAAA;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,12 +3,24 @@
3
3
  */
4
4
  /**
5
5
  * `@interop/wallet-core` -- shared wallet-domain logic for Interop wallet apps.
6
- * The two subpaths are canonical and can be imported directly:
6
+ * The subpaths are canonical and can be imported directly:
7
7
  *
8
8
  * - `@interop/wallet-core/sync` -- the WAS replication engine core.
9
9
  * - `@interop/wallet-core/space` -- the wallet Space layout contract.
10
+ * - `@interop/wallet-core/identity` -- the WAS identity derivation
11
+ * (`agentsFromSecret` / `agentsFromSeed`, `singleKeyResolver`) both wallet
12
+ * apps must perform byte-for-byte identically.
13
+ * - `@interop/wallet-core/request` -- wallet-request / exchange protocol
14
+ * handling (classification and parsing, QueryByExample matching, cryptosuite
15
+ * negotiation, VP composition, the VC-API exchange client, and VCALM
16
+ * `interaction:` URL handling).
17
+ * - `@interop/wallet-core/display` -- pure VC derivation / display helpers and
18
+ * credential input parsing (raw values out; formatting stays in the UI).
10
19
  *
11
- * This root re-exports both for convenience.
20
+ * This root re-exports `sync` and `space` for convenience. `identity`,
21
+ * `request`, and `display` are deliberately NOT re-exported here, so plaintext
22
+ * consumers of the root never pull the signing / KMS / document-loader
23
+ * dependency graph (the was-client subpath-isolation pattern).
12
24
  */
13
25
  export * from './sync/index.js';
14
26
  export * from './space/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;GAQG;AACH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,kBAAkB,CAAA"}
package/dist/index.js CHANGED
@@ -3,12 +3,24 @@
3
3
  */
4
4
  /**
5
5
  * `@interop/wallet-core` -- shared wallet-domain logic for Interop wallet apps.
6
- * The two subpaths are canonical and can be imported directly:
6
+ * The subpaths are canonical and can be imported directly:
7
7
  *
8
8
  * - `@interop/wallet-core/sync` -- the WAS replication engine core.
9
9
  * - `@interop/wallet-core/space` -- the wallet Space layout contract.
10
+ * - `@interop/wallet-core/identity` -- the WAS identity derivation
11
+ * (`agentsFromSecret` / `agentsFromSeed`, `singleKeyResolver`) both wallet
12
+ * apps must perform byte-for-byte identically.
13
+ * - `@interop/wallet-core/request` -- wallet-request / exchange protocol
14
+ * handling (classification and parsing, QueryByExample matching, cryptosuite
15
+ * negotiation, VP composition, the VC-API exchange client, and VCALM
16
+ * `interaction:` URL handling).
17
+ * - `@interop/wallet-core/display` -- pure VC derivation / display helpers and
18
+ * credential input parsing (raw values out; formatting stays in the UI).
10
19
  *
11
- * This root re-exports both for convenience.
20
+ * This root re-exports `sync` and `space` for convenience. `identity`,
21
+ * `request`, and `display` are deliberately NOT re-exported here, so plaintext
22
+ * consumers of the root never pull the signing / KMS / document-loader
23
+ * dependency graph (the was-client subpath-isolation pattern).
12
24
  */
13
25
  export * from './sync/index.js';
14
26
  export * from './space/index.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;GAQG;AACH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,kBAAkB,CAAA"}
@@ -0,0 +1,112 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * Classification of incoming VC API messages: turns a raw CHAPI event (or a QR
6
+ * / pasted payload) into a typed `IVPRequest` / `IVPOffer`, and provides the
7
+ * helpers used to dispatch on what was actually asked for (VC sharing, DID
8
+ * Authentication, capability delegation, or a combination).
9
+ *
10
+ * Ported from Freewallet's `src/lib/walletRequest/classify.ts` (the superset of
11
+ * DCW's `app/lib/exchanges.ts` / `walletRequestApi.ts` dispatch helpers). The
12
+ * App Connect query kind is a Freewallet-only extension and stays app-side; the
13
+ * shared classifier covers the three VPR-spec query types.
14
+ */
15
+ import type { CHAPIStoreEvent, ICapabilityQueryDetail, ICredentialQuery, IQueryByExample, IVPOffer, IVPRequest, IVPRDetails, IVPRQuery, IVerifiableCredential, IVerifiablePresentation, WalletRequestProfile } from './types.js';
16
+ import type { CHAPIGetEvent } from './types.js';
17
+ /**
18
+ * The Verifiable Credentials carried by a presentation, normalized to an array.
19
+ *
20
+ * @param presentation {IVerifiablePresentation}
21
+ * @returns {IVerifiableCredential[]}
22
+ */
23
+ export declare function credentialsOf(presentation: IVerifiablePresentation): IVerifiableCredential[];
24
+ /**
25
+ * Wraps a CHAPI get event as an `IVPRequest`.
26
+ *
27
+ * @param event {CHAPIGetEvent}
28
+ * @returns {IVPRequest}
29
+ */
30
+ export declare function classifyCHAPIGetEvent(event: CHAPIGetEvent): IVPRequest;
31
+ /**
32
+ * Wraps a CHAPI store event as an `IVPOffer`. A bare offered credential is
33
+ * wrapped in an unsigned presentation, so downstream code always sees a VP.
34
+ *
35
+ * @param event {CHAPIStoreEvent}
36
+ * @returns {IVPOffer}
37
+ */
38
+ export declare function classifyCHAPIStoreEvent(event: CHAPIStoreEvent): IVPOffer;
39
+ /**
40
+ * Returns true if the query set contains a `DIDAuthentication` query. Throws if
41
+ * more than one is present -- a single DID-Auth proof answers the request.
42
+ *
43
+ * @param options {object}
44
+ * @param options.queries {IVPRQuery[]}
45
+ * @returns {boolean}
46
+ */
47
+ export declare function isDIDAuthRequested({ queries }: {
48
+ queries: IVPRQuery[];
49
+ }): boolean;
50
+ /**
51
+ * Normalizes a VPR's `query` (which may be a single object or an array) to an
52
+ * array, dropping anything that is not a typed query object. A VPR body can
53
+ * legitimately carry no queries at all -- a CHAPI request that names a
54
+ * `protocols` exchange sends an empty body -- so callers get an empty array
55
+ * rather than an array holding `undefined`.
56
+ *
57
+ * @param request {IVPRDetails}
58
+ * @returns {IVPRQuery[]}
59
+ */
60
+ export declare function queriesOf(request: IVPRDetails): IVPRQuery[];
61
+ /**
62
+ * Normalizes a `QueryByExample`'s `credentialQuery` (a single detail object or
63
+ * an array of them) to an array.
64
+ *
65
+ * @param query {IQueryByExample}
66
+ * @returns {ICredentialQuery[]}
67
+ */
68
+ export declare function credentialQueriesOf(query: IQueryByExample): ICredentialQuery[];
69
+ /**
70
+ * Collects the requested capabilities from a query set: filters the two zcap
71
+ * query type strings (`AuthorizationCapabilityQuery` canonical, `ZcapQuery`
72
+ * legacy alias), normalizes each `capabilityQuery` (object or array) to an
73
+ * array, and flattens. A zcap query whose `capabilityQuery` is missing or not
74
+ * an object is malformed -- there is nothing to ask consent for -- so it throws
75
+ * rather than letting an `undefined` descriptor reach grant resolution;
76
+ * classification-time callers surface the throw as a malformed-request state.
77
+ *
78
+ * @param queries {IVPRQuery[]}
79
+ * @returns {ICapabilityQueryDetail[]}
80
+ */
81
+ export declare function zcapQueriesOf(queries: IVPRQuery[]): ICapabilityQueryDetail[];
82
+ /**
83
+ * Classifies a VPR body onto the independent axes the consent screen and
84
+ * response assembly work from: whether DID Authentication is requested, and
85
+ * separately the credential (`QueryByExample`) and capability
86
+ * (`AuthorizationCapabilityQuery` / `ZcapQuery`) content asked for. Any
87
+ * combination is valid, including zcap-only.
88
+ *
89
+ * @param request {IVPRDetails}
90
+ * @returns {WalletRequestProfile}
91
+ */
92
+ export declare function classifyRequest(request: IVPRDetails): WalletRequestProfile;
93
+ /**
94
+ * Whether a classified request is DID-Authentication *only*: it asks the wallet
95
+ * to prove control of its DID and nothing else (no credential queries, no
96
+ * capability requests). Derived from the profile so a popup's restore fast-path
97
+ * and its render both dispatch on the one predicate.
98
+ *
99
+ * @param profile {WalletRequestProfile}
100
+ * @returns {boolean}
101
+ */
102
+ export declare function isDidAuthOnly(profile: WalletRequestProfile): boolean;
103
+ /**
104
+ * Returns true if the wallet can satisfy the DID method a `DIDAuthentication`
105
+ * query constrains to. A wallet holding only `did:key` can satisfy a request
106
+ * that lists `key` among `acceptedMethods` or omits the constraint entirely.
107
+ *
108
+ * @param queries {IVPRQuery[]}
109
+ * @returns {boolean}
110
+ */
111
+ export declare function didAuthMethodSupported(queries: IVPRQuery[]): boolean;
112
+ //# sourceMappingURL=classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/request/classify.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAEhB,eAAe,EACf,QAAQ,EACR,UAAU,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,uBAAuB,EAEvB,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AA4D/C;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,uBAAuB,GACpC,qBAAqB,EAAE,CAQzB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,CAYtE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,QAAQ,CAKxE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACR,EAAE;IACD,OAAO,EAAE,SAAS,EAAE,CAAA;CACrB,GAAG,OAAO,CAMV;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,EAAE,CAS3D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,GACrB,gBAAgB,EAAE,CAMpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,sBAAsB,EAAE,CAoB5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,oBAAoB,CAS1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,OAAO,CAQpE"}
@@ -0,0 +1,210 @@
1
+ import { typeArray } from '@interop/data-integrity-core/guards';
2
+ const VC_1_CONTEXT_URL = 'https://www.w3.org/2018/credentials/v1';
3
+ const VC_2_CONTEXT_URL = 'https://www.w3.org/ns/credentials/v2';
4
+ /**
5
+ * Wraps a bare Verifiable Credential in an unsigned Verifiable Presentation,
6
+ * matching the credential's VC data model version so the presentation's
7
+ * `@context` stays coherent with the credential it carries.
8
+ *
9
+ * @param credential {IVerifiableCredential}
10
+ * @returns {IVerifiablePresentation}
11
+ */
12
+ function presentationWrapping(credential) {
13
+ const contexts = credential['@context'];
14
+ const contextArray = Array.isArray(contexts) ? contexts : [contexts];
15
+ const isV2 = contextArray.includes(VC_2_CONTEXT_URL);
16
+ return {
17
+ '@context': [isV2 ? VC_2_CONTEXT_URL : VC_1_CONTEXT_URL],
18
+ type: ['VerifiablePresentation'],
19
+ verifiableCredential: [credential]
20
+ };
21
+ }
22
+ /**
23
+ * The offered payload as a Verifiable Presentation: passed through when the
24
+ * issuer already offered one, and wrapped when it offered a bare Verifiable
25
+ * Credential.
26
+ *
27
+ * @param credential {CHAPIStoreEvent['credential']}
28
+ * @returns {IVerifiablePresentation}
29
+ */
30
+ function offeredPresentation({ dataType, data }) {
31
+ const types = typeArray(data?.type);
32
+ const isPresentation = dataType === 'VerifiablePresentation' ||
33
+ types.includes('VerifiablePresentation') ||
34
+ 'verifiableCredential' in (data ?? {});
35
+ if (isPresentation) {
36
+ return data;
37
+ }
38
+ if (dataType === 'VerifiableCredential' ||
39
+ types.includes('VerifiableCredential')) {
40
+ return presentationWrapping(data);
41
+ }
42
+ throw new Error(`CHAPI store event offered an unrecognized payload (dataType: ${dataType ?? 'undefined'}, type: ${JSON.stringify(types)}).`);
43
+ }
44
+ /**
45
+ * The Verifiable Credentials carried by a presentation, normalized to an array.
46
+ *
47
+ * @param presentation {IVerifiablePresentation}
48
+ * @returns {IVerifiableCredential[]}
49
+ */
50
+ export function credentialsOf(presentation) {
51
+ const { verifiableCredential } = presentation;
52
+ if (!verifiableCredential) {
53
+ return [];
54
+ }
55
+ return Array.isArray(verifiableCredential)
56
+ ? verifiableCredential
57
+ : [verifiableCredential];
58
+ }
59
+ /**
60
+ * Wraps a CHAPI get event as an `IVPRequest`.
61
+ *
62
+ * @param event {CHAPIGetEvent}
63
+ * @returns {IVPRequest}
64
+ */
65
+ export function classifyCHAPIGetEvent(event) {
66
+ const verifiablePresentationRequest = event.credentialRequestOptions?.web?.VerifiablePresentation;
67
+ if (!verifiablePresentationRequest) {
68
+ throw new Error('CHAPI get event is missing a VerifiablePresentation request.');
69
+ }
70
+ return {
71
+ verifiablePresentationRequest,
72
+ credentialRequestOrigin: event.credentialRequestOrigin
73
+ };
74
+ }
75
+ /**
76
+ * Wraps a CHAPI store event as an `IVPOffer`. A bare offered credential is
77
+ * wrapped in an unsigned presentation, so downstream code always sees a VP.
78
+ *
79
+ * @param event {CHAPIStoreEvent}
80
+ * @returns {IVPOffer}
81
+ */
82
+ export function classifyCHAPIStoreEvent(event) {
83
+ return {
84
+ verifiablePresentation: offeredPresentation(event.credential),
85
+ credentialRequestOrigin: event.credentialRequestOrigin
86
+ };
87
+ }
88
+ /**
89
+ * Returns true if the query set contains a `DIDAuthentication` query. Throws if
90
+ * more than one is present -- a single DID-Auth proof answers the request.
91
+ *
92
+ * @param options {object}
93
+ * @param options.queries {IVPRQuery[]}
94
+ * @returns {boolean}
95
+ */
96
+ export function isDIDAuthRequested({ queries }) {
97
+ const didAuthRequests = queries.filter(q => q.type === 'DIDAuthentication');
98
+ if (didAuthRequests.length > 1) {
99
+ throw new Error('More than one DIDAuthentication request found, exiting.');
100
+ }
101
+ return didAuthRequests.length === 1;
102
+ }
103
+ /**
104
+ * Normalizes a VPR's `query` (which may be a single object or an array) to an
105
+ * array, dropping anything that is not a typed query object. A VPR body can
106
+ * legitimately carry no queries at all -- a CHAPI request that names a
107
+ * `protocols` exchange sends an empty body -- so callers get an empty array
108
+ * rather than an array holding `undefined`.
109
+ *
110
+ * @param request {IVPRDetails}
111
+ * @returns {IVPRQuery[]}
112
+ */
113
+ export function queriesOf(request) {
114
+ const { query } = request;
115
+ const queries = Array.isArray(query) ? query : [query];
116
+ return queries.filter((entry) => !!entry &&
117
+ typeof entry === 'object' &&
118
+ typeof entry.type === 'string');
119
+ }
120
+ /**
121
+ * Normalizes a `QueryByExample`'s `credentialQuery` (a single detail object or
122
+ * an array of them) to an array.
123
+ *
124
+ * @param query {IQueryByExample}
125
+ * @returns {ICredentialQuery[]}
126
+ */
127
+ export function credentialQueriesOf(query) {
128
+ const { credentialQuery } = query;
129
+ if (!credentialQuery) {
130
+ return [];
131
+ }
132
+ return Array.isArray(credentialQuery) ? credentialQuery : [credentialQuery];
133
+ }
134
+ /**
135
+ * Collects the requested capabilities from a query set: filters the two zcap
136
+ * query type strings (`AuthorizationCapabilityQuery` canonical, `ZcapQuery`
137
+ * legacy alias), normalizes each `capabilityQuery` (object or array) to an
138
+ * array, and flattens. A zcap query whose `capabilityQuery` is missing or not
139
+ * an object is malformed -- there is nothing to ask consent for -- so it throws
140
+ * rather than letting an `undefined` descriptor reach grant resolution;
141
+ * classification-time callers surface the throw as a malformed-request state.
142
+ *
143
+ * @param queries {IVPRQuery[]}
144
+ * @returns {ICapabilityQueryDetail[]}
145
+ */
146
+ export function zcapQueriesOf(queries) {
147
+ return queries
148
+ .filter((query) => query.type === 'AuthorizationCapabilityQuery' ||
149
+ query.type === 'ZcapQuery')
150
+ .flatMap(({ type, capabilityQuery }) => {
151
+ const detailEntries = Array.isArray(capabilityQuery)
152
+ ? capabilityQuery
153
+ : [capabilityQuery];
154
+ for (const detail of detailEntries) {
155
+ if (!detail || typeof detail !== 'object') {
156
+ throw new Error(`A "${type}" query is missing its capabilityQuery detail.`);
157
+ }
158
+ }
159
+ return detailEntries;
160
+ });
161
+ }
162
+ /**
163
+ * Classifies a VPR body onto the independent axes the consent screen and
164
+ * response assembly work from: whether DID Authentication is requested, and
165
+ * separately the credential (`QueryByExample`) and capability
166
+ * (`AuthorizationCapabilityQuery` / `ZcapQuery`) content asked for. Any
167
+ * combination is valid, including zcap-only.
168
+ *
169
+ * @param request {IVPRDetails}
170
+ * @returns {WalletRequestProfile}
171
+ */
172
+ export function classifyRequest(request) {
173
+ const queries = queriesOf(request);
174
+ return {
175
+ didAuth: isDIDAuthRequested({ queries }),
176
+ vcQueries: queries.filter((query) => query.type === 'QueryByExample'),
177
+ zcapRequests: zcapQueriesOf(queries)
178
+ };
179
+ }
180
+ /**
181
+ * Whether a classified request is DID-Authentication *only*: it asks the wallet
182
+ * to prove control of its DID and nothing else (no credential queries, no
183
+ * capability requests). Derived from the profile so a popup's restore fast-path
184
+ * and its render both dispatch on the one predicate.
185
+ *
186
+ * @param profile {WalletRequestProfile}
187
+ * @returns {boolean}
188
+ */
189
+ export function isDidAuthOnly(profile) {
190
+ return (profile.didAuth &&
191
+ profile.vcQueries.length === 0 &&
192
+ profile.zcapRequests.length === 0);
193
+ }
194
+ /**
195
+ * Returns true if the wallet can satisfy the DID method a `DIDAuthentication`
196
+ * query constrains to. A wallet holding only `did:key` can satisfy a request
197
+ * that lists `key` among `acceptedMethods` or omits the constraint entirely.
198
+ *
199
+ * @param queries {IVPRQuery[]}
200
+ * @returns {boolean}
201
+ */
202
+ export function didAuthMethodSupported(queries) {
203
+ const didAuth = queries.find(query => query.type === 'DIDAuthentication');
204
+ const acceptedMethods = didAuth?.acceptedMethods;
205
+ if (!acceptedMethods || acceptedMethods.length === 0) {
206
+ return true;
207
+ }
208
+ return acceptedMethods.some(({ method }) => method === 'key');
209
+ }
210
+ //# sourceMappingURL=classify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/request/classify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { IDocumentLoader } from '@interop/data-integrity-core';
2
+ import type { IVerifiablePresentation, IVerifiableCredential, IZcap, PresentationSigner } from './types.js';
3
+ /**
4
+ * Shared JSON-LD document loader for presentation and credential signing.
5
+ * Exported so single-VC issuance paths reuse the same context resolution the VP
6
+ * compose path uses.
7
+ */
8
+ export declare const documentLoader: IDocumentLoader;
9
+ /**
10
+ * Creates a Verifiable Presentation for the requester.
11
+ *
12
+ * @param options {object}
13
+ * @param options.presentationSigner {PresentationSigner} - The authentication
14
+ * signer and the holder DID to name on a signed VP.
15
+ * @param [options.selectedVcs] {IVerifiableCredential[]} - VCs the user chose to
16
+ * share (empty for a DID-Auth-only or zcap-only response).
17
+ * @param [options.challenge] {string} - Required when DID Auth is requested.
18
+ * @param [options.domain] {string} - Signed into the proof when present;
19
+ * optional per the VPR spec.
20
+ * @param options.didAuthRequested {boolean} - Whether to sign the VP.
21
+ * @param [options.cryptosuite] {string} - Negotiated cryptosuite; falls back to
22
+ * the wallet default (Ed25519Signature2020) when absent.
23
+ * @param [options.zcaps] {IZcap[]} - Delegated capabilities to embed as the
24
+ * VP's `zcap` array (before signing, so a DIDAuth proof covers them).
25
+ * @param [options.appConnect] {{ firstRun: boolean }} - App Connect response
26
+ * marker to embed (before signing, like the grants).
27
+ * @param [options.vocabBaseIri] {string} - Vocabulary base IRI for the embedded
28
+ * term definitions; defaults to Freewallet's value.
29
+ * @param [options.documentLoader] {IDocumentLoader} - JSON-LD loader; defaults
30
+ * to the shared security loader.
31
+ * @returns {Promise<IVerifiablePresentation>}
32
+ */
33
+ export declare function composeVp({ presentationSigner, selectedVcs, challenge, domain, didAuthRequested, cryptosuite, zcaps, appConnect, vocabBaseIri, documentLoader: loader }: {
34
+ presentationSigner: PresentationSigner;
35
+ selectedVcs?: IVerifiableCredential[];
36
+ challenge?: string;
37
+ domain?: string;
38
+ didAuthRequested: boolean;
39
+ cryptosuite?: string;
40
+ zcaps?: IZcap[];
41
+ appConnect?: {
42
+ firstRun: boolean;
43
+ };
44
+ vocabBaseIri?: string;
45
+ documentLoader?: IDocumentLoader;
46
+ }): Promise<IVerifiablePresentation>;
47
+ /**
48
+ * @deprecated Use {@link composeVp}. Retained for Freewallet, which imports the
49
+ * `composeVP` spelling.
50
+ */
51
+ export declare const composeVP: typeof composeVp;
52
+ //# sourceMappingURL=composeVp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composeVp.d.ts","sourceRoot":"","sources":["../../src/request/composeVp.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAEnE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,EACL,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAEnB;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,eAEnB,CAAA;AAyGV;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,SAAS,CAAC,EAC9B,kBAAkB,EAClB,WAAgB,EAChB,SAAS,EACT,MAAM,EACN,gBAAgB,EAChB,WAAW,EACX,KAAU,EACV,UAAU,EACV,YAAqC,EACrC,cAAc,EAAE,MAAuB,EACxC,EAAE;IACD,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAA;IACrC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gBAAgB,EAAE,OAAO,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,KAAK,EAAE,CAAA;IACf,UAAU,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAA;IAClC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,eAAe,CAAA;CACjC,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAoDnC;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,kBAAY,CAAA"}