@cheqd/did-provider-cheqd 4.5.5-develop.1 → 4.6.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 (30) hide show
  1. package/build/esm/agent/ICheqd.d.ts +291 -82
  2. package/build/esm/agent/ICheqd.d.ts.map +1 -1
  3. package/build/esm/agent/ICheqd.js +1567 -87
  4. package/build/esm/agent/ICheqd.js.map +1 -1
  5. package/build/esm/did-manager/cheqd-did-provider.d.ts +13 -2
  6. package/build/esm/did-manager/cheqd-did-provider.d.ts.map +1 -1
  7. package/build/esm/did-manager/cheqd-did-provider.js +10 -2
  8. package/build/esm/did-manager/cheqd-did-provider.js.map +1 -1
  9. package/build/esm/dkg-threshold/lit-protocol/v6.d.ts.map +1 -1
  10. package/build/esm/dkg-threshold/lit-protocol/v6.js +63 -33
  11. package/build/esm/dkg-threshold/lit-protocol/v6.js.map +1 -1
  12. package/build/esm/utils/helpers.d.ts +28 -7
  13. package/build/esm/utils/helpers.d.ts.map +1 -1
  14. package/build/esm/utils/helpers.js +120 -29
  15. package/build/esm/utils/helpers.js.map +1 -1
  16. package/build/tsconfig.esm.tsbuildinfo +1 -1
  17. package/build/tsconfig.types.tsbuildinfo +1 -1
  18. package/build/types/agent/ICheqd.d.ts +291 -82
  19. package/build/types/agent/ICheqd.d.ts.map +1 -1
  20. package/build/types/did-manager/cheqd-did-provider.d.ts +13 -2
  21. package/build/types/did-manager/cheqd-did-provider.d.ts.map +1 -1
  22. package/build/types/dkg-threshold/lit-protocol/v6.d.ts.map +1 -1
  23. package/build/types/utils/helpers.d.ts +28 -7
  24. package/build/types/utils/helpers.d.ts.map +1 -1
  25. package/package.json +6 -4
  26. package/src/agent/ICheqd.ts +2425 -372
  27. package/src/did-manager/cheqd-did-provider.ts +19 -4
  28. package/src/dkg-threshold/lit-protocol/v6.ts +65 -34
  29. package/src/utils/helpers.ts +172 -34
  30. package/tsconfig.json +2 -0
@@ -82,7 +82,16 @@ export const DefaultStatusList2021ResourceTypes = {
82
82
  suspension: 'StatusList2021Suspension',
83
83
  } as const;
84
84
 
