Professional Identity Wallet Scenario
This guide demonstrates how professionals can build a comprehensive digital identity wallet using TrustWeave. You’ll learn how to manage multiple credentials (education, work experience, certifications), organize them effectively, and create targeted presentations for different purposes.
What You’ll Build
By the end of this tutorial, you’ll have:
- ✅ Created a professional identity wallet
- ✅ Stored multiple types of credentials (education, work, certifications)
- ✅ Organized credentials with collections and tags
- ✅ Created targeted presentations for different scenarios
- ✅ Implemented selective disclosure for privacy
- ✅ Built a credential verification system
Big Picture & Significance
The Professional Identity Challenge
Professionals accumulate credentials throughout their careers, but managing them effectively is challenging. Traditional systems scatter credentials across platforms, make verification difficult, and don’t respect privacy.
Industry Context:
- Market Size: Professional credential market growing rapidly with digital transformation
- Credential Volume: Professionals accumulate 10+ credentials over their careers
- Verification Costs: Employers spend significant time verifying credentials
- Privacy Concerns: Sharing all credentials reveals too much information
- Portability: Credentials tied to specific platforms limit mobility
Why This Matters:
- Professional Control: Professionals own and control their credentials
- Privacy: Selective disclosure protects sensitive information
- Efficiency: Unified credential management saves time
- Verification: Instant verification without intermediaries
- Portability: Credentials work across platforms and borders
- Career Mobility: Easy credential sharing enables career opportunities
The Credential Management Problem
Traditional credential systems face critical issues:
- Scattered Storage: Credentials stored in different places
- Verification Difficulty: Employers must contact multiple sources
- Privacy Issues: Sharing everything reveals too much
- No Portability: Tied to specific platforms or institutions
- No Organization: Hard to find and manage credentials
Value Proposition
Problems Solved
- Unified Storage: All credentials in one wallet
- Easy Organization: Collections, tags, and metadata
- Privacy Control: Selective disclosure for different contexts
- Instant Verification: Cryptographic proof without intermediaries
- Portability: Credentials work across platforms
- Professional Control: Professionals own their credentials
- Efficiency: Streamlined credential management
Business Benefits
For Professionals:
- Control: Own and control all credentials
- Privacy: Share only necessary information
- Convenience: Access credentials from any device
- Portability: Credentials work everywhere
- Organization: Easy credential management
For Employers:
- Speed: Instant verification
- Trust: Cryptographic proof of authenticity
- Efficiency: Streamlined hiring process
- Cost: Reduced verification costs
For Credential Issuers:
- Efficiency: Automated credential issuance
- Compliance: Meet regulatory requirements
- Reputation: Enhanced trust through verifiable credentials
ROI Considerations
- Time Savings: 80% reduction in credential management time
- Verification Costs: 70-90% reduction in verification costs
- Privacy: Enhanced privacy protection
- Career Opportunities: Easier credential sharing enables opportunities
Understanding the Problem
Professionals accumulate many credentials throughout their careers:
- Education: Degrees, certificates, courses
- Work Experience: Employment history, roles, achievements
- Certifications: Professional licenses, industry certifications
- Skills: Verified skills and competencies
Managing these credentials is challenging:
- Scattered: Credentials are stored in different places
- Hard to verify: Employers must contact multiple sources
- Privacy concerns: Sharing everything reveals too much
- Not portable: Tied to specific platforms or institutions
TrustWeave solves this by providing:
- Unified storage: All credentials in one wallet
- Easy organization: Collections, tags, and metadata
- Privacy control: Selective disclosure for different contexts
- Instant verification: Cryptographic proof without intermediaries
How It Works: Professional Identity Flow
flowchart TD
A["Multiple Issuers<br/>Universities<br/>Employers<br/>Certification Bodies<br/>Skills Verifiers"] -->|issue credentials| B["Professional Wallet<br/>Education Collection<br/>Work Collection<br/>Certifications Collection"]
B -->|creates presentations| C["Targeted Presentations<br/>Job Application selective<br/>Professional Profile public<br/>Contract Negotiation detailed"]
style A fill:#1976d2,stroke:#0d47a1,stroke-width:2px,color:#fff
style B fill:#f57c00,stroke:#e65100,stroke-width:2px,color:#fff
style C fill:#388e3c,stroke:#1b5e20,stroke-width:2px,color:#fff
Prerequisites
- Java 21+
- Kotlin 2.2.0+
- Gradle 8.5+
- Basic understanding of Kotlin and coroutines
Step 1: Add Dependencies
Add TrustWeave dependencies to your build.gradle.kts. These modules cover DID creation, wallet storage, and the in-memory tooling used for professional identity flows.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
dependencies {
// Core TrustWeave modules
implementation("com.trustweave:trustweave-core:1.0.0-SNAPSHOT")
implementation("com.trustweave:trustweave-json:1.0.0-SNAPSHOT")
implementation("com.trustweave:trustweave-kms:1.0.0-SNAPSHOT")
implementation("com.trustweave:trustweave-did:1.0.0-SNAPSHOT")
implementation("com.trustweave:trustweave-anchor:1.0.0-SNAPSHOT")
// Test kit for in-memory implementations
implementation("com.trustweave:trustweave-testkit:1.0.0-SNAPSHOT")
// Kotlinx Serialization
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
}
Result: Syncing these dependencies prepares Gradle to compile every example below without further configuration.
Step 2: Complete Example
Here’s the full professional identity wallet flow. Execute it once to see the end-to-end experience before exploring the step-by-step explanations.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
import com.trustweave.trust.TrustWeave
import com.trustweave.trust.dsl.credential.DidMethods
import com.trustweave.trust.dsl.credential.KeyAlgorithms
import com.trustweave.trust.types.ProofType
import com.trustweave.trust.dsl.credential.credential
import com.trustweave.testkit.services.TestkitDidMethodFactory
import com.trustweave.testkit.services.TestkitWalletFactory
import com.trustweave.testkit.kms.InMemoryKeyManagementService
import kotlinx.coroutines.runBlocking
import java.time.Instant
fun main() = runBlocking {
println("=== Professional Identity Wallet Scenario ===\n")
// Step 1: Configure Trust Layer
println("Step 1: Setting up services...")
val kms = InMemoryKeyManagementService()
val kmsRef = kms
val trustWeave = TrustWeave.build {
factories(
didMethodFactory = TestkitDidMethodFactory(),
walletFactory = TestkitWalletFactory()
)
keys {
custom(kmsRef)
signer { data, keyId ->
kmsRef.sign(com.trustweave.core.types.KeyId(keyId), data)
}
}
did {
method(DidMethods.KEY) {
algorithm(KeyAlgorithms.ED25519)
}
}
credentials {
defaultProofType(ProofType.Ed25519Signature2020)
}
}
// Create professional DID using DSL
import com.trustweave.trust.types.DidCreationResult
import com.trustweave.trust.types.WalletCreationResult
val professionalDidResult = trustWeave.createDid {
method(DidMethods.KEY)
algorithm(KeyAlgorithms.ED25519)
}
val professionalDid = when (professionalDidResult) {
is DidCreationResult.Success -> {
println("Professional DID: ${professionalDidResult.did.value}")
professionalDidResult.did
}
else -> {
println("Failed to create professional DID: ${professionalDidResult.reason}")
return@runBlocking
}
}
// Step 2: Create professional wallet
println("\nStep 2: Creating professional wallet...")
val walletResult = trustWeave.wallet {
id("professional-wallet-${professionalDid.value.substringAfterLast(":")}")
holder(professionalDid.value)
enableOrganization()
enablePresentation()
}
val wallet = when (walletResult) {
is WalletCreationResult.Success -> {
println("Wallet created: ${walletResult.wallet.walletId}")
walletResult.wallet
}
else -> {
println("Failed to create wallet: ${walletResult.reason}")
return@runBlocking
}
}
// Step 3: Store education credentials
println("\nStep 3: Storing education credentials...")
val bachelorDegree = createEducationCredential(
issuerDid = "did:key:university",
holderDid = professionalDid.value,
degreeType = "Bachelor",
field = "Computer Science",
institution = "Tech University",
year = "2018"
)
val bachelorId = wallet.store(bachelorDegree)
val masterDegree = createEducationCredential(
issuerDid = "did:key:university",
holderDid = professionalDid.value,
degreeType = "Master",
field = "Software Engineering",
institution = "Tech University",
year = "2020"
)
val masterId = wallet.store(masterDegree)
println("Stored ${wallet.list().size} education credentials")
// Step 4: Store work experience credentials
println("\nStep 4: Storing work experience credentials...")
val job1 = createEmploymentCredential(
issuerDid = "did:key:company1",
holderDid = professionalDid.value,
company = "Tech Corp",
role = "Software Engineer",
startDate = "2020-06-01",
endDate = "2022-12-31",
achievements = listOf(
"Led development of microservices architecture",
"Mentored 3 junior developers",
"Increased system performance by 40%"
)
)
val job1Id = wallet.store(job1)
val job2 = createEmploymentCredential(
issuerDid = "did:key:company2",
holderDid = professionalDid.value,
company = "Innovation Labs",
role = "Senior Software Engineer",
startDate = "2023-01-01",
endDate = null, // Current position
achievements = listOf(
"Architected cloud-native platform",
"Reduced infrastructure costs by 30%"
)
)
val job2Id = wallet.store(job2)
println("Stored ${wallet.list().size} total credentials")
// Step 5: Store certifications
println("\nStep 5: Storing certifications...")
val awsCert = createCertificationCredential(
issuerDid = "did:key:aws",
holderDid = professionalDid.value,
certificationName = "AWS Certified Solutions Architect",
issuer = "Amazon Web Services",
issueDate = "2021-03-15",
expirationDate = "2024-03-15",
credentialId = "AWS-12345"
)
val awsCertId = wallet.store(awsCert)
val kubernetesCert = createCertificationCredential(
issuerDid = "did:key:cncf",
holderDid = professionalDid.value,
certificationName = "Certified Kubernetes Administrator",
issuer = "Cloud Native Computing Foundation",
issueDate = "2022-06-20",
expirationDate = "2025-06-20",
credentialId = "CKA-67890"
)
val k8sCertId = wallet.store(kubernetesCert)
println("Stored ${wallet.list().size} total credentials")
// Step 6: Organize credentials
println("\nStep 6: Organizing credentials...")
// Create collections
val educationCollection = wallet.createCollection(
name = "Education",
description = "Academic degrees and certificates"
)
val workCollection = wallet.createCollection(
name = "Work Experience",
description = "Employment history and achievements"
)
val certificationsCollection = wallet.createCollection(
name = "Certifications",
description = "Professional licenses and certifications"
)
// Add credentials to collections
wallet.addToCollection(bachelorId, educationCollection)
wallet.addToCollection(masterId, educationCollection)
wallet.addToCollection(job1Id, workCollection)
wallet.addToCollection(job2Id, workCollection)
wallet.addToCollection(awsCertId, certificationsCollection)
wallet.addToCollection(k8sCertId, certificationsCollection)
// Add tags
wallet.tagCredential(bachelorId, setOf("education", "degree", "bachelor", "computer-science"))
wallet.tagCredential(masterId, setOf("education", "degree", "master", "software-engineering"))
wallet.tagCredential(job1Id, setOf("work", "employment", "software-engineer", "completed"))
wallet.tagCredential(job2Id, setOf("work", "employment", "senior-engineer", "current"))
wallet.tagCredential(awsCertId, setOf("certification", "cloud", "aws", "active"))
wallet.tagCredential(k8sCertId, setOf("certification", "kubernetes", "cncf", "active"))
// Add metadata
wallet.addMetadata(bachelorId, mapOf(
"gpa" to "3.8",
"honors" to "Summa Cum Laude"
))
wallet.addMetadata(job1Id, mapOf(
"salary_range" to "confidential",
"team_size" to 8
))
println("Created ${wallet.listCollections().size} collections")
println("Total tags: ${wallet.getAllTags().size}")
// Step 7: Query credentials
println("\nStep 7: Querying credentials...")
// Find all active certifications
val activeCerts = wallet.query {
byType("CertificationCredential")
notExpired()
valid()
}
println("Active certifications: ${activeCerts.size}")
// Find current employment
val currentJobs = wallet.query {
byType("EmploymentCredential")
// Add custom filter for current positions
}
println("Current positions: ${currentJobs.size}")
// Find credentials by tag
val cloudCredentials = wallet.findByTag("cloud")
println("Cloud-related credentials: ${cloudCredentials.size}")
// Step 8: Create targeted presentations
println("\nStep 8: Creating targeted presentations...")
// Presentation for job application (selective disclosure)
val jobApplicationPresentation = wallet.createSelectiveDisclosure(
credentialIds = listOf(masterId, job1Id, job2Id, awsCertId),
disclosedFields = listOf(
"degree.field",
"degree.institution",
"degree.year",
"employment.company",
"employment.role",
"employment.startDate",
"certification.name",
"certification.issuer"
// GPA, salary, and other sensitive info NOT disclosed
),
holderDid = professionalDid.value,
options = PresentationOptions(
holderDid = professionalDid.value,
proofType = "Ed25519Signature2020",
challenge = "job-application-${Instant.now().toEpochMilli()}"
)
)
println("Job application presentation created with ${jobApplicationPresentation.verifiableCredential.size} credentials")
// Presentation for professional profile (public)
val profilePresentation = wallet.createPresentation(
credentialIds = listOf(masterId, job2Id, awsCertId, k8sCertId),
holderDid = professionalDid.value,
options = PresentationOptions(
holderDid = professionalDid.value,
proofType = "Ed25519Signature2020"
)
)
println("Professional profile presentation created")
// Step 9: Archive old credentials
println("\nStep 9: Archiving old credentials...")
// Archive first job since it's completed
wallet.archive(job1Id)
val archived = wallet.getArchived()
println("Archived credentials: ${archived.size}")
// Step 10: Wallet statistics
println("\nStep 10: Wallet statistics...")
val stats = wallet.getStatistics()
println("""
Total credentials: ${stats.totalCredentials}
Valid credentials: ${stats.validCredentials}
Expired credentials: ${stats.expiredCredentials}
Collections: ${stats.collectionsCount}
Tags: ${stats.tagsCount}
Archived: ${stats.archivedCount}
""".trimIndent())
// Step 11: Export for different purposes
println("\nStep 11: Exporting credentials for different purposes...")
// Export education credentials only
val educationCreds = wallet.getCredentialsInCollection(educationCollection)
println("Education credentials available for export: ${educationCreds.size}")
// Export active certifications
val activeCertifications = wallet.query {
byType("CertificationCredential")
notExpired()
}
println("Active certifications available: ${activeCertifications.size}")
println("\n=== Scenario Complete ===")
}
fun createEducationCredential(
issuerDid: String,
holderDid: String,
degreeType: String,
field: String,
institution: String,
year: String
): VerifiableCredential {
return credential {
id("https://example.edu/credentials/${degreeType.lowercase()}-${holderDid.substringAfterLast(":")}")
type(CredentialType.Education, CredentialType.Custom("${degreeType}DegreeCredential"))
issuer(issuerDid)
subject {
id(holderDid)
"degree" {
"type" to degreeType
"field" to field
"institution" to institution
"year" to year
}
}
issued(Instant.now())
// Education credentials typically don't expire
}
}
fun createEmploymentCredential(
issuerDid: String,
holderDid: String,
company: String,
role: String,
startDate: String,
endDate: String?,
achievements: List<String>
): VerifiableCredential {
return credential {
// Sanitize company name for URI (replace spaces and special chars with hyphens)
val sanitizedCompany = company.lowercase().replace(Regex("[^a-z0-9]+"), "-")
id("https://example.com/employment/${sanitizedCompany}-${holderDid.substringAfterLast(":")}")
type("EmploymentCredential")
issuer(issuerDid)
subject {
id(holderDid)
"employment" {
"company" to company
"role" to role
"startDate" to startDate
if (endDate != null) {
"endDate" to endDate
} else {
"current" to true
}
"achievements" to achievements
}
}
issued(Instant.now())
}
}
fun createCertificationCredential(
issuerDid: String,
holderDid: String,
certificationName: String,
issuer: String,
issueDate: String,
expirationDate: String,
credentialId: String
): VerifiableCredential {
// Parse dates - handle both ISO format with time and date-only format
val parsedIssueDate = if (issueDate.contains("T")) {
Instant.parse(issueDate)
} else {
Instant.parse("${issueDate}T00:00:00Z")
}
val parsedExpirationDate = if (expirationDate.contains("T")) {
Instant.parse(expirationDate)
} else {
Instant.parse("${expirationDate}T00:00:00Z")
}
return credential {
id("https://example.com/certifications/$credentialId")
type("CertificationCredential")
issuer(issuerDid)
subject {
id(holderDid)
"certification" {
"name" to certificationName
"issuer" to issuer
"issueDate" to issueDate
"expirationDate" to expirationDate
"credentialId" to credentialId
}
}
issued(parsedIssueDate)
expires(parsedExpirationDate)
}
}
Key Features Demonstrated
1. Multi-Type Credential Management
Store different types of credentials in one wallet:
1
2
3
4
5
6
7
8
// Education
val degreeId = wallet.store(bachelorDegree)
// Work Experience
val jobId = wallet.store(employmentCredential)
// Certifications
val certId = wallet.store(certificationCredential)
2. Organization with Collections
Group related credentials:
1
2
3
4
5
6
7
val educationCollection = wallet.createCollection("Education")
val workCollection = wallet.createCollection("Work Experience")
val certCollection = wallet.createCollection("Certifications")
wallet.addToCollection(degreeId, educationCollection)
wallet.addToCollection(jobId, workCollection)
wallet.addToCollection(certId, certCollection)
3. Tagging for Easy Discovery
Tag credentials for flexible querying:
1
2
3
4
5
6
wallet.tagCredential(degreeId, setOf("education", "degree", "bachelor"))
wallet.tagCredential(jobId, setOf("work", "employment", "current"))
wallet.tagCredential(certId, setOf("certification", "cloud", "active"))
// Find by tag
val cloudCreds = wallet.findByTag("cloud")
4. Selective Disclosure
Share only what’s needed:
1
2
3
4
5
6
7
8
9
10
11
12
val presentation = wallet.createSelectiveDisclosure(
credentialIds = listOf(degreeId, jobId),
disclosedFields = listOf(
"degree.field",
"degree.institution",
"employment.company",
"employment.role"
// GPA, salary, etc. NOT disclosed
),
holderDid = holderDid,
options = PresentationOptions(...)
)
5. Advanced Querying
Find credentials efficiently:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Active certifications
val activeCerts = wallet.query {
byType("CertificationCredential")
notExpired()
valid()
}
// Current employment
val currentJobs = wallet.query {
byType("EmploymentCredential")
// Add custom logic for current positions
}
// By issuer
val universityCreds = wallet.query {
byIssuer("did:key:university")
}
Real-World Use Cases
Job Application
Create a presentation showing relevant credentials:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fun createJobApplicationPresentation(
wallet: Wallet,
jobRequirements: List<String>
): VerifiablePresentation {
// Find relevant credentials based on job requirements
val relevantCreds = findRelevantCredentials(wallet, jobRequirements)
return wallet.createSelectiveDisclosure(
credentialIds = relevantCreds.map { it.id!! },
disclosedFields = listOf(
"degree.field",
"degree.institution",
"employment.role",
"certification.name"
),
holderDid = wallet.holderDid,
options = PresentationOptions(
holderDid = wallet.holderDid,
challenge = "job-application-${UUID.randomUUID()}"
)
)
}
Professional Profile
Create a public profile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fun createProfessionalProfile(wallet: Wallet): VerifiablePresentation {
val publicCreds = wallet.query {
byTypes("EducationCredential", "CertificationCredential")
valid()
}
return wallet.createPresentation(
credentialIds = publicCreds.mapNotNull { it.id },
holderDid = wallet.holderDid,
options = PresentationOptions(
holderDid = wallet.holderDid,
proofType = "Ed25519Signature2020"
)
)
}
Contract Negotiation
Share detailed credentials:
1
2
3
4
5
6
7
8
9
10
11
12
fun createDetailedPresentation(wallet: Wallet): VerifiablePresentation {
val allCreds = wallet.list()
return wallet.createPresentation(
credentialIds = allCreds.mapNotNull { it.id },
holderDid = wallet.holderDid,
options = PresentationOptions(
holderDid = wallet.holderDid,
challenge = "contract-negotiation-${UUID.randomUUID()}"
)
)
}
Best Practices
- Organize Early: Create collections and tags when storing credentials
- Use Selective Disclosure: Only share what’s necessary
- Archive Old Credentials: Keep history but hide from normal queries
- Tag Consistently: Use consistent tagging conventions
- Verify Before Storing: Always verify credentials before storing
- Monitor Expiration: Regularly check for expired credentials
Benefits
- Unified Management: All credentials in one place
- Easy Organization: Collections and tags for quick access
- Privacy Control: Selective disclosure for different contexts
- Instant Verification: Cryptographic proof without intermediaries
- Portable: You control your credentials
Next Steps
- Learn about Wallet API Tutorial
- Explore Academic Credentials Scenario
- Check out Verifiable Credentials