@learncard/vc-templates-plugin 1.1.24 → 1.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,25 +9,26 @@
9
9
  The LearnCard Core is a pluggable, open-source, universal digital wallet to enable any individual or organization to seamlessly **issue, earn, store, share, and spend currency and credentials** built for the future of education and work.
10
10
 
11
11
  ## Documentation
12
+
12
13
  All LearnCard documentation can be found at:
13
14
  https://docs.learncard.com
14
15
 
15
16
  ## Install
16
17
 
17
18
  ```bash
18
- pnpm i @learncard/core
19
+ bun add @learncard/core
19
20
  ```
20
21
 
21
22
  ## Usage
22
23
 
23
24
  ### Instantiation
24
25
 
25
- Instantiate a wallet using `initLearnCard`. This method accepts a unique identifier string that is
26
+ Instantiate a wallet using `initLearnCard`. This method accepts a unique identifier string that is
26
27
  up to 64 characters long. If it is less than 64 characters, `initLearnCard` will pad the start of
27
28
  the string with 0's until it is 64 characters long.
28
29
 
29
30
  ```js
30
- import { initLearnCard } from "@learncard/core";
31
+ import { initLearnCard } from '@learncard/core';
31
32
 
32
33
  const wallet = await initLearnCard({ seed: 'a'.repeat(64) });
33
34
  ```
@@ -35,6 +36,7 @@ const wallet = await initLearnCard({ seed: 'a'.repeat(64) });
35
36
  ### Issuing/Verifying Credentials and Presentations
36
37
 
37
38
  #### Issue a credential
39
+
38
40
  ```js
39
41
  // Grab a test VC, or create your own!
40
42
  const unsignedVc = await wallet.invoke.getTestVc();
@@ -43,6 +45,7 @@ const vc = await wallet.invoke.issueCredential(unsignedVc);
43
45
  ```
44
46
 
45
47
  #### Verify a credential
48
+
46
49
  ```js
47
50
  const result = await wallet.invoke.verifyCredential(vc, {}, true);
48
51
 
@@ -53,11 +56,13 @@ else console.log('This credential is valid!');
53
56
  ```
54
57
 
55
58
  #### Issue a presentation
59
+
56
60
  ```js
57
61
  const vp = await wallet.invoke.issuePresentation(vc);
58
62
  ```
59
63
 
60
64
  #### Verify a presentation
65
+
61
66
  ```js
62
67
  const result = await wallet.invoke.verifyPresentation(vp);
63
68
 
@@ -74,14 +79,14 @@ else console.log('This presentation is valid!');
74
79
  To maintain co-ownership of credentials, it is best to store credentials in a public place, and then
75
80
  store references to that public place. While this is not the only way to store credentials (and is
76
81
  also definitely not a silver bullet! E.g. credentials containing private data), it is the opinion of
77
- this library that it should be used by default. As a result, instantiating a wallet, will
78
- automatically connect you to WeLibrary's ceramic node, and allow you to publish and retrieve
82
+ this library that it should be used by default. As a result, instantiating a wallet, will
83
+ automatically connect you to WeLibrary's ceramic node, and allow you to publish and retrieve
79
84
  credentials there using IDX.
80
85
 
81
86
  #### Publish Credential
82
87
 
83
88
  After signing a VC, you may choose to publish that credential to Ceramic. Doing so will return a
84
- stream ID, which you may share to the recipient. That stream ID can then be used to resolve the
89
+ stream ID, which you may share to the recipient. That stream ID can then be used to resolve the
85
90
  issued credential. This means both the issuer and recipient may store the _stream ID_ instead of the
86
91
  credential itself.
87
92
 
@@ -126,6 +131,7 @@ const vcs = await Promise.all(uris.map(async uri => wallet.read.get(uri)));
126
131
  ```
127
132
 
128
133
  ## Contributing
134
+
129
135
  Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
130
136
 
131
137
  Please make sure to update tests as appropriate.
@@ -134,7 +140,6 @@ Please make sure to update tests as appropriate.
134
140
 
