DID Operations Tutorial

This tutorial provides a comprehensive guide to performing DID operations with TrustWeave. You’ll learn how to create, resolve, update, and deactivate DIDs using various DID methods.

1
2
3
4
5
6
dependencies {
    implementation("com.trustweave:trustweave-did:1.0.0-SNAPSHOT")
    implementation("com.trustweave:trustweave-kms:1.0.0-SNAPSHOT")
    implementation("com.trustweave:trustweave-common:1.0.0-SNAPSHOT")
    implementation("com.trustweave:trustweave-testkit:1.0.0-SNAPSHOT")
}

Result: Gives you the DID registry, DID method interfaces, 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 DID logic.

Prerequisites

  • Basic understanding of Kotlin
  • Familiarity with coroutines
  • Understanding of DIDs

Table of Contents

  1. Understanding DID Methods
  2. Creating DIDs
  3. Resolving DIDs
  4. Updating DIDs
  5. Deactivating DIDs
  6. Working with Multiple DID Methods
  7. Advanced DID Operations

Understanding DID Methods

A DID method is an implementation of the DidMethod interface that supports a specific DID method (e.g., did:key, did:web, did:ion). Each DID method has its own creation, resolution, update, and deactivation logic.

1
2
3
4
5
6
7
8
9
import com.trustweave.did.*

interface DidMethod {
    val method: String
    suspend fun createDid(options: DidCreationOptions): DidDocument
    suspend fun resolveDid(did: String): DidResolutionResult
    suspend fun updateDid(did: String, updater: (DidDocument) -> DidDocument): DidDocument
    suspend fun deactivateDid(did: String): Boolean
}

What this does: Defines the contract for DID operations that all DID method implementations must fulfill.

Outcome: Enables TrustWeave to support multiple DID methods through a unified interface.

Creating DIDs

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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking

// TrustWeave core
import com.trustweave.trust.TrustWeave
import com.trustweave.trust.dsl.credential.DidMethods
import com.trustweave.trust.dsl.credential.KeyAlgorithms
// Note: TestkitDidMethodFactory is for testing/tutorials only
// In production, use appropriate DID method factories
import com.trustweave.testkit.services.*

fun main() = runBlocking {
    // Build TrustWeave instance with testkit factories (for tutorials)
    val trustWeave = TrustWeave.build {
        factories(
            didMethodFactory = TestkitDidMethodFactory()  // Test-only factory
        )
        keys {
            provider("inMemory")
            algorithm(KeyAlgorithms.ED25519)
        }
        did {
            method(DidMethods.KEY) {
                algorithm(KeyAlgorithms.ED25519)
            }
        }
    }

    // Create DID using did:key method (returns sealed result)
    import com.trustweave.trust.types.DidCreationResult
    
    val didResult = trustWeave.createDid {
        method(DidMethods.KEY)
        algorithm(KeyAlgorithms.ED25519)
    }
    
    when (didResult) {
        is DidCreationResult.Success -> {
            println("Created DID: ${didResult.did.value}")
        }
        else -> {
            println("DID creation failed: ${didResult.reason}")
        }
    }
}

Outcome: Creates a DID using the configured DID method. Returns a type-safe Did object - access the string value using .value.

Creating DIDs with Specific Methods

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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking

// TrustWeave core
import com.trustweave.trust.TrustWeave
import com.trustweave.trust.dsl.credential.DidMethods
import com.trustweave.trust.dsl.credential.KeyAlgorithms
// Note: TestkitDidMethodFactory is for testing/tutorials only
// In production, use appropriate DID method factories
import com.trustweave.testkit.services.*

fun main() = runBlocking {
    // Build TrustWeave instance with testkit factories (for tutorials)
    val trustWeave = TrustWeave.build {
        factories(didMethodFactory = TestkitDidMethodFactory())  // Test-only factory
        keys { provider("inMemory"); algorithm(KeyAlgorithms.ED25519) }
        did {
            method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) }
            method(DidMethods.WEB) { domain("example.com") }
        }
    }

    // Create DID with did:key method
    val keyDidResult = trustWeave.createDid {
        method(DidMethods.KEY)
        algorithm(KeyAlgorithms.ED25519)
    }
    
    val keyDid = when (keyDidResult) {
        is DidCreationResult.Success -> keyDidResult.did
        else -> {
            println("Failed to create key DID: ${keyDidResult.reason}")
            return@runBlocking
        }
    }

    // Create DID with did:web method
    val webDidResult = trustWeave.createDid {
        method(DidMethods.WEB)
        domain("example.com")
    }
    
    val webDid = when (webDidResult) {
        is DidCreationResult.Success -> webDidResult.did
        else -> {
            println("Failed to create web DID: ${webDidResult.reason}")
            return@runBlocking
        }
    }

    println("Key DID: ${keyDid.value}")
    println("Web DID: ${webDid.value}")
}

