Create and Manage DIDs

This guide shows you how to create, resolve, update, and deactivate Decentralized Identifiers (DIDs) using TrustWeave.

Quick Example

Here’s a complete example that creates a DID, extracts the key ID, and uses it:

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
import org.trustweave.trust.dsl.trustWeave
import org.trustweave.trust.dsl.credential.*
import org.trustweave.testkit.services.*
import org.trustweave.did.identifiers.extractKeyId
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    trustWeave {
        keys {
            provider(IN_MEMORY)  // Auto-discovered via SPI
            algorithm(ED25519)
        }
        did {
            method(KEY) {  // Auto-discovered via SPI
                algorithm(ED25519)
            }
        }
        // KMS, DID methods, and CredentialService all auto-created!
    }.run {
        // Create a DID (returns DID and document directly)
        val (issuerDid, issuerDoc) = createDid().getOrThrow()
        
        // Extract key ID from document using type-safe extension function
        val issuerKeyId = issuerDoc.verificationMethod.firstOrNull()?.extractKeyId()
            ?: throw IllegalStateException("No verification method found")

        println("Created DID: ${issuerDid.value}")
        println("Key ID: $issuerKeyId")
    }
}

Expected Output:

1
2
Created DID: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
Key ID: key-1

Note: createDid() returns a type-safe Did object. Access the string value using .value property.

Step-by-Step Guide

Step 1: Configure TrustWeave

First, create a TrustWeave instance with DID method support:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import org.trustweave.trust.dsl.trustWeave
import org.trustweave.trust.dsl.credential.*
import org.trustweave.testkit.services.*

val trustWeave = trustWeave {
    keys {
        provider(IN_MEMORY)  // Auto-discovered via SPI (for testing; use production KMS in production)
        algorithm(ED25519)
    }
    did {
        method(KEY) {  // Auto-discovered via SPI
            algorithm(ED25519)
        }
        // Add more methods as needed
        method(WEB) {  // Auto-discovered via SPI
            domain("example.com")
        }
    }
    // KMS, DID methods, and CredentialService all auto-created!
}

Step 2: Create a DID

Create a DID using the default method (did:key) or specify a method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Simple: Use defaults (did:key, ED25519)
val did = trustWeave.createDid {
    method(KEY)
    algorithm(ED25519)
}

// Or even simpler with default method
val didSimple = trustWeave.createDid()  // Uses "key" method by default

// With custom method
val webDid = trustWeave.createDid {
    method(WEB)
    domain("example.com")
}

Step 3: Extract Key ID

Extract the key ID from the DID for signing operations:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.trustweave.did.identifiers.extractKeyId

val did = trustWeave.createDid { method(KEY) }

// Resolve DID to get verification method
import org.trustweave.did.resolver.DidResolutionResult
import org.trustweave.did.identifiers.extractKeyId

// Helper extension for resolution results
fun DidResolutionResult.getOrThrow() = when (this) {
    is DidResolutionResult.Success -> this.document
    else -> throw IllegalStateException("Failed to resolve DID: ${this.errorMessage ?: "Unknown error"}")
}

val document = trustWeave.resolveDid(did).getOrThrow()

// Extract key ID from verification method using type-safe extension function
val keyId = document.verificationMethod.firstOrNull()?.extractKeyId()
    ?: throw IllegalStateException("No verification method found")  // e.g., "key-1"

Step 4: Use the DID

Use the DID and key ID in credential operations:

1
2
3
4
5
6
7
val credential = trustWeave.issue {
    credential {
        issuer(did)
        // ... credential configuration
    }
    signedBy(did)  // keyId is automatically resolved
}

Common Patterns

Pattern 1: Create Multiple DIDs

Create DIDs for different roles (issuer, holder, verifier):

1
2
3
4
5
6
7
val issuerDid = trustWeave.createDid { method(KEY) }
val holderDid = trustWeave.createDid { method(KEY) }
val verifierDid = trustWeave.createDid { method(KEY) }

println("Issuer: $issuerDid")
println("Holder: $holderDid")
println("Verifier: $verifierDid")

Pattern 2: Create DID with Error Handling