85
- export const DefaultStatusList2021Encodings = {
85
+ export const BitstringStatusPurposeTypes = {
86
+ refresh: 'refresh',
87
+ revocation: 'revocation',
88
+ suspension: 'suspension',
89
+ message: 'message',
90
+ } as const;
91
+
92
+ export const BitstringStatusListResourceType = 'BitstringStatusListCredential';
93
+
94
+ export const DefaultStatusListEncodings = {
86
95
  base64url: 'base64url',
87
96
  hex: 'hex',
88
97
  } as const;
@@ -97,14 +106,19 @@ export type DefaultStatusList2021ResourceType =
97
106
  export type DefaultStatusList2021StatusPurposeType =
98
107
  (typeof DefaultStatusList2021StatusPurposeTypes)[keyof typeof DefaultStatusList2021StatusPurposeTypes];
99
108
 
100
- export type DefaultStatusList2021Encoding =
101
- (typeof DefaultStatusList2021Encodings)[keyof typeof DefaultStatusList2021Encodings];
109
+ export type DefaultStatusListEncoding = (typeof DefaultStatusListEncodings)[keyof typeof DefaultStatusListEncodings];
110
+
111
+ export type BitstringStatusListPurposeType =
112
+ (typeof BitstringStatusPurposeTypes)[keyof typeof BitstringStatusPurposeTypes];
102
113
 
103
114
  export type LinkedResource = Omit<MsgCreateResourcePayload, 'data'> & { data?: string };
104
115
 
105
116
  export type ResourcePayload = Partial<MsgCreateResourcePayload>;
106
117
 
107
118
  export type StatusList2021ResourcePayload = ResourcePayload & { resourceType: DefaultStatusList2021ResourceType };
119
+ export type BitstringStatusListResourcePayload = ResourcePayload & {
120
+ resourceType: typeof BitstringStatusListResourceType;
121
+ };
108
122
 
109
123
  export type TImportableEd25519Key = Required<Pick<IKey, 'publicKeyHex' | 'privateKeyHex'>> & {
110
124
  kid: TImportableEd25519Key['publicKeyHex'];
@@ -1076,10 +1090,11 @@ export class CheqdDIDProvider extends AbstractIdentifierProvider {
1076
1090
  }
1077
1091
 
1078
1092
  async instantiateDkgThresholdProtocolClient(dkgOptions: DkgOptions = this.dkgOptions): Promise<LitProtocol> {
1093
+ const signer = await this._aminoSigner;
1079
1094
  return await LitProtocol.create({
1080
1095
  chain: dkgOptions.chain || this.dkgOptions.chain,
1081
1096
  litNetwork: dkgOptions.network || this.dkgOptions.network,
1082
- cosmosAuthWallet: await this._aminoSigner,
1097
+ cosmosAuthWallet: signer,
1083
1098
  });
1084
1099
  }
1085
1100
 
@@ -1,3 +1,5 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable no-empty-pattern */
1
3
  import { OfflineAminoSigner, Secp256k1HdWallet, Secp256k1Wallet, StdSignDoc } from '@cosmjs/amino';
2
4
  import { toString } from 'uint8arrays/to-string';
3
5
  import { sha256 } from '@cosmjs/crypto';
@@ -22,6 +24,7 @@ import { LitProtocolDebugEnabled } from '../../utils/constants.js';
22
24
  import { LitAccessControlConditionResource } from '@lit-protocol/auth-helpers';
23
25
  import { ethers } from 'ethers';
24
26
  import { LIT_RPC } from '@lit-protocol/constants';
27
+ import { initWasmBlsSdk } from '@lit-protocol/bls-sdk';
25
28
 
26
29
  export type ThresholdEncryptionResult = {
27
30
  encryptedString: Uint8Array;
@@ -152,16 +155,27 @@ export class LitProtocol {
152
155
  secret: Uint8Array,
153
156
  unifiedAccessControlConditions: NonNullable<UnifiedAccessControlConditions>
154
157
  ): Promise<ThresholdEncryptionResult> {
155
- // encrypt
156
- const { ciphertext: encryptedString, dataToEncryptHash: stringHash } = (await this.client.encrypt({
157
- dataToEncrypt: secret,
158
- unifiedAccessControlConditions,
159
- })) satisfies EncryptStringMethodResult;
158
+ try {
159
+ // encrypt
160
+ const { ciphertext: encryptedString, dataToEncryptHash: stringHash } = (await this.client.encrypt({
161
+ dataToEncrypt: secret,
162
+ unifiedAccessControlConditions,
163
+ })) satisfies EncryptStringMethodResult;
160
164
 
161
- return {
162
- encryptedString: fromString(encryptedString, 'base64'),
163
- stringHash,
164
- };
165
+ return {
166
+ encryptedString: fromString(encryptedString, 'base64'),
167
+ stringHash,
168
+ };
169
+ } catch (error: any) {
170
+ console.error('Encryption failed:', error);
171
+ if (error.stack) {
172
+ console.error('Stack:', error.stack);
173
+ }
174
+ // standardize error
175
+ throw new Error(
176
+ `[did-provider-cheqd]: lit-protocol: Encryption failed: ${(error as Error).message || error}`
177
+ );
178
+ }
165
179
  }
166
180
 
167
181
  async decrypt(
@@ -170,33 +184,44 @@ export class LitProtocol {
170
184
  unifiedAccessControlConditions: NonNullable<UnifiedAccessControlConditions>,
171
185
  capacityDelegationAuthSig?: GenericAuthSig
172
186
  ): Promise<string> {
173
- // generate session signatures
174
- const sessionSigs = await this.client.getSessionSigs({
175
- chain: 'cheqd',
176
- resourceAbilityRequests: [
177
- {
178
- resource: new LitAccessControlConditionResource('*'),
179
- ability: LitAbility.AccessControlConditionDecryption,
187
+ try {
188
+ // generate session signatures
189
+ const sessionSigs = await this.client.getSessionSigs({
190
+ chain: 'cheqd',
191
+ resourceAbilityRequests: [
192
+ {
193
+ resource: new LitAccessControlConditionResource('*'),
194
+ ability: LitAbility.AccessControlConditionDecryption,
195
+ },
196
+ ],
197
+ capabilityAuthSigs: capacityDelegationAuthSig ? [capacityDelegationAuthSig] : undefined,
198
+ authNeededCallback: async ({}) => {
199
+ // generate auth signature
200
+ const authSig = await LitProtocol.generateAuthSignature(this.cosmosAuthWallet);
201
+ return authSig;
180
202
  },
181
- ],
182
- capabilityAuthSigs: capacityDelegationAuthSig ? [capacityDelegationAuthSig] : undefined,
183
- authNeededCallback: async ({}) => {
184
- // generate auth signature
185
- const authSig = await LitProtocol.generateAuthSignature(this.cosmosAuthWallet);
186
- return authSig;
187
- },
188
- });
189
-
190
- // decrypt
191
- const { decryptedData } = (await this.client.decrypt({
192
- chain: this.chain,
193
- ciphertext: encryptedString,
194
- dataToEncryptHash: stringHash,
195
- unifiedAccessControlConditions,
196
- sessionSigs,
197
- })) satisfies DecryptToStringMethodResult;
203
+ });
198
204
 
199
- return toString(decryptedData, 'utf-8');
205
+ // decrypt
206
+ const { decryptedData } = (await this.client.decrypt({
207
+ chain: this.chain,
208
+ ciphertext: encryptedString,
209
+ dataToEncryptHash: stringHash,
210
+ unifiedAccessControlConditions,
211
+ sessionSigs,
212
+ })) satisfies DecryptToStringMethodResult;
213
+
214
+ return toString(decryptedData, 'utf-8');
215
+ } catch (error: any) {
216
+ console.error('Decryption failed:', error);
217
+ if (error.stack) {
218
+ console.error('Stack:', error.stack);
219
+ }
220
+ // standardize error
221
+ throw new Error(
222
+ `[did-provider-cheqd]: lit-protocol: Decryption failed: ${(error as Error).message || error}`
223
+ );
224
+ }
200
225
  }
201
226
 
202
227
  async delegateCapacitCredit(
@@ -300,6 +325,12 @@ export class LitProtocol {
300
325
 
301
326
  const litProtocol = new LitProtocol(options as LitProtocolOptions);
302
327
  await litProtocol.connect();
328
+ // Initialize BLS SDK WASM module explicitly
329
+ try {
330
+ await initWasmBlsSdk();
331
+ } catch (initError) {
332
+ throw new Error(`BLS SDK WASM initialization failed: ${(initError as Error).message || initError}`);
333
+ }
303
334
  return litProtocol;
304
335
  }
305
336
 
@@ -1,7 +1,8 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
1
2
  import { DIDDocument } from '@veramo/core-types';
2
- import { generate as generateSecret, type GenerateOptions } from 'generate-password';
3
- import { toString } from 'uint8arrays/to-string';
4
- import { EncodedList, EncodedListAsArray } from '../agent/index.js';
3
+ import { fromString, toString } from 'uint8arrays';
4
+ import { randomBytes as cryptoRandomBytes } from 'crypto';
5
+ import { Cheqd, EncodedList, EncodedListAsArray, StatusOptions } from '../agent/index.js';
5
6
 
6
7
  export function isEncodedList(list: unknown): list is EncodedList {
7
8
  return typeof list === 'string' && list.split('-').every((item) => typeof item === 'string' && item && item.length);
@@ -55,37 +56,10 @@ export async function randomFromRange(min: number, max: number, notIn: number[])
55
56
  return random;
56
57
  }
57
58
 
58
- export async function randomUniqueSubsetInRange(min: number, max: number, count: number): Promise<Array<number>> {
59
- const subset: number[] = [];
60
- for (let i = 0; i < count; i++) {
61
- subset.push(await randomFromRange(min, max, subset));
62
- }
63
- return subset;
64
- }
65
-
66
59
  export async function randomBytes(length: number): Promise<Buffer> {
67
60
  return Buffer.from(Array.from({ length }, () => Math.floor(Math.random() * 256)));
68
61
  }
69
62
 
70
- export async function randomUniqueSecret(options?: GenerateOptions): Promise<string> {
71
- return generateSecret({
72
- length: 64,
73
- numbers: true,
74
- symbols: true,
75
- uppercase: true,
76
- ...options,
77
- });
78
- }
79
-
80
- export async function initialiseIndexArray(length: number): Promise<Array<boolean>> {
81
- return Array(length).fill(true);
82
- }
83
-
84
- export async function shuffleArray<T>(array: Array<T>): Promise<Array<T>> {
85
- const shuffled = array.sort(() => Math.random() - 0.5);
86
- return shuffled;
87
- }
88
-
89
63
  export async function toBlob(data: Uint8Array): Promise<Blob> {
90
64
  return new Blob([data]);
91
65
  }
@@ -100,10 +74,9 @@ export async function blobToHexString(blob: Blob): Promise<string> {
100
74
  return toString(uint8Array, 'hex');
101
75
  }
102
76
 
103
- export function unescapeUnicode(str: string): string {
104
- return str.replace(/\\u([a-fA-F0-9]{4})/g, (m, cc) => {
105
- return String.fromCharCode(parseInt(cc, 16));
106
- });
77
+ export async function blobToUint8Array(blob: Blob): Promise<Uint8Array> {
78
+ const arrayBuffer = await blob.arrayBuffer();
79
+ return new Uint8Array(arrayBuffer);
107
80
  }
108
81
 
109
82
  export function getControllers(didDocument: DIDDocument): string[] {
@@ -118,3 +91,168 @@ export function getControllers(didDocument: DIDDocument): string[] {
118
91
  }
119
92
  return controllers;
120
93
  }
94
+
95
+ /**
96
+ * Check if encoded bitstring is valid base64url format
97
+ */
98
+ export function isValidEncodedBitstring(encodedList: string): boolean {
99
+ try {
100
+ // Should be valid base64url
101
+ fromString(encodedList, 'base64url');
102
+ return true;
103
+ } catch {
104
+ return false;
105
+ }
106
+ }
107
+ // Enhanced encoding function that returns metadata
108
+ export async function encodeWithMetadata(
109
+ symmetricEncryptionCiphertext: Blob,
110
+ thresholdEncryptionCiphertext: Uint8Array
111
+ ): Promise<{ encodedList: string; symmetricLength: number }> {
112
+ const symmetricBytes = await blobToUint8Array(symmetricEncryptionCiphertext);
113
+ // Concatenate both byte arrays
114
+ const combinedBytes = new Uint8Array(symmetricBytes.length + thresholdEncryptionCiphertext.length);
115
+ combinedBytes.set(symmetricBytes, 0);
116
+ combinedBytes.set(thresholdEncryptionCiphertext, symmetricBytes.length);
117
+
118
+ // Encode as base64url
119
+ const encodedList = toString(combinedBytes, 'base64url');
120
+
121
+ return { encodedList, symmetricLength: symmetricBytes.length };
122
+ }
123
+
124
+ export function decodeWithMetadata(
125
+ encodedList: string,
126
+ symmetricLength: number
127
+ ): {
128
+ symmetricEncryptionCiphertext: Blob;
129
+ thresholdEncryptionCiphertext: Uint8Array;
130
+ } {
131
+ // Decode from base64url to bytes
132
+ const combinedBytes = fromString(encodedList, 'base64url');
133
+
134
+ // Split based on the symmetric length
135
+ const symmetricBytes = combinedBytes.slice(0, symmetricLength);
136
+ const thresholdBytes = combinedBytes.slice(symmetricLength);
137
+
138
+ // Return as desired types
139
+ return {
140
+ symmetricEncryptionCiphertext: new Blob([symmetricBytes]),
141
+ thresholdEncryptionCiphertext: thresholdBytes,
142
+ };
143
+ }
144
+
145
+ interface IndexGenerationConfig {
146
+ statusSize?: number;
147
+ length?: number; // Bitstring length (default: 131072)
148
+ maxRetries?: number;
149
+ }
150
+ /**
151
+ * Generates a random statusListIndex based on external system constraints
152
+ *
153
+ * @param statusOptions - Constraints from external StatusListIndexManager
154
+ * @param config - Bitstring configuration (statusSize, length, etc.)
155
+ * @returns Random statusListIndex that satisfies all constraints
156
+ */
157
+ export function generateRandomStatusListIndex(
158
+ statusOptions: StatusOptions,
159
+ config: IndexGenerationConfig = {}
160
+ ): number {
161
+ const {
162
+ statusSize = Cheqd.DefaultBitstringStatusSize,
163
+ length = Cheqd.DefaultBitstringLength,
164
+ maxRetries = 1000,
165
+ } = config;
166
+
167
+ // If external system already provided a specific index, validate and return it
168
+ if (statusOptions.statusListIndex !== undefined) {
169
+ validateStatusListIndex(statusOptions.statusListIndex, statusOptions, config);
170
+ return statusOptions.statusListIndex;
171
+ }
172
+
173
+ // Calculate valid range bounds
174
+ const bounds = calculateValidRange(statusOptions, config);
175
+ const excludedIndices = new Set(statusOptions.indexNotIn || []);
176
+
177
+ // Check if generation is possible
178
+ const totalPossibleIndices = bounds.end - bounds.start + 1;
179
+ if (excludedIndices.size >= totalPossibleIndices) {
180
+ throw new Error(`Cannot generate index: all indices in range [${bounds.start}, ${bounds.end}] are excluded`);
181
+ }
182
+ let attempts = 0;
183
+ while (attempts < maxRetries) {
184
+ // Generate cryptographically secure random index within range
185
+ const randBytes = cryptoRandomBytes(4);
186
+ const randomValue = randBytes.readUInt32BE(0);
187
+
188
+ // Map to valid range [bounds.start, bounds.end]
189
+ const rangeSize = bounds.end - bounds.start + 1;
190
+ const statusListIndex = bounds.start + (randomValue % rangeSize);
191
+
192
+ // Check if this index is excluded
193
+ if (!excludedIndices.has(statusListIndex)) {
194
+ return statusListIndex;
195
+ }
196
+
197
+ attempts++;
198
+ }
199
+
200
+ throw new Error(
201
+ `Failed to generate unique statusListIndex after ${maxRetries} attempts. ` +
202
+ `Range: [${bounds.start}, ${bounds.end}], Excluded: ${excludedIndices.size} indices`
203
+ );
204
+ }
205
+ /**
206
+ * Validates a specific statusListIndex against constraints
207
+ */
208
+ function validateStatusListIndex(index: number, statusOptions: StatusOptions, config: IndexGenerationConfig): void {
209
+ const bounds = calculateValidRange(statusOptions, config);
210
+ const excludedIndices = statusOptions.indexNotIn || [];
211
+
212
+ if (index < bounds.start || index > bounds.end) {
213
+ throw new Error(`StatusListIndex ${index} is outside valid range [${bounds.start}, ${bounds.end}]`);
214
+ }
215
+
216
+ if (excludedIndices.includes(index)) {
217
+ throw new Error(`StatusListIndex ${index} is in the excluded list: [${excludedIndices.join(', ')}]`);
218
+ }
219
+ }
220
+ /**
221
+ * Calculates the valid range for statusListIndex generation
222
+ */
223
+ function calculateValidRange(
224
+ statusOptions: StatusOptions,
225
+ config: IndexGenerationConfig
226
+ ): { start: number; end: number } {
227
+ const { statusSize = Cheqd.DefaultBitstringStatusSize, length = Cheqd.DefaultBitstringLength } = config;
228
+
229
+ // Calculate maximum possible index based on bitstring configuration
230
+ const totalBits = length * statusSize;
231
+ const alignedLength = Math.ceil(totalBits / 8) * 8;
232
+ const maxPossibleIndex = Math.floor(alignedLength / statusSize) - 1;
233
+
234
+ // Start with external system's range constraints
235
+ let start = statusOptions.statusListRangeStart ?? 0;
236
+ let end = statusOptions.statusListRangeEnd ?? maxPossibleIndex;
237
+
238
+ // Ensure range is within bitstring bounds
239
+ start = Math.max(0, start);
240
+ end = Math.min(maxPossibleIndex, end);
241
+
242
+ // Validate range
243
+ if (start > end) {
244
+ throw new Error(
245
+ `Invalid range: start (${start}) is greater than end (${end}). ` +
246
+ `Maximum possible index for this configuration: ${maxPossibleIndex}`
247
+ );
248
+ }
249
+
250
+ if (start < 0 || end > maxPossibleIndex) {
251
+ throw new Error(
252
+ `Range [${start}, ${end}] exceeds valid bounds [0, ${maxPossibleIndex}] ` +
253
+ `for statusSize=${statusSize} and length=${length}`
254
+ );
255
+ }
256
+
257
+ return { start, end };
258
+ }
package/tsconfig.json CHANGED
@@ -5,6 +5,7 @@
5
5
  "sourceMap": true,
6
6
  "module": "NodeNext",
7
7
  "esModuleInterop": true,
8
+ "resolveJsonModule": true,
8
9
  "downlevelIteration": true,
9
10
  "declarationMap": true,
10
11
  "declaration": true,
@@ -12,6 +13,7 @@
12
13
  "noImplicitAny": false,
13
14
  "emitDecoratorMetadata": true,
14
15
  "experimentalDecorators": true,
16
+ "outDir": "build",
15
17
  "skipLibCheck": true,
16
18
  "rootDir": "src",
17
19
  },