API Patterns and Best Practices

This guide explains the correct API patterns to use with TrustWeave and clarifies common misconceptions.

Primary API: TrustWeave

TrustWeave is the main entry point for all TrustWeave operations. Always use TrustWeave for your application code.

Creating a TrustWeave Instance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.trustweave.trust.TrustWeave
import org.trustweave.testkit.services.*
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val trustWeave = TrustWeave.build {
        factories(
            kmsFactory = TestkitKmsFactory(),
            didMethodFactory = TestkitDidMethodFactory()
        )
        keys {
            provider(IN_MEMORY)
            algorithm(ED25519)
        }
        did {
            method(KEY) {
                algorithm(ED25519)
            }
        }
    }

    // Use trustWeave for all operations
    val didResult = trustWeave.createDid { method(KEY) }
}

Correct API Patterns

DID Operations

Correct:

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
import org.trustweave.trust.types.DidCreationResult
import org.trustweave.trust.types.DidUpdateResult
import org.trustweave.trust.types.KeyRotationResult

val trustWeave = TrustWeave.build { ... }

// Create DID (using compact pattern)
import org.trustweave.trust.types.getOrThrowDid

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

// Update DID (returns sealed result)
val updateResult = trustWeave.updateDid {
    did("did:key:example")
    addService { ... }
}
val updated = when (updateResult) {
    is DidUpdateResult.Success -> updateResult.document
    else -> {
        println("Failed to update DID: ${updateResult.reason}")
        return@runBlocking
    }
}

// Rotate key (returns sealed result)
val rotationResult = trustWeave.rotateKey {
    did("did:key:example")
    oldKeyId("did:key:example#key-1")
    newKeyId("did:key:example#key-2")
}
val rotated = when (rotationResult) {
    is KeyRotationResult.Success -> rotationResult.document
    else -> {
        println("Failed to rotate key: ${rotationResult.reason}")
        return@runBlocking
    }
}

Incorrect (Old API - Do Not Use):

1
2
3
// These patterns are from older documentation and should not be used
val did = trustWeave.createDid { method(KEY) }
val resolution = trustWeave.resolveDid(did)

Credential Operations

Correct:

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.types.IssuanceResult

val trustWeave = TrustWeave.build { ... }

// Issue credential (using compact pattern)
import org.trustweave.trust.types.getOrThrow

val credential = trustWeave.issue {
    credential {
        type(CredentialType.VerifiableCredential, CredentialType.Person)
        issuer(issuerDid)
        subject {
            id(holderDid)
            "name" to "Alice"
        }
    }
    signedBy(issuerDid = issuerDid, keyId = "$issuerDid#key-1")
}.getOrThrow()

// Verify credential (returns VerificationResult, not sealed)
val verification = trustWeave.verify {
    credential(credential)
    checkExpiration(true)
    checkRevocation(true)
    checkTrust(true)
}

Incorrect (Old API - Do Not Use):

1
2
3
// These patterns are from older documentation
val credential = trustWeave.issue { credential { ... }; signedBy(...) }
val verification = trustWeave.verify { credential(credential) }

Wallet Operations

Correct:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.trustweave.trust.types.WalletCreationResult

val trustWeave = TrustWeave.build { ... }

// Create wallet (using compact pattern)
import org.trustweave.trust.types.getOrThrow

val wallet = trustWeave.wallet {
    holder(holderDid)
    enableOrganization()
    enablePresentation()
}.getOrThrow()

// Use wallet
val credentialId = wallet.store(credential)
val retrieved = wallet.get(credentialId)
val allCredentials = wallet.list()

Trust Operations

Correct:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
val trustWeave = TrustWeave.build {
    trust { provider(IN_MEMORY) }
}

// Using DSL
trustWeave.trust {
    addAnchor("did:key:university") {
        credentialTypes("EducationCredential")
        description("Trusted university")
    }

    val isTrusted = isTrusted("did:key:university", "EducationCredential")
}

// Using direct methods
trustWeave.addTrustAnchor("did:key:university") {
    credentialTypes("EducationCredential")
}
val isTrusted = trustWeave.isTrustedIssuer("did:key:university", "EducationCredential")

Error Handling Patterns

Exception-Based (TrustWeave Methods)

All TrustWeave methods throw exceptions. Always use try-catch for 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
import org.trustweave.core.TrustWeaveError

try {
    val didResult = trustWeave.createDid { method(KEY) }
    val did = when (didResult) {
        is DidCreationResult.Success -> didResult.did
        is DidCreationResult.Failure.MethodNotRegistered -> {
            println("Method not registered: ${didResult.method}")
            println("Available methods: ${didResult.availableMethods.joinToString()}")
            return@runBlocking
        }
        else -> {
            println("Failed to create DID: ${didResult.reason}")
            return@runBlocking
        }
    }
    
    val issuanceResult = trustWeave.issue { ... }
    val credential = when (issuanceResult) {
        is IssuanceResult.Success -> issuanceResult.credential
        else -> {
            println("Failed to issue credential: ${issuanceResult.reason}")
            return@runBlocking
        }
    }
} catch (error: TrustWeaveException) {
    when (error) {
        is TrustWeaveError.CredentialInvalid -> {
            println("Credential invalid: ${error.reason}")
        }
        else -> {
            println("Error: ${error.message}")
        }
    }
}