Handle errors gracefully:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
val did = try {
    trustWeave.createDid {
        method(KEY)
        algorithm(ED25519)
    }
} catch (error: TrustWeaveException) {
    when (error) {
        is TrustWeaveException.PluginNotFound -> {
            println("DID method not registered: ${error.pluginId}")
            return@runBlocking
        }
        else -> {
            println("Unexpected error: ${error.message}")
            return@runBlocking
        }
    }
}

Pattern 3: Resolve a DID

Resolve a DID to get its document:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.trustweave.did.identifiers.Did

val did = Did("did:key:z6Mk...")
val result = trustWeave.resolveDid(did)

when (result) {
    is DidResolutionResult.Success -> {
        println("DID resolved: ${result.document.id}")
        println("Verification methods: ${result.document.verificationMethod.size}")
    }
    is DidResolutionResult.Failure.NotFound -> {
        println("DID not found: ${result.did.value}")
    }
    is DidResolutionResult.Failure.InvalidFormat -> {
        println("Invalid DID format: ${result.reason}")
    }
    is DidResolutionResult.Failure.MethodNotRegistered -> {
        println("DID method not registered: ${result.method}")
    }
    else -> {
        println("Resolution failed: ${result}")
    }
}

Pattern 4: Update a DID Document

Update a DID document to add services or verification methods:

1
2
3
4
5
6
7
8
9
10
11
import org.trustweave.did.identifiers.Did

val did = Did("did:key:example")
val updated = trustWeave.updateDid {
    did(did.value)  // DSL builder accepts string for convenience
    addService {
        id("${did.value}#service-1")
        type("LinkedDomains")
        endpoint("https://example.com/service")
    }
}

Pattern 5: Deactivate a DID

Deactivate a DID when it’s no longer needed:

1
2
3
4
5
6
7
8
9
10
11
import org.trustweave.did.identifiers.Did

// Note: Deactivation depends on the DID method implementation
// For did:key, deactivation is typically not supported as it's stateless
// For other methods like did:web or did:ion, use the method-specific deactivation API

val did = Did("did:key:example")
val deactivated = trustWeave.deactivateDid(did)
if (deactivated) {
    println("DID deactivated successfully")
}

DID Methods

TrustWeave supports multiple DID methods. Choose based on your needs:

Method Use Case Network Required
did:key Testing, simple use cases No
did:web Web-based identity Yes (HTTPS)
did:ion Microsoft ION network Yes
did:ethr Ethereum-based identity Yes (Ethereum)
did:polygon Polygon-based identity Yes (Polygon)

See DID Method Integrations for complete list.

Error Handling

DID operations now return sealed result types instead of throwing exceptions. This provides 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
import org.trustweave.trust.types.DidCreationResult

val didResult = trustWeave.createDid { 
    method(KEY) 
}

when (didResult) {
    is DidCreationResult.Success -> {
        println("Created DID: ${didResult.did.value}")
        // Use didResult.did and didResult.document
    }
    is DidCreationResult.Failure.MethodNotRegistered -> {
        println("DID method not found: ${didResult.method}")
        println("Available methods: ${didResult.availableMethods.joinToString()}")
    }
    is DidCreationResult.Failure.KeyGenerationFailed -> {
        println("Key generation failed: ${didResult.reason}")
        didResult.cause?.printStackTrace()
    }
    is DidCreationResult.Failure.DocumentCreationFailed -> {
        println("Document creation failed: ${didResult.reason}")
    }
    is DidCreationResult.Failure.InvalidConfiguration -> {
        println("Invalid configuration: ${didResult.reason}")
    }
    is DidCreationResult.Failure.Other -> {
        println("Error: ${didResult.reason}")
        didResult.cause?.printStackTrace()
    }
}

For tests and examples, you can use the getOrFail() helper:

1
2
3
4
import org.trustweave.testkit.getOrFail

val did = trustWeave.createDid { method(KEY) }.getOrFail()
// Throws AssertionError on failure (suitable for tests/examples only)

Note: All I/O operations (createDid, issue, updateDid, rotateKey, wallet, revoke) now return sealed result types for exhaustive error handling. resolveDid() also returns a sealed result type.

API Reference

For complete API documentation, see:

See Also

Next Steps

Ready to issue credentials?

Want to learn more?


This site uses Just the Docs, a documentation theme for Jekyll.