Outcome: Creates DIDs using specific DID methods with custom configuration options.

Using DID Method Registry

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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking

// TrustWeave core
import com.trustweave.did.*
import com.trustweave.kms.*
import com.trustweave.testkit.kms.InMemoryKeyManagementService

fun main() = runBlocking {
    // Create KMS
    val kms = InMemoryKeyManagementService()

    // Create DID method registry
    val registry = DidMethodRegistry()

    // Register did:key method
    val keyMethod = /* create or discover did:key method */
    registry.register("key", keyMethod)

    // Create DID using registry
    val options = didCreationOptions {
        algorithm = KeyAlgorithm.Secp256k1
    }

    val method = registry.get("key")
    val didDoc = method?.createDid(options)

    println("Created DID: ${didDoc?.id}")
}

Outcome: Creates a DID using a manually configured DID method registry.

Resolving DIDs

Resolving DIDs with TrustWeave DSL

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
import com.trustweave.trust.TrustWeave
import com.trustweave.trust.dsl.credential.DidMethods
import com.trustweave.trust.dsl.credential.KeyAlgorithms
import com.trustweave.trust.types.Did
import com.trustweave.did.resolver.DidResolutionResult
import com.trustweave.testkit.services.*
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val trustWeave = TrustWeave.build {
        factories(didMethodFactory = TestkitDidMethodFactory())
        keys { provider("inMemory"); algorithm(KeyAlgorithms.ED25519) }
        did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
    }

    val didString = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
    val resolution = trustWeave.resolveDid(didString)
    
    when (resolution) {
        is DidResolutionResult.Success -> {
            println("Resolved DID: ${resolution.document.id}")
            println("Document: ${resolution.document}")
            println("Verification methods: ${resolution.document.verificationMethod.size}")
        }
        is DidResolutionResult.Failure.NotFound -> {
            println("DID not found: ${resolution.did.value}")
        }
        is DidResolutionResult.Failure.InvalidFormat -> {
            println("Invalid DID format: ${resolution.reason}")
        }
        is DidResolutionResult.Failure.MethodNotRegistered -> {
            println("DID method not registered: ${resolution.method}")
        }
        else -> {
            println("Resolution failed")
        }
    }
}

Outcome: Resolves a DID using the appropriate DID method automatically. Returns a sealed DidResolutionResult for type-safe error handling.

Resolving DIDs with Method Registry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Kotlin stdlib
import kotlinx.coroutines.runBlocking

// TrustWeave core
import com.trustweave.did.*

fun main() = runBlocking {
    val registry = DidMethodRegistry()
    // ... register methods ...

    val did = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
    val resolutionResult = registry.resolve(did)

    resolutionResult.fold(
        onSuccess = { result ->
            println("Resolved: ${result.didDocument?.id}")
        },
        onFailure = { error ->
            println("Resolution failed: ${error.message}")
        }
    )
}

Outcome: Resolves a DID using a manually configured method registry.

Updating DIDs

Updating DID Documents

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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking

// TrustWeave core
import com.trustweave.trust.TrustWeave
import com.trustweave.trust.dsl.credential.DidMethods
import com.trustweave.trust.dsl.credential.KeyAlgorithms
import com.trustweave.did.*
import com.trustweave.testkit.services.*

fun main() = runBlocking {
    val trustWeave = TrustWeave.build {
        factories(didMethodFactory = TestkitDidMethodFactory())
        keys { provider("inMemory"); algorithm(KeyAlgorithms.ED25519) }
        did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
    }

    val didString = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"

    // Update DID document
    try {
        val updatedDoc = trustWeave.updateDid {
            did(didString)
            // Add a new service endpoint
            service {
                id("${didString}#service-1")
                type("LinkedDomains")
                endpoint("https://example.com/service")
            }
        }

        println("Updated DID: ${updatedDoc.id}")
        println("Services: ${updatedDoc.service.size}")
    } catch (error: Exception) {
        println("Update failed: ${error.message}")
    }
}

Outcome: Updates a DID document with new verification methods or services.

Deactivating DIDs

Deactivating DIDs

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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking

// TrustWeave core
import com.trustweave.trust.TrustWeave
import com.trustweave.trust.dsl.credential.DidMethods
import com.trustweave.trust.dsl.credential.KeyAlgorithms
import com.trustweave.testkit.services.*

