@docknetwork/wallet-sdk-wasm 1.7.0 → 1.7.6

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 (85) hide show
  1. package/lib/index.js +1 -0
  2. package/lib/index.mjs +1 -0
  3. package/lib/modules/network-manager.js +15 -12
  4. package/lib/modules/network-manager.mjs +15 -12
  5. package/lib/rpc-server.js +1 -0
  6. package/lib/rpc-server.mjs +1 -0
  7. package/lib/services/blockchain/service.js +22 -9
  8. package/lib/services/blockchain/service.mjs +23 -10
  9. package/lib/services/credential/bound-check.js +1 -1
  10. package/lib/services/credential/bound-check.mjs +1 -1
  11. package/lib/services/credential/delegatable-credentials.js +300 -0
  12. package/lib/services/credential/delegatable-credentials.mjs +263 -0
  13. package/lib/services/credential/index.js +39 -0
  14. package/lib/services/credential/index.mjs +4 -0
  15. package/lib/services/credential/pex-helpers.js +4 -4
  16. package/lib/services/credential/pex-helpers.mjs +4 -4
  17. package/lib/services/edv/index.js +1 -0
  18. package/lib/services/edv/index.mjs +1 -0
  19. package/lib/services/edv/service-rpc.js +23 -0
  20. package/lib/services/edv/service-rpc.mjs +23 -0
  21. package/lib/services/edv/service.js +81 -1
  22. package/lib/services/edv/service.mjs +78 -2
  23. package/lib/services/index.js +1 -0
  24. package/lib/services/index.mjs +1 -0
  25. package/lib/services/pex/config.js +4 -0
  26. package/lib/services/pex/config.mjs +4 -0
  27. package/lib/services/pex/service-rpc.js +4 -0
  28. package/lib/services/pex/service-rpc.mjs +4 -0
  29. package/lib/services/pex/service.js +7 -0
  30. package/lib/services/pex/service.mjs +7 -0
  31. package/lib/setup-nodejs.js +1 -0
  32. package/lib/setup-nodejs.mjs +1 -0
  33. package/lib/setup-tests.js +1 -0
  34. package/lib/setup-tests.mjs +1 -0
  35. package/lib/src/modules/event-manager.d.ts +0 -1
  36. package/lib/src/modules/event-manager.d.ts.map +1 -1
  37. package/lib/src/modules/network-manager.d.ts +2 -4
  38. package/lib/src/modules/network-manager.d.ts.map +1 -1
  39. package/lib/src/services/blockchain/configs.d.ts +1 -2
  40. package/lib/src/services/blockchain/configs.d.ts.map +1 -1
  41. package/lib/src/services/blockchain/service.d.ts +4 -3
  42. package/lib/src/services/blockchain/service.d.ts.map +1 -1
  43. package/lib/src/services/credential/bbs-revocation.d.ts +1 -1
  44. package/lib/src/services/credential/bbs-revocation.d.ts.map +1 -1
  45. package/lib/src/services/credential/bound-check.d.ts.map +1 -1
  46. package/lib/src/services/credential/delegatable-credentials.d.ts +272 -0
  47. package/lib/src/services/credential/delegatable-credentials.d.ts.map +1 -0
  48. package/lib/src/services/credential/index.d.ts +1 -0
  49. package/lib/src/services/credential/index.d.ts.map +1 -1
  50. package/lib/src/services/credential/pex-helpers.d.ts +2 -2
  51. package/lib/src/services/credential/pex-helpers.d.ts.map +1 -1
  52. package/lib/src/services/dids/keypair-utils.d.ts +2 -2
  53. package/lib/src/services/dids/keypair-utils.d.ts.map +1 -1
  54. package/lib/src/services/dids/service.d.ts +35 -3
  55. package/lib/src/services/dids/service.d.ts.map +1 -1
  56. package/lib/src/services/edv/service.d.ts +50 -1
  57. package/lib/src/services/edv/service.d.ts.map +1 -1
  58. package/lib/src/services/pex/config.d.ts +1 -0
  59. package/lib/src/services/pex/config.d.ts.map +1 -1
  60. package/lib/src/services/pex/service.d.ts +1 -0
  61. package/lib/src/services/pex/service.d.ts.map +1 -1
  62. package/lib/src/services/relay-service/service.d.ts +19 -7
  63. package/lib/src/services/relay-service/service.d.ts.map +1 -1
  64. package/lib/src/services/storage/service.d.ts.map +1 -1
  65. package/lib/src/services/util-crypto/service.d.ts +2 -2
  66. package/lib/src/services/util-crypto/service.d.ts.map +1 -1
  67. package/lib/tsconfig.tsbuildinfo +1 -1
  68. package/package.json +24 -16
  69. package/rollup.config.mjs +5 -3
  70. package/src/globals.d.ts +3 -0
  71. package/src/modules/network-manager.ts +15 -14
  72. package/src/services/blockchain/configs.ts +1 -2
  73. package/src/services/blockchain/service.ts +26 -10
  74. package/src/services/credential/bound-check.ts +1 -1
  75. package/src/services/credential/delegatable-credentials.ts +409 -0
  76. package/src/services/credential/index.ts +16 -0
  77. package/src/services/credential/pex-helpers.js +4 -4
  78. package/src/services/credential/pex-helpers.test.js +2 -2
  79. package/src/services/edv/index.test.js +229 -0
  80. package/src/services/edv/service-rpc.js +23 -0
  81. package/src/services/edv/service.ts +119 -0
  82. package/src/services/pex/config.ts +4 -0
  83. package/src/services/pex/service-rpc.js +4 -0
  84. package/src/services/pex/service.ts +13 -0
  85. package/src/services/pex/tests/pex-service.test.js +210 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docknetwork/wallet-sdk-wasm",