135
141
  **[Learning Economy Foundation (LEF)](https://www.learningeconomy.io)** is a 501(c)(3) non-profit organization leveraging global standards and web3 protocols to bring quality skills and equal opportunity to every human on earth, and address the persistent inequities that exist around the globe in education and employment. We help you build the future of education and work with:
136
142
 
137
-
138
143
  ## License
139
144
 
140
145
  MIT © [Learning Economy Foundation](https://github.com/Learning-Economy-Foundation)
package/package.json CHANGED
@@ -1,56 +1,58 @@
1
1
  {
2
- "name": "@learncard/vc-templates-plugin",
3
- "version": "1.1.24",
4
- "description": "",
5
- "type": "module",
6
- "main": "./dist/index.cjs",
7
- "module": "./dist/vc-templates-plugin.esm.js",
8
- "exports": {
9
- ".": {
10
- "import": {
11
- "types": "./dist/index.d.ts",
12
- "default": "./dist/vc-templates-plugin.esm.js"
13
- },
14
- "require": {
15
- "types": "./dist/index.d.cts",
16
- "default": "./dist/index.cjs"
17
- }
18
- }
19
- },
20
- "files": [
21
- "dist"
22
- ],
23
- "author": "Learning Economy Foundation (www.learningeconomy.io)",
24
- "license": "MIT",
25
- "homepage": "https://github.com/learningeconomy/LearnCard/tree/main/packages/plugins/vc-templates/README.md",
26
- "repository": {
27
- "type": "git",
28
- "url": "https://github.com/learningeconomy/LearnCard"
29
- },
30
- "bugs": {
31
- "url": "https://github.com/learningeconomy/LearnCard/issues"
32
- },
33
- "devDependencies": {
34
- "@types/jest": "^29.2.2",
35
- "@types/node": "^17.0.31",
36
- "aqu": "0.4.3",
37
- "esbuild": "^0.27.1",
38
- "esbuild-jest": "^0.5.0",
39
- "esbuild-plugin-copy": "^1.3.0",
40
- "jest": "^29.3.0",
41
- "shx": "^0.3.4",
42
- "ts-jest": "^29.0.3"
43
- },
44
- "types": "./dist/index.d.ts",
45
- "dependencies": {
46
- "@learncard/core": "9.4.24",
47
- "@learncard/types": "5.17.4"
48
- },
49
- "sideEffects": false,
50
- "scripts": {
51
- "build": "node ./scripts/build.mjs && shx cp ./scripts/mixedEntypoint.js ./dist/index.cjs && tsc --p tsconfig.json && shx cp ./dist/index.d.ts ./dist/index.d.cts",
52
- "test": "jest --passWithNoTests",
53
- "test:watch": "jest --watch",
54
- "test:coverage": "jest --silent --ci --coverage --coverageReporters=\"text\" --coverageReporters=\"text-summary\""
55
- }
56
- }
2
+ "name": "@learncard/vc-templates-plugin",
3
+ "version": "1.1.25",
4
+ "description": "",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/vc-templates-plugin.esm.js",
8
+ "exports": {
9
+ ".": {
10
+ "development": "./src/index.ts",
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/vc-templates-plugin.esm.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "src"
24
+ ],
25
+ "scripts": {
26
+ "build": "node ./scripts/build.mjs && shx cp ./scripts/mixedEntypoint.js ./dist/index.cjs && tsc --p tsconfig.json && shx cp ./dist/index.d.ts ./dist/index.d.cts",
27
+ "test": "jest --passWithNoTests",
28
+ "test:watch": "jest --watch",
29
+ "test:coverage": "jest --silent --ci --coverage --coverageReporters=\"text\" --coverageReporters=\"text-summary\""
30
+ },
31
+ "author": "Learning Economy Foundation (www.learningeconomy.io)",
32
+ "license": "MIT",
33
+ "homepage": "https://github.com/learningeconomy/LearnCard/tree/main/packages/plugins/vc-templates/README.md",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/learningeconomy/LearnCard"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/learningeconomy/LearnCard/issues"
40
+ },
41
+ "devDependencies": {
42
+ "@types/jest": "^29.2.2",
43
+ "@types/node": "^17.0.31",
44
+ "aqu": "0.4.3",
45
+ "esbuild": "^0.27.1",
46
+ "esbuild-jest": "^0.5.0",
47
+ "esbuild-plugin-copy": "^1.3.0",
48
+ "jest": "^29.3.0",
49
+ "shx": "^0.3.4",
50
+ "ts-jest": "^29.0.3"
51
+ },
52
+ "types": "./dist/index.d.ts",
53
+ "dependencies": {
54
+ "@learncard/core": "workspace:*",
55
+ "@learncard/types": "workspace:*"
56
+ },
57
+ "sideEffects": false
58
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { getVCTemplatesPlugin } from './vc-templates';
2
+ export * from './types';
@@ -0,0 +1,283 @@
1
+ import { UnsignedVC, UnsignedAchievementCredential } from '@learncard/types';
2
+
3
+ import { VcTemplates } from './types';
4
+
5
+ /** @group VC Templates Plugin */
6
+ export const VC_TEMPLATES: {
7
+ [Key in keyof VcTemplates]: (args: VcTemplates[Key], crypto: Crypto) => UnsignedVC;
8
+ } = {
9
+ basic: (
10
+ {
11
+ did = 'did:example:d23dd687a7dc6787646f2eb98d0',
12
+ subject = 'did:example:d23dd687a7dc6787646f2eb98d0',
13
+ issuanceDate = '2020-08-19T21:41:50Z',
14
+ } = {},
15
+ crypto
16
+ ) => ({
17
+ '@context': ['https://www.w3.org/ns/credentials/v2'],
18
+ id: `urn:uuid:${crypto.randomUUID()}`,
19
+ type: ['VerifiableCredential'],
20
+ issuer: did,
21
+ validFrom: issuanceDate,
22
+ credentialSubject: { id: subject },
23
+ }),
24
+ achievement: (
25
+ {
26
+ did = 'did:example:d23dd687a7dc6787646f2eb98d0',
27
+ subject = 'did:example:d23dd687a7dc6787646f2eb98d0',
28
+ name = 'Teamwork Badge',
29
+ achievementName = 'Teamwork',
30
+ description = 'This badge recognizes the development of the capacity to collaborate within a group environment.',
31
+ criteriaNarrative = 'Team members are nominated for this badge by their peers and recognized upon review by Example Corp management.',
32
+ issuanceDate = '2020-08-19T21:41:50Z',
33
+ } = {},
34
+ crypto
35
+ ): UnsignedAchievementCredential => ({
36
+ '@context': [
37
+ 'https://www.w3.org/ns/credentials/v2',
38
+ 'https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json',
39
+ ],
40
+ id: `urn:uuid:${crypto.randomUUID()}`,
41
+ type: ['VerifiableCredential', 'OpenBadgeCredential'],
42
+ issuer: { id: did },
43
+ validFrom: issuanceDate,
44
+ name,
45
+ credentialSubject: {
46
+ id: subject,
47
+ type: ['AchievementSubject'],
48
+ achievement: {
49
+ id: `urn:uuid:${crypto.randomUUID()}`,
50
+ type: ['Achievement'],
51
+ criteria: { narrative: criteriaNarrative },
52
+ description,
53
+ name: achievementName,
54
+ },
55
+ },
56
+ }),
57
+ jff2: (
58
+ {
59
+ did = 'did:example:d23dd687a7dc6787646f2eb98d0',
60
+ subject = 'did:example:d23dd687a7dc6787646f2eb98d0',
61
+ issuanceDate = '2020-08-19T21:41:50Z',
62
+ } = {},
63
+ crypto
64
+ ) => ({
65
+ '@context': [
66
+ 'https://www.w3.org/2018/credentials/v1',
67
+ 'https://purl.imsglobal.org/spec/ob/v3p0/context.json',
68
+ 'https://w3id.org/security/suites/ed25519-2020/v1',
69
+ ],
70
+ id: `urn:uuid:${crypto.randomUUID()}`,
71
+ type: ['VerifiableCredential', 'OpenBadgeCredential'],
72
+ name: 'JFF x vc-edu PlugFest 2 Interoperability',
73
+ issuer: {
74
+ type: ['Profile'],
75
+ id: did,
76
+ name: 'Jobs for the Future (JFF)',
77
+ image: {
78
+ id: 'https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png',
79
+ type: 'Image',
80
+ },
81
+ },
82
+ issuanceDate: issuanceDate,
83
+ credentialSubject: {
84
+ type: ['AchievementSubject'],
85
+ id: subject,
86
+ achievement: {
87
+ id: `urn:uuid:${crypto.randomUUID()}`,
88
+ type: ['Achievement'],
89
+ name: 'JFF x vc-edu PlugFest 2 Interoperability',
90
+ description:
91
+ 'This credential solution supports the use of OBv3 and w3c Verifiable Credentials and is interoperable with at least two other solutions. This was demonstrated successfully during JFF x vc-edu PlugFest 2.',
92
+ criteria: {
93
+ narrative:
94
+ 'Solutions providers earned this badge by demonstrating interoperability between multiple providers based on the OBv3 candidate final standard, with some additional required fields. Credential issuers earning this badge successfully issued a credential into at least two wallets. Wallet implementers earning this badge successfully displayed credentials issued by at least two different credential issuers.',
95
+ },
96
+ image: {
97
+ id: 'https://w3c-ccg.github.io/vc-ed/plugfest-2-2022/images/JFF-VC-EDU-PLUGFEST2-badge-image.png',
98
+ type: 'Image',
99
+ },
100
+ },
101
+ },
102
+ }),
103
+ boost: (
104
+ {
105
+ did = 'did:example:d23dd687a7dc6787646f2eb98d0',
106
+ subject = 'did:example:d23dd687a7dc6787646f2eb98d0',
107
+ issuanceDate = '2020-08-19T21:41:50Z',
108
+ expirationDate,
109
+ boostName = 'Example Boost',
110
+ boostImage,
111
+ achievementId,
112
+ achievementType = 'Influencer',
113
+ achievementName = 'Awesome Badge',
114
+ achievementDescription = 'Awesome People Earn Awesome Badge',
115
+ achievementNarrative = 'Earned by being awesome.',
116
+ achievementImage = '',
117
+ attachments,
118
+ display,
119
+ familyTitles,
120
+ skills,
121
+ groupID = '',
122
+ evidence = [],
123
+ alignment,
124
+ source,
125
+ } = {},
126
+ crypto
127
+ ) => ({
128
+ '@context': [
129
+ 'https://www.w3.org/ns/credentials/v2',
130
+ 'https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json',
131
+ 'https://ctx.learncard.com/boosts/1.0.3.json',
132
+ ],
133
+ type: ['VerifiableCredential', 'OpenBadgeCredential', 'BoostCredential'],
134
+ id: `urn:uuid:${crypto.randomUUID()}`,
135
+ issuer: { id: did },
136
+ validFrom: issuanceDate,
137
+ ...(expirationDate && { validUntil: expirationDate }),
138
+ name: boostName,
139
+ credentialSubject: {
140
+ id: subject,
141
+ type: ['AchievementSubject'],
142
+ achievement: {
143
+ id: achievementId ?? `urn:uuid:${crypto.randomUUID()}`,
144
+ type: ['Achievement'],
145
+ achievementType: achievementType,
146
+ name: achievementName,
147
+ description: achievementDescription,
148
+ image: achievementImage,
149
+ criteria: {
150
+ narrative: achievementNarrative,
151
+ },
152
+ ...(alignment && { alignment }),
153
+ },
154
+ ...(source && { source }),
155
+ },
156
+ ...(Array.isArray(evidence) &&
157
+ evidence.length > 0 && {
158
+ evidence: evidence.map(e => ({
159
+ ...e,
160
+ type: e.type?.includes('EvidenceFile')
161
+ ? e.type
162
+ : [
163
+ 'Evidence',
164
+ 'EvidenceFile',
165
+ ...(e.type?.filter(t => t !== 'Evidence') || []),
166
+ ],
167
+ })),
168
+ }),
169
+ display,
170
+ familyTitles,
171
+ image: boostImage,
172
+ attachments,
173
+ skills,
174
+ groupID,
175
+ }),
176
+ boostID: (
177
+ {
178
+ did = 'did:example:d23dd687a7dc6787646f2eb98d0',
179
+ subject = 'did:example:d23dd687a7dc6787646f2eb98d0',
180
+ issuanceDate = '2020-08-19T21:41:50Z',
181
+ expirationDate,
182
+ boostName = 'Example Boost',
183
+ boostImage,
184
+ achievementId,
185
+ achievementType = 'Influencer',
186
+ achievementName = 'Awesome Badge',
187
+ achievementDescription = 'Awesome People Earn Awesome Badge',
188
+ achievementNarrative = 'Earned by being awesome.',
189
+ achievementImage = '',
190
+ address,
191
+ attachments,
192
+ skills,
193
+ display,
194
+ familyTitles,
195
+ boostID,
196
+ groupID = '',
197
+ evidence = [],
198
+ alignment,
199
+ source,
200
+ } = {},
201
+ crypto
202
+ ) => ({
203
+ '@context': [
204
+ 'https://www.w3.org/ns/credentials/v2',
205
+ 'https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json',
206
+ 'https://ctx.learncard.com/boosts/1.0.3.json',
207
+ 'https://ctx.learncard.com/boostIDs/1.0.0.json',
208
+ ],
209
+ type: ['VerifiableCredential', 'OpenBadgeCredential', 'BoostCredential', 'BoostID'],
210
+ id: `urn:uuid:${crypto.randomUUID()}`,
211
+ issuer: { id: did },
212
+ validFrom: issuanceDate,
213
+ ...(expirationDate && { validUntil: expirationDate }),
214
+ name: boostName,
215
+ credentialSubject: {
216
+ id: subject,
217
+ type: ['AchievementSubject'],
218
+ achievement: {
219
+ id: achievementId ?? `urn:uuid:${crypto.randomUUID()}`,
220
+ type: ['Achievement'],
221
+ achievementType: achievementType,
222
+ name: achievementName,
223
+ description: achievementDescription,
224
+ image: achievementImage,
225
+ criteria: {
226
+ narrative: achievementNarrative,
227
+ },
228
+ ...(alignment && { alignment }),
229
+ },
230
+ ...(source && { source }),
231
+ },
232
+ ...(Array.isArray(evidence) && evidence.length > 0 && { evidence }),
233
+ ...(address
234
+ ? {
235
+ address: {
236
+ type: ['Address'],
237
+ ...address,
238
+ ...(address.geo ? { geo: { type: ['GeoCoordinates'], ...address.geo } } : {}),
239
+ },
240
+ }
241
+ : {}),
242
+ ...(Array.isArray(evidence) &&
243
+ evidence.length > 0 && {
244
+ evidence: evidence.map(e => ({
245
+ ...e,
246
+ type: e.type?.includes('EvidenceFile')
247
+ ? e.type
248
+ : [
249
+ 'Evidence',
250
+ 'EvidenceFile',
251
+ ...(e.type?.filter(t => t !== 'Evidence') || []),
252
+ ],
253
+ })),
254
+ }),
255
+ display,
256
+ familyTitles,
257
+ image: boostImage,
258
+ attachments,
259
+ skills,
260
+ boostID,
261
+ groupID,
262
+ }),
263
+ delegate: (
264
+ {
265
+ did = 'did:example:d23dd687a7dc6787646f2eb98d0',
266
+ subject = 'did:example:d23dd687a7dc6787646f2eb98d0',
267
+ issuanceDate = new Date().toISOString(),
268
+ access = ['read'],
269
+ } = {},
270
+ crypto
271
+ ) => ({
272
+ '@context': [
273
+ 'https://www.w3.org/ns/credentials/v2',
274
+ 'https://ctx.learncard.com/delegates/1.0.0.json',
275
+ ],
276
+ type: ['VerifiableCredential', 'DelegateCredential'],
277
+ id: `urn:uuid:${crypto.randomUUID()}`,
278
+ issuer: { id: did },
279
+ validFrom: issuanceDate,
280
+ credentialSubject: { id: subject },
281
+ permissions: { statementAccess: access },
282
+ }),
283
+ };
@@ -0,0 +1,3 @@
1
+ export type DiscriminatedUnionize<T extends object = {}, K extends string = 'type'> = {
2
+ [Key in keyof T]: { [Key2 in K]: Key } & T[Key];
3
+ }[keyof T];
package/src/types.ts ADDED
@@ -0,0 +1,192 @@
1
+ import { UnsignedVC, VC, UnsignedVP } from '@learncard/types';
2
+ import { DiscriminatedUnionize } from './type.helpers';
3
+ import { Plugin } from '@learncard/core';
4
+
5
+ /** @group VC Templates Plugin */
6
+ export type BoostAttachment = {
7
+ type?: string;
8
+ title?: string;
9
+ url?: string;
10
+ fileName?: string;
11
+ fileSize?: string;
12
+ fileType?: string;
13
+ };
14
+
15
+ export type BoostSkills = {
16
+ category: string;
17
+ skill: string;
18
+ subskills: string[];
19
+ };
20
+
21
+ export type DisplayType = 'badge' | 'certificate' | 'id' | 'course' | 'award' | 'media';
22
+ export type PreviewType = 'default' | 'media';
23
+
24
+ /** @group VC Templates Plugin */
25
+ export type BoostDisplay = {
26
+ backgroundImage?: string;
27
+ backgroundColor?: string;
28
+
29
+ fadeBackgroundImage?: boolean;
30
+ repeatBackgroundImage?: boolean;
31
+
32
+ emoji: BoostEmoji;
33
+
34
+ displayType?: DisplayType;
35
+ previewType?: PreviewType;
36
+ };
37
+
38
+ export type BoostFamilyTitleOption = {
39
+ plural: string;
40
+ singular: string;
41
+ };
42
+
43
+ export type BoostFamilyTitles = {
44
+ guardians: BoostFamilyTitleOption[];
45
+ dependents: BoostFamilyTitleOption[];
46
+ };
47
+
48
+ export type BoostEmoji = {
49
+ activeSkinTone: string;
50
+ unified: string;
51
+ unifiedWithoutSkinTone: string;
52
+ names: string[];
53
+ imageUrl: string;
54
+ };
55
+
56
+ export type BoostID = {
57
+ fontColor?: string;
58
+ accentColor?: string;
59
+ backgroundImage?: string;
60
+ dimBackgroundImage?: boolean;
61
+ issuerThumbnail?: string;
62
+ showIssuerThumbnail?: boolean;
63
+ IDIssuerName?: string;
64
+
65
+ idThumbnail?: string;
66
+ accentFontColor?: string;
67
+ idBackgroundColor?: string;
68
+ repeatIdBackgroundImage: boolean;
69
+ idDescription?: string;
70
+ };
71
+
72
+ export type AddressSpec = {
73
+ streetAddress?: string | undefined;
74
+ addressLocality?: string | undefined;
75
+ addressRegion?: string | undefined;
76
+ addressCountry?: string | undefined;
77
+ postalCode?: string | undefined;
78
+ geo?: {
79
+ latitude?: number | undefined;
80
+ longitude?: number | undefined;
81
+ };
82
+ };
83
+
84
+ export type Source = {
85
+ type: string[];
86
+ id?: string;
87
+ name?: string;
88
+ description?: string;
89
+ url?: string;
90
+ image?: string;
91
+ address?: {
92
+ type?: string[];
93
+ addressLocality?: string;
94
+ addressRegion?: string;
95
+ addressCountry?: string;
96
+ };
97
+ };
98
+
99
+ export type Alignment = {
100
+ type: string[];
101
+ targetName?: string; // https://purl.imsglobal.org/spec/vc/ob/vocab.html#targetName
102
+ targetType?: string; // https://purl.imsglobal.org/spec/vc/ob/vocab.html#targetType
103
+ targetFramework?: string; // https://purl.imsglobal.org/spec/vc/ob/vocab.html#targetFramework
104
+ };
105
+
106
+ export interface Evidence {
107
+ id?: string;
108
+ type: [string, ...string[]]; // Changed from string[] to ensure at least one element
109
+ name?: string;
110
+ narrative?: string;
111
+ description?: string;
112
+ genre?: string;
113
+ audience?: string;
114
+
115
+ // Extended fields
116
+ fileName?: string;
117
+ fileType?: string;
118
+ fileSize?: string;
119
+ }
120
+
121
+ export type BoostTemplate = {
122
+ did?: string;
123
+ subject?: string;
124
+ issuanceDate?: string;
125
+ expirationDate?: string;
126
+ boostId?: string;
127
+ boostName?: string;
128
+ boostImage?: string;
129
+ achievementId?: string;
130
+ achievementType?: string;
131
+ achievementName?: string;
132
+ achievementDescription?: string;
133
+ achievementNarrative?: string;
134
+ achievementImage?: string;
135
+ attachments?: BoostAttachment[];
136
+ skills?: BoostSkills[];
137
+ display?: BoostDisplay;
138
+ familyTitles?: BoostFamilyTitles;
139
+ boostID?: BoostID;
140
+ address?: AddressSpec;
141
+ groupID?: string;
142
+ evidence?: Evidence[];
143
+ alignment?: Alignment[];
144
+ source?: Source;
145
+ };
146
+
147
+ /** @group VC Templates Plugin */
148
+ export type VcTemplates = {
149
+ basic: { did?: string; subject?: string; issuanceDate?: string };
150
+ achievement: {
151
+ did?: string;
152
+ subject?: string;
153
+ name?: string;
154
+ achievementName?: string;
155
+ description?: string;
156
+ criteriaNarrative?: string;
157
+ issuanceDate?: string;
158
+ };
159
+ jff2: { did?: string; subject?: string; issuanceDate?: string };
160
+ boost: BoostTemplate;
161
+ boostID: BoostTemplate;
162
+ delegate: {
163
+ did?: string;
164
+ subject?: string;
165
+ issuanceDate?: string;
166
+ access?: ('read' | 'write')[];
167
+ };
168
+ };
169
+
170
+ /** @group VC Templates Plugin */
171
+ export type NewCredentialFunction = (args?: DiscriminatedUnionize<VcTemplates>) => UnsignedVC;
172
+
173
+ /** @group VC Templates Plugin */
174
+ export type VCTemplatePluginDependentMethods = {
175
+ getSubjectDid?: (type: 'key') => string;
176
+ crypto: () => Crypto;
177
+ };
178
+
179
+ /** @group VC Templates Plugin */
180
+ export type VCTemplatePluginMethods = {
181
+ newCredential: NewCredentialFunction;
182
+ newPresentation: (credential: VC, args?: { did?: string }) => Promise<UnsignedVP>;
183
+ };
184
+
185
+ /** @group VC Templates Plugin */
186
+ export type VCTemplatePlugin = Plugin<
187
+ 'VC Templates',
188
+ any,
189
+ VCTemplatePluginMethods,
190
+ 'id',
191
+ VCTemplatePluginDependentMethods
192
+ >;
@@ -0,0 +1,48 @@
1
+ import { VC_TEMPLATES } from './templates';
2
+
3
+ import { VCTemplatePlugin } from './types';
4
+
5
+ /**
6
+ * @group Plugins
7
+ */
8
+ export const getVCTemplatesPlugin = (): VCTemplatePlugin => {
9
+ return {
10
+ name: 'VC Templates',
11
+ displayName: 'VC Templates',
12
+ description: 'Allows for the easy creation of VCs and VPs based on predefined templates',
13
+ methods: {
14
+ newCredential: (_learnCard, args = { type: 'basic' }) => {
15
+ const did = args.did || _learnCard.id.did();
16
+
17
+ if (!did) throw new Error('Could not get issuer did!');
18
+
19
+ const defaults = {
20
+ did,
21
+ subject: 'did:example:d23dd687a7dc6787646f2eb98d0',
22
+ issuanceDate: new Date().toISOString(),
23
+ };
24
+
25
+ const { type = 'basic', ...functionArgs } = args;
26
+
27
+ if (!(type in VC_TEMPLATES)) throw new Error('Invalid Test VC Type!');
28
+
29
+ return VC_TEMPLATES[type](
30
+ { ...defaults, ...functionArgs },
31
+ _learnCard.invoke.crypto()
32
+ );
33
+ },
34
+ newPresentation: async (_learnCard, credential, args = {}) => {
35
+ const did = args?.did || _learnCard.id.did();
36
+
37
+ if (!did) throw new Error('Could not get issuer did!');
38
+
39
+ return {
40
+ '@context': ['https://www.w3.org/ns/credentials/v2'],
41
+ type: ['VerifiablePresentation'],
42
+ holder: did,
43
+ verifiableCredential: credential,
44
+ };
45
+ },
46
+ },
47
+ };
48
+ };