fun main() = runBlocking {
    val trustWeave = TrustWeave.build {
        factories(didMethodFactory = TestkitDidMethodFactory())
        keys { provider("inMemory"); algorithm(KeyAlgorithms.ED25519) }
        did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
    }

    val didString = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"

    // Deactivate DID (via updateDid with deactivated flag)
    try {
        val updatedDoc = trustWeave.updateDid {
            did(didString)
            deactivated(true)
        }
        println("DID deactivated successfully: ${updatedDoc.id}")
    } catch (error: Exception) {
        println("Deactivation error: ${error.message}")
    }
}

Outcome: Deactivates a DID, marking it as no longer active.

Working with Multiple DID Methods

Managing Multiple DID Methods

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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking

// TrustWeave core
import com.trustweave.did.*
import com.trustweave.kms.*

fun main() = runBlocking {
    val kms = InMemoryKeyManagementService()
    val registry = DidMethodRegistry()

    // Register multiple DID methods
    registry.register("key", /* did:key method */)
    registry.register("web", /* did:web method */)
    registry.register("ion", /* did:ion method */)

    // Create DIDs using different methods
    val keyDid = registry.get("key")?.createDid(didCreationOptions {
        algorithm = KeyAlgorithm.Ed25519
    })

    val webDid = registry.get("web")?.createDid(didCreationOptions {
        domain = "example.com"
        path = "/did/user/alice"
    })

    val ionDid = registry.get("ion")?.createDid(didCreationOptions {
        // ION-specific options
    })

    println("Key DID: ${keyDid?.id}")
    println("Web DID: ${webDid?.id}")
    println("ION DID: ${ionDid?.id}")
}

Outcome: Demonstrates how to work with multiple DID methods in the same application.

Advanced DID Operations

Working with DID Documents

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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking

// TrustWeave core
import com.trustweave.trust.TrustWeave
import com.trustweave.trust.dsl.credential.DidMethods
import com.trustweave.trust.dsl.credential.KeyAlgorithms
import com.trustweave.did.*
import com.trustweave.testkit.services.*

fun main() = runBlocking {
    // Build TrustWeave instance with testkit factories (for tutorials)
    val trustWeave = TrustWeave.build {
        factories(didMethodFactory = TestkitDidMethodFactory())  // Test-only factory
        keys { provider("inMemory"); algorithm(KeyAlgorithms.ED25519) }
        did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
    }

    try {
        val did = trustWeave.createDid {
            method(DidMethods.KEY)
            algorithm(KeyAlgorithms.ED25519)
        }
        
        // Resolve DID to get document
        val resolution = trustWeave.resolveDid(did)
        val document = when (resolution) {
            is DidResolutionResult.Success -> resolution.document
            else -> throw IllegalStateException("Failed to resolve DID")
        }

        // Access verification methods
        val verificationMethods = document.verificationMethod
        println("Verification methods: ${verificationMethods.size}")

        // Access services
        val services = document.service
        println("Services: ${services.size}")

        // Access authentication methods
        val authentication = document.authentication
        println("Authentication methods: ${authentication.size}")
    } catch (error: Exception) {
        println("Error: ${error.message}")
    }
}

Outcome: Shows how to access and work with DID document components.

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
// Kotlin stdlib
import kotlinx.coroutines.runBlocking

// TrustWeave core
import com.trustweave.trust.TrustWeave
import com.trustweave.trust.dsl.credential.DidMethods
import com.trustweave.trust.dsl.credential.KeyAlgorithms
import com.trustweave.core.exception.TrustWeaveError
import com.trustweave.testkit.services.*

fun main() = runBlocking {
    // Build TrustWeave instance with testkit factories (for tutorials)
    val trustWeave = TrustWeave.build {
        factories(didMethodFactory = TestkitDidMethodFactory())  // Test-only factory
        keys { provider("inMemory"); algorithm(KeyAlgorithms.ED25519) }
        did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
    }

    try {
        val did = trustWeave.createDid {
            method(DidMethods.KEY)
            algorithm(KeyAlgorithms.ED25519)
        }
        println("Created: ${did.value}")
    } catch (error: Exception) {
        when (error) {
            is IllegalStateException -> {
                if (error.message?.contains("not configured") == true) {
                    println("DID method not configured: ${error.message}")
                } else {
                    println("Error: ${error.message}")
                }
            }
            else -> {
                println("Error: ${error.message}")
            }
            is TrustWeaveError.DidNotFound -> {
                println("DID not found: ${error.did}")
            }
            else -> println("Error: ${error.message}")
        }
    }
}

Outcome: Demonstrates structured error handling for DID operations.

Next Steps

References