3
- "version": "1.7.0",
3
+ "version": "1.7.6",
4
4
  "license": "https://github.com/docknetwork/wallet-sdk/LICENSE",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,34 +18,42 @@
18
18
  "p-limit": "2.3.0"
19
19
  },
20
20
  "dependencies": {
21
- "p-limit": "2.3.0",
22
21
  "@astronautlabs/jsonpath": "^1.1.2",
23
- "@docknetwork/universal-wallet": "^2.0.1",
24
- "@docknetwork/wallet-sdk-dids": "^1.7.0",
22
+ "@cedar-policy/cedar-wasm": "^4.5.0",
25
23
  "@cosmjs/proto-signing": "^0.32.4",
26
- "@docknetwork/cheqd-blockchain-api": "4.0.5",
27
- "@docknetwork/cheqd-blockchain-modules": "4.0.6",
28
- "@scure/bip39": "^1.6.0",
24
+ "@docknetwork/cheqd-blockchain-api": "4.1.1",
25
+ "@docknetwork/cheqd-blockchain-modules": "4.0.8",
26
+ "@docknetwork/credential-sdk": "0.54.16",
27
+ "@docknetwork/universal-wallet": "^2.0.1",
28
+ "@docknetwork/vc-delegation-engine": "1.0.3",
29
+ "@docknetwork/wallet-sdk-dids": "^1.7.6",
29
30
  "@noble/hashes": "1.8.0",
30
- "@docknetwork/credential-sdk": "0.54.9",
31
- "@sphereon/oid4vci-client": "^0.16.0",
32
- "@sphereon/oid4vci-common": "^0.16.0",
31
+ "@scure/bip39": "^1.6.0",
33
32
  "@sd-jwt/crypto-nodejs": "^0.15.0",
34
33
  "@sd-jwt/sd-jwt-vc": "^0.15.1",
35
- "base64url": "^3.0.1",
34
+ "@sphereon/oid4vci-client": "^0.16.0",
35
+ "@sphereon/oid4vci-common": "^0.16.0",
36
+ "@sphereon/pex": "^1.1.4",
36
37
  "axios": "^0.25.0",
38
+ "axios-retry": "^3.2.5",
39
+ "base64url": "^3.0.1",
40
+ "cwait": "1.1.2",
41
+ "futoin-hkdf": "^1.5.3",
37
42
  "json-rpc-2.0": "^0.2.16",
43
+ "jsonld": "^6.0.0",
44
+ "p-limit": "2.3.0",
38
45
  "uuid": "^8.3.2",
39
- "winston": "^3.3.3",
40
- "cwait": "1.1.2",
41
- "axios-retry": "^3.2.5",
42
- "@sphereon/pex": "^1.1.4"
46
+ "winston": "^3.3.3"
43
47
  },
