@cooperation/vc-storage 1.0.28 → 1.0.30

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.
@@ -5,6 +5,9 @@ import { v4 as uuidv4 } from 'uuid';
5
5
  import { extractKeyPairFromCredential, generateDIDSchema, generateUnsignedRecommendation, generateUnsignedVC, } from '../utils/credential.js';
6
6
  import { customDocumentLoader } from '../utils/digitalbazaar.js';
7
7
  import { saveToGoogleDrive } from '../utils/google.js';
8
+ function delay(ms) {
9
+ return new Promise((resolve) => setTimeout(resolve, ms));
10
+ }
8
11
  /**
9
12
  * Class representing the Credential Engine.
10
13
  * @class CredentialEngine
@@ -47,12 +50,19 @@ export class CredentialEngine {
47
50
  this.keyPair = key;
48
51
  return key;
49
52
  }
50
- generateKeyPair = async (address) => {
51
- const keyPair = await Ed25519VerificationKey2020.generate();
53
+ generateKeyPair = async (address, seed) => {
54
+ // Generate the key pair using the library's method
55
+ const keyPair = seed
56
+ ? await Ed25519VerificationKey2020.generate({
57
+ seed: Buffer.from(seed).toString('hex'),
58
+ })
59
+ : await Ed25519VerificationKey2020.generate();
60
+ // Configure key pair attributes
52
61
  const a = address || keyPair.publicKeyMultibase;
53
62
  keyPair.controller = `did:key:${a}`;
54
63
  keyPair.id = `${keyPair.controller}#${a}`;
55
64
  keyPair.revoked = false;
65
+ // The `signer` is already provided by the `Ed25519VerificationKey2020` instance
56
66
  return keyPair;
57
67
  };
58
68
  async verifyCreds(creds) {
@@ -71,11 +81,6 @@ export class CredentialEngine {
71
81
  async createDID() {
72
82
  try {
73
83
  const keyPair = await this.generateKeyPair();
74
- // const keyFile = await saveToGoogleDrive({
75
- // storage: this.storage,
76
- // data: keyPair,
77
- // type: 'KEYPAIR',
78
- // });
79
84
  const didDocument = await generateDIDSchema(keyPair);
80
85
  return { didDocument, keyPair };
81
86
  }
@@ -234,4 +239,112 @@ export class CredentialEngine {
234
239
  throw error;
235
240
  }
236
241
  }
242
+ /**
243
+ * Generate and sign an email Verifiable Credential (VC)
244
+ * @param {string} email - The email address to create the VC for
245
+ * @returns {Promise<{signedVC: any, fileId: string}>} The signed VC and its Google Drive file ID
246
+ */
247
+ async generateAndSignEmailVC(email) {
248
+ try {
249
+ let keyPair;
250
+ let didDocument;
251
+ // Require SEED from environment
252
+ const encodedSeed = process.env.SEED;
253
+ if (!encodedSeed) {
254
+ throw new Error('SEED environment variable not set. Cannot generate or use any DID.');
255
+ }
256
+ // Use deterministic keys from environment seed
257
+ const { getDidFromEnvSeed } = await import('../utils/decodedSeed');
258
+ const result = await getDidFromEnvSeed();
259
+ keyPair = result.keyPair;
260
+ didDocument = result.didDocument;
261
+ console.log('Using DID from environment seed:', didDocument.id);
262
+ // Ensure the key has proper ID and controller
263
+ if (!keyPair.id || !keyPair.controller) {
264
+ const verificationMethod = didDocument.verificationMethod?.[0] || didDocument.authentication?.[0];
265
+ if (verificationMethod) {
266
+ keyPair.id = typeof verificationMethod === 'string' ? verificationMethod : verificationMethod.id;
267
+ keyPair.controller = didDocument.id;
268
+ }
269
+ }
270
+ console.log('Creating email VC with DID:', didDocument.id);
271
+ // Generate unsigned email VC
272
+ const unsignedCredential = {
273
+ '@context': [
274
+ 'https://www.w3.org/2018/credentials/v1',
275
+ {
276
+ email: 'https://schema.org/email',
277
+ EmailCredential: {
278
+ '@id': 'https://example.com/EmailCredential',
279
+ },
280
+ },
281
+ ],
282
+ id: `urn:uuid:${uuidv4()}`,
283
+ type: ['VerifiableCredential', 'EmailCredential'],
284
+ issuer: {
285
+ id: didDocument.id,
286
+ },
287
+ issuanceDate: new Date().toISOString(),
288
+ expirationDate: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(), // 1 year from now
289
+ credentialSubject: {
290
+ id: `did:email:${email}`,
291
+ email: email,
292
+ },
293
+ };
294
+ // Sign the VC
295
+ const suite = new Ed25519Signature2020({
296
+ key: keyPair,
297
+ verificationMethod: keyPair.id,
298
+ });
299
+ const signedVC = await dbVc.issue({
300
+ credential: unsignedCredential,
301
+ suite,
302
+ documentLoader: customDocumentLoader,
303
+ });
304
+ const rootFolders = await this.storage.findFolders();
305
+ // Find or create Credentials folder
306
+ let credentialsFolder = rootFolders.find((f) => f.name === 'Credentials');
307
+ if (!credentialsFolder) {
308
+ credentialsFolder = await this.storage.createFolder({
309
+ folderName: 'Credentials',
310
+ parentFolderId: 'root',
311
+ });
312
+ // Wait and re-check to avoid duplicates
313
+ await delay(1500);
314
+ const refreshedFolders = await this.storage.findFolders();
315
+ const foundAgain = refreshedFolders.find((f) => f.name === 'Credentials');
316
+ if (foundAgain)
317
+ credentialsFolder = foundAgain;
318
+ }
319
+ // Find or create EMAIL_VC folder
320
+ const subfolders = await this.storage.findFolders(credentialsFolder.id);
321
+ let emailVcFolder = subfolders.find((f) => f.name === 'EMAIL_VC');
322
+ if (!emailVcFolder) {
323
+ emailVcFolder = await this.storage.createFolder({
324
+ folderName: 'EMAIL_VC',
325
+ parentFolderId: credentialsFolder.id,
326
+ });
327
+ // Wait and re-check to avoid duplicates
328
+ await delay(1500);
329
+ const refreshedSubfolders = await this.storage.findFolders(credentialsFolder.id);
330
+ const foundAgain = refreshedSubfolders.find((f) => f.name === 'EMAIL_VC');
331
+ if (foundAgain)
332
+ emailVcFolder = foundAgain;
333
+ }
334
+ // Save the VC in the EMAIL_VC folder
335
+ const file = await this.storage.saveFile({
336
+ data: {
337
+ fileName: `${email}`,
338
+ mimeType: 'application/json',
339
+ body: signedVC,
340
+ },
341
+ folderId: emailVcFolder.id,
342
+ });
343
+ return { signedVC, fileId: file.id };
344
+ }
345
+ catch (error) {
346
+ console.error('Error generating and signing email VC:', error);
347
+ throw error;
348
+ }
349
+ }
237
350
  }
