Credential Issuance Tutorial
This tutorial provides a comprehensive guide to issuing verifiable credentials with TrustWeave. You’ll learn how to issue credentials, verify them, and handle the complete credential lifecycle.
1
2
3
4
5
6
dependencies {
implementation("org.trustweave:distribution-all:0.6.0")
// Or use individual modules:
// implementation("org.trustweave:trust:0.6.0")
// implementation("org.trustweave:testkit:0.6.0")
}
Result: Gives you the credential issuance APIs, DID methods, KMS abstractions, and in-memory implementations used throughout this tutorial.
Tip: The runnable quick-start sample (
./gradlew :TrustWeave-examples:runQuickStartSample) mirrors the core flows below. Clone it as a starting point before wiring more advanced credential logic.
Prerequisites
- Basic understanding of Kotlin
- Familiarity with coroutines
- Understanding of DIDs and Verifiable Credentials
- Completion of DID Operations Tutorial recommended
Table of Contents
- Understanding Credential Issuance
- Issuing Credentials
- Verifying Credentials
- Credential Lifecycle
- Advanced Credential Operations
- Error Handling
Understanding Credential Issuance
A verifiable credential is a tamper-evident credential that has authorship that can be cryptographically verified. The issuance process involves:
- Issuer creates a DID and keys
- Issuer creates credential with subject information
- Issuer signs credential with issuer key
- Holder receives credential
- Verifier verifies credential signature
What this does: Defines the credential issuance workflow.
Type-Safe Credential Types
TrustWeave uses strongly-typed CredentialType instances for credential types. You can use:
- Built-in types:
CredentialType.Education,CredentialType.Person,CredentialType.Degree, etc. - Convenience constants:
CredentialTypes.EDUCATION,CredentialTypes.PERSON(returnsCredentialTypeinstances) - Custom types:
CredentialType.Custom("MyCustomType")orCredentialType.fromString("MyCustomType")
Example:
1
2
3
4
5
6
7
credential {
type(CredentialType.Person) // Type-safe
// OR
type(CredentialTypes.PERSON) // Convenience constant
// OR
type(CredentialType.Custom("MyCustomCredential")) // Custom type
}
Outcome: Enables secure, verifiable credential issuance with cryptographic proof.
Issuing Credentials
Using TrustWeave Service API (Recommended)
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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.*
import java.time.Instant
// TrustWeave core
import org.trustweave.trust.TrustWeave
import org.trustweave.trust.dsl.credential.DidMethods
import org.trustweave.trust.dsl.credential.KeyAlgorithms
import org.trustweave.credential.model.ProofType
import org.trustweave.credential.model.CredentialType
import org.trustweave.credential.model.CredentialTypes
import org.trustweave.testkit.services.*
import org.trustweave.trust.types.getOrThrowDid
import org.trustweave.credential.results.getOrThrow
import org.trustweave.did.resolver.DidResolutionResult
import org.trustweave.did.resolver.errorMessage
import org.trustweave.did.identifiers.extractKeyId
import org.trustweave.did.identifiers.Did
import org.trustweave.credential.results.VerificationResult
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
credentials { defaultProofType(ProofType.Ed25519Signature2020) } // Using ProofType enum
}
// Create issuer DID
val issuerDid = trustWeave.createDid {
method(DidMethods.KEY)
algorithm(KeyAlgorithms.ED25519)
}.getOrThrowDid()
// Resolve DID to get key ID
val issuerDoc = when (val res = trustWeave.resolveDid(issuerDid)) {
is DidResolutionResult.Success -> res.document
else -> throw IllegalStateException(res.errorMessage ?: "Failed to resolve DID")
}
val issuerKeyId = issuerDoc.verificationMethod.firstOrNull()?.extractKeyId()
?: throw IllegalStateException("No verification method found")
// Issue credential using DSL
val credential = trustWeave.issue {
credential {
type(CredentialTypes.PERSON)
issuer(issuerDid)
subject {
id(Did("did:key:subject"))
"type" to "Person"
"name" to "Alice"
"email" to "alice@example.com"
}
issued(Instant.now())
}
signedBy(issuerDid)
}.getOrThrow()
println("Issued credential: ${credential.id}")
println("Issuer: ${credential.issuer}")
println("Subject: ${credential.credentialSubject}")
println("Proof: ${credential.proof}")
}
Outcome: Issues a verifiable credential with the issuer’s DID and cryptographic signature.
Issuing Credentials with Custom Options
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
import org.trustweave.trust.TrustWeave
import org.trustweave.trust.dsl.credential.DidMethods
import org.trustweave.trust.dsl.credential.KeyAlgorithms
import org.trustweave.credential.model.CredentialTypes
import org.trustweave.trust.types.DidCreationResult
import org.trustweave.did.resolver.DidResolutionResult
import org.trustweave.did.resolver.errorMessage
import org.trustweave.did.identifiers.extractKeyId
import org.trustweave.credential.results.getOrThrow
import org.trustweave.testkit.services.*
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.*
import java.time.Instant
import java.time.temporal.ChronoUnit
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
}
val didResult = trustWeave.createDid { method(DidMethods.KEY) }
val issuerDid = when (didResult) {
is DidCreationResult.Success -> didResult.did
else -> {
val errorMsg = when (didResult) {
is DidCreationResult.Failure.MethodNotRegistered ->
"Method '${didResult.method}' not registered. Available: ${didResult.availableMethods.joinToString()}"
is DidCreationResult.Failure.KeyGenerationFailed ->
"Key generation failed: ${didResult.reason}"
is DidCreationResult.Failure.DocumentCreationFailed ->
"Document creation failed: ${didResult.reason}"
is DidCreationResult.Failure.InvalidConfiguration ->
"Invalid configuration: ${didResult.reason}"
is DidCreationResult.Failure.Other ->
"Error: ${didResult.reason}"
}
println("Failed to create DID: $errorMsg")
return@runBlocking
}
}
val issuerDoc = when (val res = trustWeave.resolveDid(issuerDid)) {
is DidResolutionResult.Success -> res.document
else -> throw IllegalStateException(res.errorMessage ?: "Failed to resolve issuer DID")
}
val issuerKeyId = issuerDoc.verificationMethod.firstOrNull()?.extractKeyId()
?: throw IllegalStateException("No verification method found")
// Issue credential with custom expiration
val issuanceResult = trustWeave.issue {
credential {
type(CredentialTypes.PERSON)
issuer(issuerDid)
subject {
id("did:key:subject")
"type" to "Person"
"name" to "Alice"
"email" to "alice@example.com"
}
issued(Instant.now())
expires(Instant.now().plus(365, ChronoUnit.DAYS))
}
signedBy(issuerDid = issuerDid, keyId = issuerKeyId)
}
val credential = issuanceResult.getOrThrow()
println("Issued credential with expiration: ${credential.expirationDate}")
if (credential.credentialStatus != null) {
println("Status: ${credential.credentialStatus}")
}
}
Outcome: Issues a credential with custom expiration and status information.
Verifying Credentials
Verifying Credentials
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
import org.trustweave.trust.TrustWeave
import org.trustweave.trust.dsl.credential.DidMethods
import org.trustweave.trust.dsl.credential.KeyAlgorithms
import org.trustweave.credential.results.VerificationResult
import org.trustweave.testkit.services.*
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
}
val credential = /* previously issued credential */
val result = trustWeave.verify {
credential(credential)
}
when (result) {
is VerificationResult.Valid -> {
println("Credential is valid: ${result.credential.id}")
result.warnings.forEach { println("Warning: $it") }
}
is VerificationResult.Invalid -> {
println("Credential is invalid: ${result.allErrors.joinToString()}")
}
}
}
Outcome: Verifies a credential’s signature and validity.
Verifying with Custom Configuration
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
import org.trustweave.trust.TrustWeave
import org.trustweave.trust.dsl.credential.DidMethods
import org.trustweave.trust.dsl.credential.KeyAlgorithms
import org.trustweave.credential.results.VerificationResult
import org.trustweave.testkit.services.*
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
}
val credential = /* previously issued credential */
val result = trustWeave.verify {
credential(credential)
checkExpiration()
checkRevocation()
}
when (result) {
is VerificationResult.Valid -> println("Credential verified successfully")
is VerificationResult.Invalid -> println("Verification failed: ${result.allErrors.joinToString()}")
}
}
Outcome: Verifies a credential with custom verification configuration.
Credential Lifecycle
Credential Lifecycle Management
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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.*
// TrustWeave core
import org.trustweave.trust.TrustWeave
import org.trustweave.trust.dsl.credential.DidMethods
import org.trustweave.trust.dsl.credential.KeyAlgorithms
import org.trustweave.credential.*
import org.trustweave.testkit.services.*
import org.trustweave.did.identifiers.extractKeyId
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
credentials { defaultProofType(ProofType.Ed25519Signature2020) } // Using ProofType enum
}
val didResult = trustWeave.createDid {
method(DidMethods.KEY)
algorithm(KeyAlgorithms.ED25519)
}
val issuerDid = when (didResult) {
is DidCreationResult.Success -> didResult.did
else -> {
val errorMsg = when (didResult) {
is DidCreationResult.Failure.MethodNotRegistered ->
"Method '${didResult.method}' not registered. Available: ${didResult.availableMethods.joinToString()}"
is DidCreationResult.Failure.KeyGenerationFailed ->
"Key generation failed: ${didResult.reason}"
is DidCreationResult.Failure.DocumentCreationFailed ->
"Document creation failed: ${didResult.reason}"
is DidCreationResult.Failure.InvalidConfiguration ->
"Invalid configuration: ${didResult.reason}"
is DidCreationResult.Failure.Other ->
"Error: ${didResult.reason}"
}
println("Failed to create DID: $errorMsg")
return@runBlocking
}
}
val resolution = trustWeave.resolveDid(issuerDid)
val issuerDoc = when (resolution) {
is DidResolutionResult.Success -> resolution.document
else -> throw IllegalStateException("Failed to resolve issuer DID")
}
val issuerKeyId = issuerDoc.verificationMethod.firstOrNull()?.extractKeyId()
?: throw IllegalStateException("No verification method found")
// Issue credential
val issuanceResult = trustWeave.issue {
credential {
issuer(issuerDid)
subject {
id("did:key:subject")
}
issued(Instant.now())
}
signedBy(issuerDid = issuerDid, keyId = issuerKeyId)
}
val credential = when (issuanceResult) {
is IssuanceResult.Success -> {
println("Issued: ${issuanceResult.credential.id}")
issuanceResult.credential
}
else -> {
println("Error: ${issuanceResult.allErrors.joinToString("; ")}")
return@runBlocking
}
}
// Verify credential
val verificationResult = trustWeave.verify {
credential(credential)
}
when (verificationResult) {
is VerificationResult.Valid -> println("Valid: true")
is VerificationResult.Invalid.Expired -> println("Valid: false — expired at ${verificationResult.expiredAt}")
is VerificationResult.Invalid.Revoked -> println("Valid: false — revoked")
is VerificationResult.Invalid.InvalidProof -> println("Valid: false — invalid proof: ${verificationResult.reason}")
is VerificationResult.Invalid.InvalidIssuer -> println("Valid: false — issuer: ${verificationResult.reason}")
is VerificationResult.Invalid.UntrustedIssuer -> println("Valid: false — untrusted issuer: ${verificationResult.issuerDid.value}")
is VerificationResult.Invalid.SchemaValidationFailed -> println("Valid: false — schema: ${verificationResult.allErrors.joinToString()}")
is VerificationResult.Invalid.MultipleFailures -> println("Valid: false — ${verificationResult.allErrors.joinToString()}")
is VerificationResult.Invalid -> println("Valid: false — ${verificationResult.allErrors.joinToString()}")
}
// Note: Revocation is typically handled through credential status lists
// and checked during verification. See revocation documentation for details.
}
Outcome: Demonstrates the complete credential lifecycle from issuance to verification.
Advanced Credential Operations
Batch Credential Issuance
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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.*
// TrustWeave core
import org.trustweave.trust.TrustWeave
import org.trustweave.trust.dsl.credential.DidMethods
import org.trustweave.trust.dsl.credential.KeyAlgorithms
import org.trustweave.trust.types.DidCreationResult
import org.trustweave.did.resolver.DidResolutionResult
import org.trustweave.did.resolver.errorMessage
import org.trustweave.did.identifiers.extractKeyId
import org.trustweave.credential.*
import org.trustweave.testkit.services.*
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
}
val didResult = trustWeave.createDid { method(DidMethods.KEY) }
val issuerDid = when (didResult) {
is DidCreationResult.Success -> didResult.did
else -> {
val errorMsg = when (didResult) {
is DidCreationResult.Failure.MethodNotRegistered ->
"Method '${didResult.method}' not registered. Available: ${didResult.availableMethods.joinToString()}"
is DidCreationResult.Failure.KeyGenerationFailed ->
"Key generation failed: ${didResult.reason}"
is DidCreationResult.Failure.DocumentCreationFailed ->
"Document creation failed: ${didResult.reason}"
is DidCreationResult.Failure.InvalidConfiguration ->
"Invalid configuration: ${didResult.reason}"
is DidCreationResult.Failure.Other ->
"Error: ${didResult.reason}"
}
println("Failed to create DID: $errorMsg")
return@runBlocking
}
}
val issuerDoc = when (val res = trustWeave.resolveDid(issuerDid)) {
is DidResolutionResult.Success -> res.document
else -> throw IllegalStateException(res.errorMessage ?: "Failed to resolve issuer DID")
}
val issuerKeyId = issuerDoc.verificationMethod.firstOrNull()?.extractKeyId()
?: throw IllegalStateException("No verification method found")
// Issue credentials in batch using DSL
val subjects = listOf(
mapOf("id" to "did:key:alice", "name" to "Alice"),
mapOf("id" to "did:key:bob", "name" to "Bob"),
mapOf("id" to "did:key:charlie", "name" to "Charlie")
)
// Issue credentials in batch (one credential per subject)
val credentials = subjects.mapNotNull { subjectData ->
val issuanceResult = trustWeave.issue {
credential {
type("VerifiableCredential", "PersonCredential")
issuer(issuerDid)
subject {
id(subjectData["id"] as String)
subjectData.forEach { (key, value) ->
if (key != "id") {
key to value
}
}
}
}
signedBy(issuerDid = issuerDid, keyId = issuerKeyId)
}
when (issuanceResult) {
is IssuanceResult.Success -> issuanceResult.credential
is IssuanceResult.Failure -> {
println(
"Failed to issue credential for ${subjectData["id"]}: ${issuanceResult.allErrors.joinToString()}"
)
null
}
}
}
println("Issued ${credentials.size} credentials")
credentials.forEach { credential ->
println("Credential: ${credential.id} for ${credential.credentialSubject}")
}
}
Outcome: Demonstrates batch credential issuance for multiple subjects.
Credential Presentations
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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking
// TrustWeave core
import org.trustweave.trust.TrustWeave
import org.trustweave.trust.dsl.credential.DidMethods
import org.trustweave.trust.dsl.credential.KeyAlgorithms
import org.trustweave.trust.dsl.credential.presentationResult
import org.trustweave.trust.types.DidCreationResult
import org.trustweave.trust.types.PresentationResult
import org.trustweave.credential.requests.VerificationOptions
import org.trustweave.credential.results.VerificationResult
import org.trustweave.credential.model.vc.VerifiableCredential
import org.trustweave.testkit.services.*
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
}
val credentials: List<VerifiableCredential> = /* credentials from issuance steps */
val holderDidResult = trustWeave.createDid { method(DidMethods.KEY) }
val holderDid = when (holderDidResult) {
is DidCreationResult.Success -> holderDidResult.did
is DidCreationResult.Failure.MethodNotRegistered -> {
println("Holder DID: method not registered: ${holderDidResult.method}")
return@runBlocking
}
is DidCreationResult.Failure.KeyGenerationFailed -> {
println("Holder DID: key generation failed: ${holderDidResult.reason}")
return@runBlocking
}
is DidCreationResult.Failure.DocumentCreationFailed -> {
println("Holder DID: document creation failed: ${holderDidResult.reason}")
return@runBlocking
}
is DidCreationResult.Failure.InvalidConfiguration -> {
println("Holder DID: invalid configuration: ${holderDidResult.reason}")
return@runBlocking
}
is DidCreationResult.Failure.Other -> {
println("Holder DID: ${holderDidResult.reason}")
return@runBlocking
}
}
// Build presentation via TrustWeave DSL → CredentialService.createPresentation
val presentationOutcome = trustWeave.presentationResult {
credentials(credentials)
holder(holderDid)
challenge("tutorial-challenge-" + System.currentTimeMillis())
}
val presentation = when (presentationOutcome) {
is PresentationResult.Success -> presentationOutcome.presentation
is PresentationResult.Failure -> {
println("Presentation failed: ${presentationOutcome.allErrors.joinToString()}")
return@runBlocking
}
}
println("Created presentation: ${presentation.id}")
println("Holder: ${presentation.holder}")
println("Credentials: ${presentation.verifiableCredential.size}")
val credentialService = trustWeave.configuration.credentialService
if (credentialService == null) {
println("CredentialService not configured on TrustWeave")
return@runBlocking
}
when (
val verifyResult = credentialService.verifyPresentation(
presentation = presentation,
options = VerificationOptions(),
)
) {
is VerificationResult.Valid -> println("Presentation verification: valid")
is VerificationResult.Invalid -> {
println("Presentation verification: invalid — ${verifyResult.allErrors.joinToString()}")
}
}
}
Outcome: Creates a presentation with trustWeave.presentationResult { } and verifies it with CredentialService.verifyPresentation from trustWeave.configuration.credentialService.
Error Handling
Sealed Result Error Handling
TrustWeave uses sealed result types for all I/O operations, providing type-safe, exhaustive error handling:
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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.*
// TrustWeave core
import org.trustweave.trust.TrustWeave
import org.trustweave.trust.dsl.credential.DidMethods
import org.trustweave.trust.dsl.credential.KeyAlgorithms
import org.trustweave.trust.types.DidCreationResult
import org.trustweave.credential.results.IssuanceResult
import org.trustweave.credential.*
import org.trustweave.did.resolver.DidResolutionResult
import org.trustweave.did.resolver.errorMessage
import org.trustweave.did.identifiers.extractKeyId
import org.trustweave.testkit.services.*
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
}
// Create DID with error handling
val didResult = trustWeave.createDid { method(DidMethods.KEY) }
val issuerDid = when (didResult) {
is DidCreationResult.Success -> didResult.did
is DidCreationResult.Failure.MethodNotRegistered -> {
println("DID method not registered: ${didResult.method}")
println("Available methods: ${didResult.availableMethods.joinToString()}")
return@runBlocking
}
is DidCreationResult.Failure.KeyGenerationFailed -> {
println("Key generation failed: ${didResult.reason}")
return@runBlocking
}
is DidCreationResult.Failure.DocumentCreationFailed -> {
println("Document creation failed: ${didResult.reason}")
return@runBlocking
}
is DidCreationResult.Failure.InvalidConfiguration -> {
println("Invalid configuration: ${didResult.reason}")
return@runBlocking
}
is DidCreationResult.Failure.Other -> {
println("Error: ${didResult.reason}")
didResult.cause?.printStackTrace()
return@runBlocking
}
}
val issuerDoc = when (val res = trustWeave.resolveDid(issuerDid)) {
is DidResolutionResult.Success -> res.document
else -> throw IllegalStateException(res.errorMessage ?: "Failed to resolve issuer DID")
}
val issuerKeyId = issuerDoc.verificationMethod.firstOrNull()?.extractKeyId()
?: throw IllegalStateException("No verification method found")
// Issue credential with error handling
val issuanceResult = trustWeave.issue {
credential {
issuer(issuerDid)
subject {
id("did:key:subject")
}
issued(Instant.now())
}
signedBy(issuerDid = issuerDid, keyId = issuerKeyId)
}
when (issuanceResult) {
is IssuanceResult.Success -> {
println("Issued: ${issuanceResult.credential.id}")
}
is IssuanceResult.Failure.UnsupportedFormat -> {
println("Unsupported format: ${issuanceResult.format.value}")
println("Supported formats: ${issuanceResult.supportedFormats.joinToString { it.value }}")
}
is IssuanceResult.Failure.AdapterNotReady -> {
println("Adapter not ready: ${issuanceResult.reason ?: "Unknown reason"}")
}
is IssuanceResult.Failure.InvalidRequest -> {
println("Invalid request: field '${issuanceResult.field}' - ${issuanceResult.reason}")
}
is IssuanceResult.Failure.AdapterError -> {
println("Adapter error: ${issuanceResult.reason}")
issuanceResult.cause?.printStackTrace()
}
is IssuanceResult.Failure.MultipleFailures -> {
println("Multiple failures: ${issuanceResult.allErrors.joinToString("; ")}")
}
}
}
Outcome: Demonstrates exhaustive error handling using sealed result types with when expressions.
Next Steps
- Review Verifiable Credentials Concepts for deeper understanding
- See Wallet API Tutorial for credential storage
- Explore Verification Policies for advanced verification
- Check Creating Plugins to implement custom credential services
References
- W3C Verifiable Credentials Specification](https://www.w3.org/TR/vc-data-model/)
- TrustWeave Common Module](../modules/trustweave-common.md)
- TrustWeave Core API](../api-reference/core-api.md)