44
48
  "devDependencies": {
45
49
  "@babel/node": "^7.16.0",
46
- "sinon": "^12.0.1",
47
50
  "jest": "29.6.1",
51
+ "sinon": "^12.0.1",
48
52
  "ts-jest": "29.1.0",
49
53
  "typescript": "^5.0.4"
54
+ },
55
+ "overrides": {
56
+ "@digitalbazaar/http-client": "^3.4.1",
57
+ "base58-universal": "2.0.0"
50
58
  }
51
59
  }
package/rollup.config.mjs CHANGED
@@ -1,14 +1,16 @@
1
1
  import json from '@rollup/plugin-json';
2
- import multiInput from 'rollup-plugin-multi-input';
2
+ import _multiInput from 'rollup-plugin-multi-input';
3
3
  import commonjs from '@rollup/plugin-commonjs';
4
4
  import flow from 'rollup-plugin-flow';
5
5
  import typescript from '@rollup/plugin-typescript';
6
6
 
7
+ const multiInput = _multiInput.default || _multiInput;
8
+
7
9
  export default async function () {
8
10
  return [
9
11
  {
10
12
  plugins: [
11
- multiInput.default(),
13
+ multiInput(),
12
14
  json(),
13
15
  flow({
14
16
  all: true,
@@ -17,7 +19,7 @@ export default async function () {
17
19
  commonjs(),
18
20
  typescript(),
19
21
  ],
20
- input: ['src/**/*.ts', 'src/**/*.js', '!src/**/*.test.ts', '!src/**/*.test.js'],
22
+ input: ['src/**/*.ts', 'src/**/*.js', '!src/**/*.test.ts', '!src/**/*.test.js', '!src/**/*.d.ts'],
21
23
  output: [
22
24
  {
23
25
  dir: 'lib',
@@ -0,0 +1,3 @@
1
+ // CryptoKey is available globally in Node.js 15+ but TypeScript needs
2
+ // the DOM lib to recognize it. Declare it here to avoid pulling in all DOM types.
3
+ type CryptoKey = import('crypto').webcrypto.CryptoKey;
@@ -3,35 +3,36 @@ import assert from 'assert';
3
3
 
4
4
  export type NetworkInfo = {
5
5
  name: string,
6
- substrateUrl: string | string[],
7
- addressPrefix: number,
8
- cheqdApiUrl: string,
6
+ cheqdApiUrl: string | string[],
9
7
  };
10
8
 
11
9
  export type NetworkId = 'mainnet' | 'testnet' | 'local' | 'custom';
12
10
 
13
- export const SUBSTRATE_NETWORKS : Record<NetworkId, NetworkInfo> = {
11
+ export const BLOCKCHAIN_NETWORKS : Record<NetworkId, NetworkInfo> = {
14
12
  mainnet: {
15
13
  name: 'Cheqd Mainnet',
16
- substrateUrl: null,
17
- addressPrefix: 22,
18
- cheqdApiUrl: 'https://mainnet.cheqd.docknode.io',
14
+ cheqdApiUrl: [
15
+ 'https://mainnet.cheqd.docknode.io',
16
+ 'https://rpc.cheqd.net',
17
+ ],
19
18
  },
20
19
  testnet: {
21
20
  name: 'Cheqd Testnet',
22
- substrateUrl: null,
23
- addressPrefix: 21,
24
- cheqdApiUrl: 'https://testnet.cheqd.docknode.io',
21
+ cheqdApiUrl: [
22
+ 'https://testnet.cheqd.docknode.io',
23
+ 'https://api.cheqd.network',
24
+ ],
25
25
  },
26
26
  local: {
27
27
  name: 'Local Node',
28
- substrateUrl: 'ws://127.0.0.1:9944',
29
- addressPrefix: 21,
28
+ cheqdApiUrl: [
29
+ 'http://localhost:8080',
30
+ ],
30
31
  },
31
32
  };
32
33
 
33
34
  function getNetworkInfo(networkId): NetworkInfo {
34
- const networkInfo = SUBSTRATE_NETWORKS[networkId];
35
+ const networkInfo = BLOCKCHAIN_NETWORKS[networkId];
35
36
 
36
37
  assert(!!networkInfo, `Network ${networkId} not found`);
37
38
 
@@ -57,7 +58,7 @@ export class NetworkManager {
57
58
  * @param {string} networkId
58
59
  */
59
60
  setNetworkId(networkId: NetworkId) {
60
- assert(!!SUBSTRATE_NETWORKS[networkId], `invalid networkId ${networkId}`);
61
+ assert(!!BLOCKCHAIN_NETWORKS[networkId], `invalid networkId ${networkId}`);
61
62
 
62
63
  this.networkId = networkId;
63
64
  }
@@ -4,8 +4,7 @@ import assert from 'assert';
4
4
  export const validation = {};
5
5
 
6
6
  export type InitParams = {
7
- substrateUrl: string,
8
- cheqdApiUrl?: string,
7
+ cheqdApiUrl?: string | string[],
9
8
  networkId?: string,
10
9
  cheqdMnemonic?: string,
11
10
  };
@@ -60,7 +60,11 @@ export class BlockchainService {
60
60
  cheqdApi;
61
61
  cheqdApiUrl;
62
62
  isBlockchainReady = false;
63
- resolver: any;
63
+ private _resolver: any;
64
+
65
+ get resolver(): any {
66
+ return this._resolver;
67
+ }
64
68
  /**
65
69
  * Event names emitted by the blockchain service
66
70
  * @static
@@ -93,7 +97,8 @@ export class BlockchainService {
93
97
  this.cheqdModules = new CheqdCoreModules(this.cheqdApi);
94
98
  this.modules = new MultiApiCoreModules([this.cheqdModules]);
95
99
  this.emitter = new EventEmitter();
96
- this.resolver = this.createDIDResolver();
100
+ // Blockchain is not ready yet, but we can use fallback resolvers
101
+ this._resolver = this.createDIDResolver();
97
102
  }
98
103
 
99
104
  /**
@@ -161,12 +166,21 @@ export class BlockchainService {
161
166
  * @private
162
167
  * @returns {CachedDIDResolver} Cached DID resolver instance
163
168
  */
164
- createDIDResolver() {
165
- const router = new AnyDIDResolver([
166
- new DIDKeyResolver(),
167
- new CoreResolver(this.modules),
169
+ createDIDResolver(isBlockchainReady: boolean) {
170
+ let resolvers = [
168
171
  new UniversalResolver(universalResolverUrl),
169
- ]);
172
+ new DIDKeyResolver(),
173
+ ]
174
+
175
+ // Add blockchain resolvers if the blockchain is ready
176
+ if (isBlockchainReady) {
177
+ resolvers = [
178
+ new CoreResolver(this.modules),
179
+ ...resolvers
180
+ ]
181
+ }
182
+
183
+ const router = new AnyDIDResolver(resolvers);
170
184
 
171
185
  return new CachedDIDResolver(router);
172
186
  }
@@ -217,16 +231,18 @@ export class BlockchainService {
217
231
  try {
218
232
  await this.cheqdApi.init({
219
233
  wallet,
220
- url: checkdApiUrl,
234
+ urls: Array.isArray(checkdApiUrl) ? checkdApiUrl : [checkdApiUrl],
221
235
  network: cheqdNetworkId,
222
236
  });
223
237
  Logger.info(`Cheqd initialized at: ${checkdApiUrl}`);
224
238
  } catch (err) {
239
+ debugger
225
240
  Logger.error(`Failed to initialize cheqd at: ${checkdApiUrl}`, err);
226
241
  }
227
242
 
228
243
 
229
- this.resolver = this.createDIDResolver();
244
+ // Re-create the resolver with the new blockchain connection
245
+ this._resolver = this.createDIDResolver(true);
230
246
 
231
247
  if (
232
248
  process.env.NODE_ENV !== 'test' ||
@@ -299,7 +315,7 @@ export class BlockchainService {
299
315
  * @example
300
316
  * const apiUrl = await blockchainService.getAddress();
301
317
  */
302
- async getAddress() {
318
+ async getAddress(): Promise<string | string[]> {
303
319
  return this.cheqdApiUrl;
304
320
  }
305
321
 
@@ -107,7 +107,7 @@ export function blobFromBase64(base64String: string): Uint8Array {
107
107
  /^data:application\/octet-stream;base64,/,
108
108
  '',
109
109
  );
110
- return base64url.toBuffer(cleanedBase64);
110
+ return new Uint8Array(base64url.toBuffer(cleanedBase64));
111
111
  }
112
112
 
113
113
  export async function isBase64OrDataUrl(str: string): Promise<boolean> {
@@ -0,0 +1,409 @@
1
+ // @ts-nocheck
2
+ import * as cedar from '@cedar-policy/cedar-wasm/nodejs';
3
+ import {
4
+ verifyPresentation,
5
+ issueCredential,
6
+ signPresentation,
7
+ documentLoader,
8
+ getSuiteFromKeyDoc,
9
+ } from '@docknetwork/credential-sdk/vc';
10
+ import { MAY_CLAIM_IRI } from '@docknetwork/vc-delegation-engine';
11
+ import { getKeypairFromDoc } from '@docknetwork/universal-wallet/methods/keypairs';
12
+ import { blockchainService } from '../blockchain/service';
13
+
14
+ /**
15
+ * Prepares a key document for signing by creating a proper keypair with signer capability
16
+ * @param keyDoc - The key document with id, controller, type, and key material
17
+ * @returns A key document with an active signer
18
+ */
19
+ function prepareKeyForSigning(keyDoc: KeyPair): any {
20
+ const kp = getKeypairFromDoc(keyDoc);
21
+ // Get the signer from the keypair - this returns an object with id and sign method
22
+ const signer = kp.signer();
23
+ // Set the id on the signer to match the verification method
24
+ signer.id = keyDoc.id;
25
+ return {
26
+ ...keyDoc,
27
+ keypair: kp,
28
+ signer,
29
+ };
30
+ }
31
+
32
+ export interface VerificationResult {
33
+ verified: boolean;
34
+ credentialResults?: any[];
35
+ delegationResult?: {
36
+ decision: string;
37
+ summaries?: any[];
38
+ authorizations?: any[];
39
+ failures?: any[];
40
+ };
41
+ error?: any;
42
+ }
43
+
44
+ export interface CedarPolicies {
45
+ staticPolicies: string;
46
+ }
47
+
48
+ export interface VerifiablePresentation {
49
+ '@context': any[];
50
+ type: string[];
51
+ proof?: any;
52
+ verifiableCredential?: any[];
53
+ }
54
+
55
+ export interface DelegationCredential {
56
+ '@context': any[];
57
+ id: string;
58
+ type: string[];
59
+ issuer: string;
60
+ issuanceDate: string;
61
+ previousCredentialId: string | null;
62
+ rootCredentialId: string;
63
+ credentialSubject: {
64
+ id: string;
65
+ [key: string]: any;
66
+ };
67
+ proof?: any;
68
+ }
69
+
70
+ export interface VerifyDelegationOptions {
71
+ challenge?: string;
72
+ domain?: string;
73
+ unsignedPresentation?: boolean;
74
+ failOnUnauthorizedClaims?: boolean;
75
+ policies?: CedarPolicies;
76
+ }
77
+
78
+ export interface KeyPair {
79
+ type: string;
80
+ id?: string;
81
+ controller?: string;
82
+ publicKeyJwk?: any;
83
+ privateKeyJwk?: any;
84
+ publicKeyBase58?: string;
85
+ privateKeyBase58?: string;
86
+ }
87
+
88
+ /**
89
+ * W3C Credentials V1 context URL
90
+ */
91
+ export const W3C_CREDENTIALS_V1 = 'https://www.w3.org/2018/credentials/v1';
92
+
93
+ /**
94
+ * Re-export MAY_CLAIM_IRI for use in credentials
95
+ */
96
+ export { MAY_CLAIM_IRI };
97
+
98
+ /**
99
+ * Namespace used by the vc-delegation-engine for delegation properties
100
+ */
101
+ export const DELEGATION_ENGINE_NS = 'https://ld.truvera.io/credentials/delegation#';
102
+
103
+ /**
104
+ * Base delegation context terms required for delegation credentials.
105
+ * These terms define the JSON-LD mappings needed for the vc-delegation-engine
106
+ * to properly process delegation chains.
107
+ *
108
+ * Use this as a base and extend with your own application-specific terms:
109
+ * @example
110
+ * const myContext = [
111
+ * W3C_CREDENTIALS_V1,
112
+ * {
113
+ * ...DELEGATION_CONTEXT_TERMS,
114
+ * // Add your custom terms here
115
+ * MyCredentialType: 'https://example.org/MyCredentialType',
116
+ * myField: 'https://example.org/myField',
117
+ * },
118
+ * ];
119
+ */
120
+ export const DELEGATION_CONTEXT_TERMS = {
121
+ '@version': 1.1,
122
+ '@protected': true,
123
+ DelegationCredential: `${DELEGATION_ENGINE_NS}DelegationCredential`,
124
+ mayClaim: { '@id': MAY_CLAIM_IRI, '@container': '@set' },
125
+ rootCredentialId: { '@id': `${DELEGATION_ENGINE_NS}rootCredentialId`, '@type': '@id' },
126
+ previousCredentialId: { '@id': `${DELEGATION_ENGINE_NS}previousCredentialId`, '@type': '@id' },
127
+ };
128
+
129
+ /**
130
+ * Default context for verifiable presentations
131
+ */
132
+ export const PRESENTATION_CONTEXT = [W3C_CREDENTIALS_V1];
133
+
134
+ /**
135
+ * Issues a delegation credential that grants authority to a delegate
136
+ * @param keyPair - The key pair to sign the credential
137
+ * @param params - Delegation parameters
138
+ * @returns Signed delegation credential
139
+ */
140
+ export async function issueDelegationCredential(
141
+ keyPair: KeyPair,
142
+ credential: any
143
+ ): Promise<DelegationCredential> {
144
+ const preparedKey = prepareKeyForSigning(keyPair);
145
+ return issueCredential(preparedKey, credential);
146
+ }
147
+
148
+ /**
149
+ * Issues a credential as a delegate (with delegation chain reference)
150
+ * @param keyPair - The delegate's key pair to sign the credential
151
+ * @param params - Credential parameters
152
+ * @returns Signed credential
153
+ */
154
+ export async function issueDelegatedCredential(
155
+ keyPair: KeyPair,
156
+ credential: any
157
+ ): Promise<any> {
158
+ const preparedKey = prepareKeyForSigning(keyPair);
159
+ return issueCredential(preparedKey, credential);
160
+ }
161
+
162
+ /**
163
+ * Creates and signs a verifiable presentation with delegation credentials
164
+ * @param keyPair - The key pair to sign the presentation
165
+ * @param params - Presentation parameters
166
+ * @returns Signed verifiable presentation
167
+ */
168
+ export async function createSignedPresentation(
169
+ keyPair: KeyPair,
170
+ params: {
171
+ credentials: any[];
172
+ holderDid: string;
173
+ challenge: string;
174
+ domain: string;
175
+ context?: any[];
176
+ }
177
+ ): Promise<VerifiablePresentation> {
178
+ const {
179
+ credentials,
180
+ holderDid,
181
+ challenge,
182
+ domain,
183
+ context = PRESENTATION_CONTEXT,
184
+ } = params;
185
+
186
+ const presentation = {
187
+ '@context': context,
188
+ type: ['VerifiablePresentation'],
189
+ holder: holderDid,
190
+ verifiableCredential: credentials,
191
+ };
192
+
193
+ // Create key document for signing with proper keypair
194
+ const keyDoc = {
195
+ ...keyPair,
196
+ id: keyPair.id || `${holderDid}#keys-1`,
197
+ controller: keyPair.controller || holderDid,
198
+ };
199
+
200
+ const preparedKey = prepareKeyForSigning(keyDoc);
201
+ return signPresentation(presentation, preparedKey, challenge, domain);
202
+ }
203
+
204
+ /**
205
+ * Verifies a verifiable presentation with optional delegation chain validation
206
+ * Uses the credential-sdk's verifyPresentation which automatically:
207
+ * 1. Verifies the presentation signature
208
+ * 2. Verifies all credentials
209
+ * 3. Detects delegation credentials
210
+ * 4. Validates the delegation chain
211
+ * 5. Applies Cedar policies if provided
212
+ *
213
+ * @param vp - The verifiable presentation to verify
214
+ * @param options - Verification options
215
+ * @returns Verification result with delegation info if applicable
216
+ */
217
+ export async function verifyDelegatablePresentation(
218
+ vp: VerifiablePresentation,
219
+ options: VerifyDelegationOptions = {}
220
+ ): Promise<VerificationResult> {
221
+ const {
222
+ challenge = vp.proof?.challenge || 'default-challenge',
223
+ domain = vp.proof?.domain || 'default-domain',
224
+ unsignedPresentation = false,
225
+ failOnUnauthorizedClaims = true,
226
+ policies,
227
+ } = options;
228
+
229
+ const verifyOptions: any = {
230
+ challenge,
231
+ domain,
232
+ documentLoader: documentLoader(blockchainService.resolver),
233
+ unsignedPresentation,
234
+ failOnUnauthorizedClaims,
235
+ };
236
+
237
+ // Add Cedar authorization if policies are provided
238
+ if (policies) {
239
+ verifyOptions.cedarAuth = {
240
+ policies,
241
+ cedar,
242
+ };
243
+ }
244
+
245
+ return verifyPresentation(vp, verifyOptions);
246
+ }
247
+
248
+ /**
249
+ * Creates a Cedar policy for delegation verification
250
+ * @param config - Policy configuration
251
+ * @returns Cedar policy object
252
+ */
253
+ export function createCedarPolicy(config: {
254
+ maxDepth?: number;
255
+ rootIssuer: string;
256
+ requiredClaims?: Record<string, any>;
257
+ }): CedarPolicies {
258
+ const { maxDepth = 2, rootIssuer, requiredClaims = {} } = config;
259
+
260
+ let claimsConditions = '';
261
+ for (const [key, value] of Object.entries(requiredClaims)) {
262
+ if (typeof value === 'number') {
263
+ claimsConditions += ` &&\n context.authorizedClaims.${key} >= ${value}`;
264
+ } else if (typeof value === 'string') {
265
+ claimsConditions += ` &&\n context.authorizedClaims.${key} == "${value}"`;
266
+ }
267
+ }
268
+
269
+ const policyText = `
270
+ permit(
271
+ principal in Credential::Chain::"Action:Verify",
272
+ action == Credential::Action::"Verify",
273
+ resource
274
+ ) when {
275
+ principal == context.vpSigner &&
276
+ context.tailDepth <= ${maxDepth} &&
277
+ context.rootIssuer == Credential::Actor::"${rootIssuer}"${claimsConditions}
278
+ };
279
+ `;
280
+
281
+ return { staticPolicies: policyText };
282
+ }
283
+
284
+ /**
285
+ * Creates an unsigned verifiable presentation (for testing)
286
+ * @param credentials - Array of credentials to include
287
+ * @param proof - Optional proof object
288
+ * @param context - Optional context
289
+ * @returns Verifiable presentation object
290
+ */
291
+ export function createUnsignedPresentation(
292
+ credentials: any[],
293
+ proof?: any,
294
+ context: any[] = PRESENTATION_CONTEXT
295
+ ): VerifiablePresentation {
296
+ const vp: VerifiablePresentation = {
297
+ '@context': context,
298
+ type: ['VerifiablePresentation'],
299
+ verifiableCredential: credentials,
300
+ };
301
+
302
+ if (proof) {
303
+ vp.proof = proof;
304
+ }
305
+
306
+ return vp;
307
+ }
308
+
309
+ /**
310
+ * Re-export cedar for use in tests and external code
311
+ */
312
+ export { cedar };
313
+
314
+ /**
315
+ * Service class for delegatable credentials operations
316
+ */
317
+ class DelegatableCredentialsService {
318
+ name = 'delegatable-credentials';
319
+
320
+ rpcMethods = [
321
+ DelegatableCredentialsService.prototype.issueDelegation,
322
+ DelegatableCredentialsService.prototype.issueDelegatedCredential,
323
+ DelegatableCredentialsService.prototype.createPresentation,
324
+ DelegatableCredentialsService.prototype.verifyPresentation,
325
+ DelegatableCredentialsService.prototype.createPolicy,
326
+ ];
327
+
328
+ /**
329
+ * Issues a delegation credential
330
+ */
331
+ async issueDelegation(params: {
332
+ keyPair: KeyPair;
333
+ id: string;
334
+ issuerDid: string;
335
+ delegateDid: string;
336
+ mayClaim: string[];
337
+ context: any[];
338
+ types: string[];
339
+ additionalSubjectProperties?: Record<string, any>;
340
+ previousCredentialId?: string | null;
341
+ rootCredentialId?: string;
342
+ }): Promise<DelegationCredential> {
343
+ return issueDelegationCredential(params.keyPair, params);
344
+ }
345
+
346
+ /**
347
+ * Issues a credential as a delegate
348
+ */
349
+ async issueDelegatedCredential(params: {
350
+ keyPair: KeyPair;
351
+ id: string;
352
+ issuerDid: string;
353
+ subjectDid: string;
354
+ claims: Record<string, any>;
355
+ rootCredentialId: string;
356
+ previousCredentialId: string;
357
+ context: any[];
358
+ types: string[];
359
+ }): Promise<any> {
360
+ return issueDelegatedCredential(params.keyPair, params);
361
+ }
362
+
363
+ /**
364
+ * Creates and signs a verifiable presentation
365
+ */
366
+ async createPresentation(params: {
367
+ keyPair: KeyPair;
368
+ credentials: any[];
369
+ holderDid: string;
370
+ challenge: string;
371
+ domain: string;
372
+ context?: any[];
373
+ }): Promise<VerifiablePresentation> {
374
+ return createSignedPresentation(params.keyPair, params);
375
+ }
376
+
377
+ /**
378
+ * Verifies a verifiable presentation with delegation chain
379
+ */
380
+ async verifyPresentation(params: {
381
+ presentation: VerifiablePresentation;
382
+ challenge?: string;
383
+ domain?: string;
384
+ unsignedPresentation?: boolean;
385
+ failOnUnauthorizedClaims?: boolean;
386
+ policies?: CedarPolicies;
387
+ }): Promise<VerificationResult> {
388
+ return verifyDelegatablePresentation(params.presentation, {
389
+ challenge: params.challenge,
390
+ domain: params.domain,
391
+ unsignedPresentation: params.unsignedPresentation,
392
+ failOnUnauthorizedClaims: params.failOnUnauthorizedClaims,
393
+ policies: params.policies,
394
+ });
395
+ }
396
+
397
+ /**
398
+ * Creates a Cedar policy for delegation verification
399
+ */
400
+ createPolicy(params: {
401
+ maxDepth?: number;
402
+ rootIssuer: string;
403
+ requiredClaims?: Record<string, any>;
404
+ }): CedarPolicies {
405
+ return createCedarPolicy(params);
406
+ }
407
+ }
408
+
409
+ export const delegatableCredentialsService = new DelegatableCredentialsService();
@@ -3,3 +3,19 @@ import {credentialService} from './service';
3
3
 
4
4
  // TODO: rename it to credentialService, will need to update dock-app
5
5
  export const credentialServiceRPC = credentialService;
6
+
7
+ export {
8
+ delegatableCredentialsService,
9
+ verifyDelegatablePresentation,
10
+ issueDelegationCredential,
11
+ issueDelegatedCredential,
12
+ createSignedPresentation,
13
+ createUnsignedPresentation,
14
+ createCedarPolicy,
15
+ cedar,
16
+ MAY_CLAIM_IRI,
17
+ W3C_CREDENTIALS_V1,
18
+ DELEGATION_ENGINE_NS,
19
+ DELEGATION_CONTEXT_TERMS,
20
+ PRESENTATION_CONTEXT,
21
+ } from './delegatable-credentials';