@@ -142,6 +142,14 @@ export class GoogleDriveStorage {
142
142
  headers: {},
143
143
  body: JSON.stringify({ role: 'reader', type: 'anyone' }),
144
144
  });
145
+ // Invalidate cache for this parent folder
146
+ if (this.folderCache[parentFolderId]) {
147
+ delete this.folderCache[parentFolderId];
148
+ }
149
+ // Also clear 'root' cache if parent is root
150
+ if (parentFolderId === 'root' && this.folderCache['root']) {
151
+ delete this.folderCache['root'];
152
+ }
145
153
  return folder;
146
154
  }
147
155
  async getMediaFolderId() {
@@ -7,18 +7,31 @@ import { generateDIDSchema } from '../utils/credential.js';
7
7
  import { inlineResumeContext } from '../utils/context.js';
8
8
  export class ResumeVC {
9
9
  async sign({ formData, issuerDid, keyPair }) {
10
+ // First, generate the unsigned credential with the professional summary
10
11
  const unsignedCredential = this.generateUnsignedCredential({ formData, issuerDid });
12
+ // Create the signature suite for signing
11
13
  const suite = new Ed25519Signature2020({
12
- key: new Ed25519VerificationKey2020(keyPair), // Ensure proper initialization
14
+ key: new Ed25519VerificationKey2020(keyPair),
13
15
  verificationMethod: keyPair.id,
14
16
  });
15
17
  try {
16
- const signedVC = await dbVc.issue({
18
+ // 1: Sign the professional summary VC first
19
+ const professionalSummaryVC = unsignedCredential.credentialSubject.professionalSummary;
20
+ const signedProfessionalSummaryVC = await dbVc.issue({
21
+ credential: professionalSummaryVC,
22
+ suite,
23
+ documentLoader: customDocumentLoader,
24
+ });
25
+ // Replace the unsigned professional summary with the signed one
26
+ unsignedCredential.credentialSubject.professionalSummary = signedProfessionalSummaryVC;
27
+ // 2: Now sign the entire resume VC (which includes the signed professional summary)
28
+ const signedResumeVC = await dbVc.issue({
17
29
  credential: unsignedCredential,
18
30
  suite,
19
31
  documentLoader: customDocumentLoader,
20
32
  });
21
- console.log('Signed VC:', signedVC);
33
+ console.log('Signed Resume VC:', signedResumeVC);
34
+ return signedResumeVC;
22
35
  }
23
36
  catch (error) {
24
37
  console.error('Error signing VC:', error.message);
@@ -27,8 +40,34 @@ export class ResumeVC {
27
40
  }
28
41
  throw error;
29
42
  }
30
- return unsignedCredential;
31
43
  }
44
+ generateProfessionalSummary = (aff) => {
45
+ let cleanNarrative = aff.narrative || '';
46
+ if (cleanNarrative.startsWith('<p>') && cleanNarrative.endsWith('</p>')) {
47
+ // Remove the opening and closing p tags
48
+ cleanNarrative = cleanNarrative.substring(3, cleanNarrative.length - 4);
49
+ }
50
+ // removing all <p> tags
51
+ cleanNarrative = cleanNarrative.replace(/<\/?p>/g, '');
52
+ // Replace <b> or <strong> tags with markdown bold syntax (**word**)
53
+ cleanNarrative = cleanNarrative.replace(/<b>(.*?)<\/b>/g, '**$1**');
54
+ cleanNarrative = cleanNarrative.replace(/<strong>(.*?)<\/strong>/g, '**$1**');
55
+ return {
56
+ '@context': [
57
+ 'https://www.w3.org/2018/credentials/v1',
58
+ {
59
+ '@vocab': 'https://schema.hropenstandards.org/4.4/',
60
+ narrative: 'https://schema.org/narrative',
61
+ },
62
+ ],
63
+ type: ['VerifiableCredential', 'NarrativeCredential'],
64
+ issuer: aff.issuer, // same DID as the issuer of the resume
65
+ issuanceDate: new Date().toISOString(),
66
+ credentialSubject: {
67
+ narrative: cleanNarrative,
68
+ },
69
+ };
70
+ };
32
71
  generateUnsignedCredential({ formData, issuerDid }) {
33
72
  const unsignedResumeVC = {
34
73
  '@context': ['https://www.w3.org/2018/credentials/v1', inlineResumeContext['@context']],
@@ -62,9 +101,10 @@ export class ResumeVC {
62
101
  },
63
102
  },
64
103
  },
65
- narrative: {
66
- text: formData.summary || '',
67
- },
104
+ professionalSummary: this.generateProfessionalSummary({
105
+ issuer: issuerDid,
106
+ narrative: formData.summary || '',
107
+ }),
68
108
  employmentHistory: formData.experience.items.map((exp) => ({
69
109
  id: exp.id ? `urn:uuid${exp.id}` : `urn:uuid:${uuidv4()}`, // Ensure each entry has an ID
70
110
  organization: {
@@ -0,0 +1,31 @@
1
+ import { CredentialEngine } from '../models/CredentialEngine.js';
2
+ import { GoogleDriveStorage } from '../models/GoogleDriveStorage.js';
3
+ async function testEmailVC() {
4
+ try {
5
+ // Get Google Drive access token from environment
6
+ const accessToken = 'your access token';
7
+ // Initialize storage and engine
8
+ const storage = new GoogleDriveStorage(accessToken);
9
+ const engine = new CredentialEngine(storage);
10
+ // Test email
11
+ const testEmail = 'test@example.com';
12
+ console.log('Starting email VC generation test...');
13
+ console.log('Test email:', testEmail);
14
+ // Generate and sign the email VC
15
+ const result = await engine.generateAndSignEmailVC(testEmail);
16
+ console.log('\nTest Results:');
17
+ console.log('-------------');
18
+ console.log('File ID:', result.fileId);
19
+ console.log('Signed VC:', JSON.stringify(result.signedVC, null, 2));
20
+ // Test retrieving the VC from storage
21
+ console.log('\nRetrieving VC from storage...');
22
+ const retrievedVC = await storage.retrieve(result.fileId);
23
+ console.log('Retrieved VC:', retrievedVC ? 'Success' : 'Failed');
24
+ console.log('\nTest completed successfully!');
25
+ }
26
+ catch (error) {
27
+ console.error('Test failed:', error);
28
+ }
29
+ }
30
+ // Run the test
31
+ testEmailVC().catch(console.error);
@@ -0,0 +1,75 @@
1
+ // @ts-nocheck
2
+ import { decodeSecretKeySeed } from 'bnid';
3
+ import { Ed25519VerificationKey2020 } from '@digitalbazaar/ed25519-verification-key-2020';
4
+ import { driver as keyDriver } from '@digitalbazaar/did-method-key';
5
+ import { CryptoLD } from 'crypto-ld';
6
+ // EXACT SAME SETUP AS YOUR WORKING SCRIPT
7
+ const cryptoLd = new CryptoLD();
8
+ cryptoLd.use(Ed25519VerificationKey2020);
9
+ // Reference decodeSeed implementation
10
+ const decodeSeed = async (secretKeySeed) => {
11
+ let secretKeySeedBytes;
12
+ if (secretKeySeed.startsWith('z')) {
13
+ secretKeySeedBytes = decodeSecretKeySeed({ secretKeySeed });
14
+ }
15
+ else if (secretKeySeed.length >= 32) {
16
+ secretKeySeedBytes = new TextEncoder().encode(secretKeySeed).slice(0, 32);
17
+ }
18
+ else {
19
+ throw TypeError('"secretKeySeed" must be at least 32 bytes, preferably multibase-encoded.');
20
+ }
21
+ return secretKeySeedBytes;
22
+ };
23
+ // EXACT SAME FUNCTION AS YOUR WORKING generateSeed BUT WITH PREDEFINED SEEDS
24
+ async function testGenerateSeed(encodedSeed) {
25
+ const seed = await decodeSeed(encodedSeed);
26
+ let didDocument;
27
+ // EXACT SAME CODE AS YOUR WORKING SCRIPT
28
+ const didKeyDriver = keyDriver();
29
+ didKeyDriver.use({
30
+ multibaseMultikeyHeader: 'z6Mk',
31
+ fromMultibase: Ed25519VerificationKey2020.from,
32
+ });
33
+ const verificationKeyPair = await Ed25519VerificationKey2020.generate({
34
+ seed,
35
+ });
36
+ ({ didDocument } = await didKeyDriver.fromKeyPair({ verificationKeyPair }));
37
+ const did = didDocument.id;
38
+ return { seed: encodedSeed, decodedSeed: seed, did, didDocument, publicKey: verificationKeyPair.publicKeyMultibase };
39
+ }
40
+ // Test with different seeds
41
+ async function testDifferentSeeds() {
42
+ console.log('Testing different seeds with EXACT working script approach:\n');
43
+ const testSeeds = [
44
+ 'z1AjjnVSNmZot5TJcgtFYhn83WASAcphrqgE95AQ436hrGR',
45
+ 'z1AibHGc5Zek2kvdSyC22xGLZCvV7b77KWBFWiQmZGnD6rV',
46
+ 'z1AgfwVqaN3zX1kw2iTvLLekCbXNRJA7XbiFZCQv9TfgKCT',
47
+ ];
48
+ const results = [];
49
+ for (const testSeed of testSeeds) {
50
+ console.log(`Testing seed: ${testSeed}`);
51
+ console.log(`Decoded hex: ${Buffer.from(await decodeSeed(testSeed)).toString('hex')}`);
52
+ try {
53
+ const result = await testGenerateSeed(testSeed);
54
+ console.log(`Generated DID: ${result.did}`);
55
+ console.log(`Public key: ${result.publicKey}`);
56
+ results.push(result);
57
+ }
58
+ catch (error) {
59
+ console.error(`Error: ${error.message}`);
60
+ }
61
+ console.log('---');
62
+ }
63
+ console.log('\nResults:');
64
+ const uniqueDids = new Set(results.map((r) => r.did));
65
+ const uniqueKeys = new Set(results.map((r) => r.publicKey));
66
+ console.log(`Total results: ${results.length}`);
67
+ console.log(`Unique DIDs: ${uniqueDids.size}`);
68
+ console.log(`Unique public keys: ${uniqueKeys.size}`);
69
+ console.log(`Expected unique: ${testSeeds.length}`);
70
+ console.log(`Success: ${uniqueDids.size === testSeeds.length ? '✓ YES' : '✗ NO'}`);
71
+ results.forEach((result, i) => {
72
+ console.log(`${i + 1}. ${result.seed} -> ${result.did}`);
73
+ });
74
+ }
75
+ testDifferentSeeds().catch(console.error);
@@ -0,0 +1,29 @@
1
+ import { CredentialEngine } from '../models/CredentialEngine.js';
2
+ import { GoogleDriveStorage } from '../models/GoogleDriveStorage.js';
3
+ async function testEmailVC() {
4
+ try {
5
+ // Initialize storage and engine
6
+ const storage = new GoogleDriveStorage('YOUR_ACCESS_TOKEN'); // Replace with actual access token
7
+ const engine = new CredentialEngine(storage);
8
+ // Test email
9
+ const testEmail = 'test@example.com';
10
+ console.log('Starting email VC generation test...');
11
+ console.log('Test email:', testEmail);
12
+ // Generate and sign the email VC
13
+ const result = await engine.generateAndSignEmailVC(testEmail);
14
+ console.log('\nTest Results:');
15
+ console.log('-------------');
16
+ console.log('File ID:', result.fileId);
17
+ console.log('Signed VC:', JSON.stringify(result.signedVC, null, 2));
18
+ // Test retrieving the VC from storage
19
+ console.log('\nRetrieving VC from storage...');
20
+ const retrievedVC = await storage.retrieve(result.fileId);
21
+ console.log('Retrieved VC:', retrievedVC ? 'Success' : 'Failed');
22
+ console.log('\nTest completed successfully!');
23
+ }
24
+ catch (error) {
25
+ console.error('Test failed:', error);
26
+ }
27
+ }
28
+ // Run the test
29
+ testEmailVC().catch(console.error);
@@ -78,5 +78,14 @@ export declare class CredentialEngine {
78
78
  * @returns
79
79
  */
80
80
  signPresentation(presentation: any): Promise<any>;
81
+ /**
82
+ * Generate and sign an email Verifiable Credential (VC)
83
+ * @param {string} email - The email address to create the VC for
84
+ * @returns {Promise<{signedVC: any, fileId: string}>} The signed VC and its Google Drive file ID
85
+ */
86
+ generateAndSignEmailVC(email: string): Promise<{
87
+ signedVC: any;
88
+ fileId: string;
89
+ }>;
81
90
  }
82
91
  export {};
@@ -4,6 +4,18 @@ export declare class ResumeVC {
4
4
  issuerDid: string;
5
5
  keyPair: any;
6
6
  }): Promise<any>;
7
+ generateProfessionalSummary: (aff: any) => {
8
+ '@context': (string | {
9
+ '@vocab': string;
10
+ narrative: string;
11
+ })[];
12
+ type: string[];
13
+ issuer: any;
14
+ issuanceDate: string;
15
+ credentialSubject: {
16
+ narrative: any;
17
+ };
18
+ };
7
19
  generateUnsignedCredential({ formData, issuerDid }: {
8
20
  formData: any;
9
21
  issuerDid: string;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -4,7 +4,7 @@ export declare const inlineResumeContext: {
4
4
  name: string;
5
5
  formattedName: string;
6
6
  primaryLanguage: string;
7
- narrative: string;
7
+ professionalSummary: string;
8
8
  text: string;
9
9
  contact: string;
10
10
  email: string;
@@ -0,0 +1,18 @@
1
+ export declare function decodeSeed(encodedSeed: string): Promise<Uint8Array>;
2
+ export declare const getDidFromEnvSeed: () => Promise<{
3
+ keyPair: any;
4
+ didDocument: {
5
+ '@context': string[];
6
+ id: string;
7
+ verificationMethod: {
8
+ id: string;
9
+ type: string;
10
+ controller: string;
11
+ publicKeyMultibase: any;
12
+ }[];
13
+ authentication: string[];
14
+ assertionMethod: string[];
15
+ capabilityDelegation: string[];
16
+ capabilityInvocation: string[];
17
+ };
18
+ }>;
@@ -6,7 +6,7 @@ export const inlineResumeContext = {
6
6
  formattedName: 'https://schema.org/formattedName',
7
7
  primaryLanguage: 'https://schema.org/primaryLanguage',
8
8
  // Narrative
9
- narrative: 'https://schema.org/narrative',
9
+ professionalSummary: 'https://schema.org/professionalSummary',
10
10
  text: 'https://schema.org/text',
11
11
  // Contact Information
12
12
  contact: 'https://schema.org/ContactPoint',
@@ -0,0 +1,77 @@
1
+ import { Ed25519VerificationKey2020 } from '@digitalbazaar/ed25519-verification-key-2020';
2
+ import { base58btc } from 'multiformats/bases/base58';
3
+ export async function decodeSeed(encodedSeed) {
4
+ try {
5
+ // Ensure the seed has the 'z' prefix
6
+ const seedWithPrefix = encodedSeed.startsWith('z') ? encodedSeed : `z${encodedSeed}`;
7
+ // Decode the entire string including the prefix
8
+ const decoded = base58btc.decode(seedWithPrefix);
9
+ // The decoded data includes a multicodec header (2 bytes: 0x00 0x20)
10
+ // We need to remove this header to get the actual 32-byte seed
11
+ if (decoded.length === 34 && decoded[0] === 0x00 && decoded[1] === 0x20) {
12
+ // Skip the first 2 bytes to get the actual seed
13
+ const seed = new Uint8Array(decoded.slice(2));
14
+ console.log('Decoded seed (removed 2-byte header):', Buffer.from(seed).toString('hex'));
15
+ return seed;
16
+ }
17
+ // If it's already 32 bytes, return as is
18
+ if (decoded.length === 32) {
19
+ console.log('Decoded seed (already 32 bytes):', Buffer.from(decoded).toString('hex'));
20
+ return new Uint8Array(decoded);
21
+ }
22
+ throw new Error(`Invalid seed length: ${decoded.length} bytes (expected 32 bytes after removing any headers)`);
23
+ }
24
+ catch (error) {
25
+ console.error('Error decoding seed:', error);
26
+ throw error;
27
+ }
28
+ }
29
+ export const getDidFromEnvSeed = async () => {
30
+ // Get seed from environment variable
31
+ const encodedSeed = process.env.SEED;
32
+ if (!encodedSeed) {
33
+ throw new Error('SEED environment variable not set');
34
+ }
35
+ console.log('Using seed from environment:', encodedSeed);
36
+ // Decode the seed (this will remove the 2-byte header if present)
37
+ const seed = await decodeSeed(encodedSeed);
38
+ console.log('Decoded seed length:', seed.length);
39
+ // Create key pair from seed
40
+ const verificationKeyPair = await Ed25519VerificationKey2020.generate({
41
+ seed: seed,
42
+ type: 'Ed25519VerificationKey2020',
43
+ });
44
+ console.log('Generated public key:', verificationKeyPair.publicKeyMultibase);
45
+ // Create DID manually to avoid key agreement issues
46
+ const fingerprint = verificationKeyPair.fingerprint();
47
+ const did = `did:key:${fingerprint}`;
48
+ // Create a proper DID document
49
+ const didDocument = {
50
+ '@context': [
51
+ 'https://www.w3.org/ns/did/v1',
52
+ 'https://w3id.org/security/suites/ed25519-2020/v1',
53
+ 'https://w3id.org/security/suites/x25519-2020/v1',
54
+ ],
55
+ id: did,
56
+ verificationMethod: [
57
+ {
58
+ id: `${did}#${fingerprint}`,
59
+ type: 'Ed25519VerificationKey2020',
60
+ controller: did,
61
+ publicKeyMultibase: verificationKeyPair.publicKeyMultibase,
62
+ },
63
+ ],
64
+ authentication: [`${did}#${fingerprint}`],
65
+ assertionMethod: [`${did}#${fingerprint}`],
66
+ capabilityDelegation: [`${did}#${fingerprint}`],
67
+ capabilityInvocation: [`${did}#${fingerprint}`],
68
+ };
69
+ // Set the key ID and controller on the key pair
70
+ verificationKeyPair.id = `${did}#${fingerprint}`;
71
+ verificationKeyPair.controller = did;
72
+ console.log('Generated DID:', did);
73
+ return {
74
+ keyPair: verificationKeyPair,
75
+ didDocument,
76
+ };
77
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cooperation/vc-storage",
3
3
  "type": "module",
4
- "version": "1.0.28",
4
+ "version": "1.0.30",
5
5
  "description": "Sign and store your verifiable credentials.",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/types/index.d.ts",
@@ -17,12 +17,16 @@
17
17
  "license": "ISC",
18
18
  "dependencies": {
19
19
  "@digitalbazaar/did-method-key": "^5.2.0",
20
- "@digitalbazaar/ed25519-signature-2020": "^5.3.0",
20
+ "@digitalbazaar/ed25519-signature-2020": "^5.4.0",
21
21
  "@digitalbazaar/ed25519-verification-key-2020": "^4.1.0",
22
22
  "@digitalbazaar/vc": "^6.3.0",
23
+ "add": "^2.0.6",
24
+ "bnid": "^3.0.0",
23
25
  "crypto-js": "^4.2.0",
26
+ "crypto-ld": "^7.0.0",
24
27
  "ethers": "^6.13.2",
25
28
  "jest": "^29.7.0",
29
+ "multiformats": "^13.3.6",
26
30
  "ts-jest": "^29.2.5",
27
31
  "ts-node": "^10.9.2",
28
32
  "tsc": "^2.0.4",