Result-Based (Lower-Level APIs)

Some lower-level service APIs return Result<T>. Use fold():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
val result = someService.operation()
result.fold(
    onSuccess = { value ->
        // Handle success
        println("Success: $value")
    },
    onFailure = { error ->
        // Handle error
        when (error) {
            is TrustWeaveError.ValidationFailed -> {
                println("Validation failed: ${error.reason}")
            }
            else -> {
                println("Error: ${error.message}")
            }
        }
    }
)

Common Mistakes to Avoid

❌ Mistake 1: Using Old API Patterns

Wrong:

1
val did = TrustWeave.dids.create()

Correct:

1
2
val trustWeave = TrustWeave.build { ... }
val did = trustWeave.createDid { method(KEY) }

❌ Mistake 2: Ignoring Errors

Wrong:

1
2
val did = trustWeave.createDid { method(KEY) }
// This returns DidCreationResult, not Did - need to unwrap!

Correct:

1
2
3
4
5
6
7
8
9
val didResult = trustWeave.createDid { method(KEY) }
val did = when (didResult) {
    is DidCreationResult.Success -> didResult.did
    else -> {
        logger.error("Failed to create DID: ${didResult.reason}")
        return@runBlocking // or handle appropriately
    }
}
// Use did

❌ Mistake 3: Not Configuring Required Components

Wrong:

1
2
3
4
5
val trustWeave = TrustWeave.build {
    // Missing KMS configuration!
}
val did = trustWeave.createDid { method(KEY) }
// Fails: No KMS provider configured

Correct:

1
2
3
4
5
6
7
8
9
val trustWeave = TrustWeave.build {
    keys {
        provider(IN_MEMORY)
        algorithm(ED25519)
    }
    did {
        method(KEY) { algorithm(ED25519) }
    }
}

❌ Mistake 4: Using Wrong Key ID Format

Wrong:

1
2
3
4
val credential = trustWeave.issue {
    credential { ... }
    signedBy(issuerDid = issuerDid, keyId = "key-1")  // Missing DID prefix!
}

Correct:

1
2
3
4
5
val issuerKeyId = "$issuerDid#key-1"
val credential = trustWeave.issue {
    credential { ... }
    signedBy(issuerDid = issuerDid, keyId = issuerKeyId)
}

Migration from Old API

If you’re using older documentation or examples that reference TrustWeave.dids.create(), here’s how to migrate:

Old Pattern

1
2
3
val trustweave = TrustWeave.create()
val did = trustweave.dids.create()
val credential = trustweave.credentials.issue(...)

New Pattern

1
2
3
4
5
6
7
8
9
10
val trustWeave = TrustWeave.build {
    keys { provider(IN_MEMORY); algorithm(ED25519) }
    did { method(KEY) { algorithm(ED25519) } }
}

val did = trustWeave.createDid { method(KEY) }
val credential = trustWeave.issue {
    credential { ... }
    signedBy(issuerDid = issuerDid, keyId = "$issuerDid#key-1")
}

Best Practices

1. Always Configure Explicitly

Don’t rely on defaults in production. Explicitly configure all components:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
val trustWeave = TrustWeave.build {
    keys {
        provider(AWS)  // Production KMS
        algorithm(ED25519)
    }
    did {
        method(KEY) { algorithm(ED25519) }
        method(WEB) { domain("example.com") }
    }
    anchor {
        chain("algorand:mainnet") { provider(ALGORAND) }
    }
    trust {
        provider("database")  // Production trust registry
    }
}

2. Handle Errors Explicitly

Always wrap TrustWeave operations in try-catch:

1
2
3
4
5
6
7
8
try {
    val result = trustWeave.operation { ... }
    // Process result
} catch (error: TrustWeaveError) {
    // Log and handle error
    logger.error("Operation failed", error)
    // Return error response or retry
}

3. Use Type-Safe Builders

Leverage the DSL for type safety:

1
2
3
4
5
6
7
8
9
10
11
12
// ✅ Good: Type-safe, IDE autocomplete
val credential = trustWeave.issue {
    credential {
        type(CredentialType.VerifiableCredential, CredentialType.Person)
        issuer(issuerDid)
        subject {
            id(holderDid)
            "name" to "Alice"
        }
    }
    signedBy(issuerDid = issuerDid, keyId = "$issuerDid#key-1")
}

4. Reuse TrustWeave Instance

Create one TrustWeave instance and reuse it:

1
2
3
4
5
6
// ✅ Good: Create once, reuse
val trustWeave = TrustWeave.build { ... }

fun createUserDid() = trustWeave.createDid { method(KEY) }
fun issueCredential(...) = trustWeave.issue { ... }
fun verifyCredential(...) = trustWeave.verify { ... }

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