Wallet API Tutorial
This tutorial provides a comprehensive guide to using TrustWeave’s Wallet API. You’ll learn how to create wallets, store credentials, organize them, and create presentations.
1
2
3
4
5
dependencies {
implementation("org.trustweave:common:0.6.0")
implementation("org.trustweave:trust:0.6.0")
implementation("org.trustweave:testkit:0.6.0")
}
Result: Wallet APIs, TrustWeave, and testkit factories used in this tutorial.
Tip: Run
./gradlew :distribution:examples:runQuickStartSample(or follow Quick start) for runnable samples aligned with the snippets below.
Prerequisites
- Basic understanding of Kotlin
- Familiarity with coroutines
- Understanding of DIDs and Verifiable Credentials
Table of Contents
- Creating a Wallet
- Storing Credentials
- Retrieving Credentials
- Organizing Credentials
- Querying Credentials
- Creating Presentations
- Lifecycle Management
- Advanced Features
Creating a Wallet
Service API Wallet (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
// 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.KmsProviders
import org.trustweave.trust.types.getOrThrow
import org.trustweave.core.exception.TrustWeaveException
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(KmsProviders.IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
}
try {
val wallet = trustWeave.wallet {
holder("did:key:holder")
provider("inMemory")
enablePresentation()
}.getOrThrow()
println("Wallet ID: ${wallet.walletId}")
} catch (error: TrustWeaveException) {
println("Wallet creation failed: ${error.message}")
}
}
Outcome: Creates a wallet via TrustWeave.wallet { } and unwraps WalletCreationResult with getOrThrow() (see result types).
Same pattern with TrustWeave.build
Use TrustWeave.build { keys { ... }; did { ... }; factories(walletFactory = ...) } when you need explicit KMS/DID/wallet factory wiring instead of defaults-only demos.
Testkit Wallets
BasicWallet and InMemoryWallet remain available for lightweight unit tests:
1
2
3
4
5
import org.trustweave.testkit.credential.BasicWallet
import org.trustweave.testkit.credential.InMemoryWallet
val basic = BasicWallet()
val inMemory = InMemoryWallet(holderDid = "did:key:test-holder")
Outcome: Shows the lightweight testkit wallets you can use in unit tests or prototypes.
Storing Credentials
Basic Storage
In 0.6.0 the VerifiableCredential constructor was tightened to use typed
identifiers (Issuer, CredentialSubject, kotlinx.datetime.Instant,
List<CredentialType>). Always build credentials through the issuance DSL — never
the raw constructor — and store the result. Storage itself is unchanged.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.trustweave.credential.results.IssuanceResult
import org.trustweave.did.identifiers.Did
// 1. Issue via the DSL (full walkthrough in the Credential Issuance tutorial).
val credential = (trustWeave.issue {
credential {
issuer(issuerDid)
subject {
id(holderDid)
claim("degree", "Bachelor of Science")
}
}
signedBy(issuerDid = Did(issuerDid), keyId = "key-1")
} as IssuanceResult.Success).credential
// 2. Store it.
val credentialId = wallet.store(credential)
println("Stored credential: $credentialId")
Outcome: Persists a credential in the wallet and returns its storage identifier.
Storing Multiple Credentials
1
2
3
val credentials = listOf(credential1, credential2, credential3)
val credentialIds = credentials.map { wallet.store(it) }
println("Stored ${credentialIds.size} credentials")
Outcome: Demonstrates bulk storage patterns for credential lists.
Retrieving Credentials
Get by ID
1
2
3
4
5
6
val credential = wallet.get(credentialId)
if (credential != null) {
println("Found credential: ${credential.id}")
} else {
println("Credential not found")
}
Outcome: Retrieves a stored credential by ID and handles the nullable response.
List All Credentials
1
2
val allCredentials = wallet.list()
println("Total credentials: ${allCredentials.size}")
Outcome: Lists every credential in the wallet—useful for dashboards or audits.
List with Filter
1
2
3
4
5
6
7
8
import org.trustweave.wallet.CredentialFilter
val workCredentials = wallet.list(
filter = CredentialFilter(
issuer = "did:key:work-issuer",
type = listOf("WorkCredential")
)
)
Outcome: Shows how filter criteria narrow the result set without writing manual queries.
Organizing Credentials
Collections
Create collections to group related credentials:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if (wallet is CredentialOrganization) {
// Create a collection
val workCollection = wallet.createCollection(
name = "Work Credentials",
description = "Professional credentials and certifications"
)
// Add credentials to collection
wallet.addToCollection(credentialId, workCollection)
// Get credentials in collection
val workCreds = wallet.getCredentialsInCollection(workCollection)
println("Work credentials: ${workCreds.size}")
// List all collections
val collections = wallet.listCollections()
collections.forEach { collection ->
println("Collection: ${collection.name} (${collection.credentialCount} credentials)")
}
}
Outcome: Creates collections, adds credentials, and lists collection metadata when the wallet supports organization.
Tags
Tag credentials for easy filtering:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (wallet is CredentialOrganization) {
// Tag a credential
wallet.tagCredential(credentialId, setOf("important", "verified", "work"))
// Get tags for a credential
val tags = wallet.getTags(credentialId)
println("Tags: $tags")
// Find credentials by tag
val importantCreds = wallet.findByTag("important")
// Get all tags
val allTags = wallet.getAllTags()
println("All tags: $allTags")
// Remove tags
wallet.untagCredential(credentialId, setOf("work"))
}
Outcome: Demonstrates tagging workflows—ideal for building saved searches or UI filters.
Metadata
Add custom metadata to credentials:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (wallet is CredentialOrganization) {
// Add metadata
wallet.addMetadata(credentialId, mapOf(
"source" to "issuer.com",
"verified" to true,
"priority" to "high"
))
// Get metadata
val metadata = wallet.getMetadata(credentialId)
println("Metadata: ${metadata?.metadata}")
// Add notes
wallet.updateNotes(credentialId, "This credential was verified manually")
}
Querying Credentials
Basic Query
1
2
3
4
5
val credentials = wallet.query {
byIssuer("did:key:issuer")
byType("PersonCredential")
notExpired()
}
Complex Query
1
2
3
4
5
6
7
val validWorkCredentials = wallet.query {
byTypes("WorkCredential", "EmploymentCredential", "CertificationCredential")
bySubject("did:key:subject")
notExpired()
notRevoked()
valid() // Has proof, not expired, not revoked
}
Query Examples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Find expired credentials
val expired = wallet.query {
expired()
}
// Find revoked credentials
val revoked = wallet.query {
revoked()
}
// Find credentials by issuer and type
val specific = wallet.query {
byIssuer("did:key:university")
byType("DegreeCredential")
}
Creating Presentations
Basic Presentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import org.trustweave.credential.proof.ProofOptions
import org.trustweave.credential.proof.ProofPurpose
if (wallet is CredentialPresentation) {
val presentation = wallet.createPresentation(
credentialIds = listOf(credentialId1, credentialId2),
holderDid = "did:key:holder",
options = ProofOptions(
purpose = ProofPurpose.Authentication,
challenge = "random-challenge-123",
domain = "example.com"
)
)
println("Created presentation with ${presentation.verifiableCredential.size} credentials")
}
Selective Disclosure
Reveal only specific fields:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.trustweave.credential.proof.ProofOptions
import org.trustweave.credential.proof.ProofPurpose
if (wallet is CredentialPresentation) {
val selectivePresentation = wallet.createSelectiveDisclosure(
credentialIds = listOf(credentialId),
disclosedFields = listOf(
"name",
"email",
"credentialSubject.degree.name"
),
holderDid = "did:key:holder",
options = ProofOptions(purpose = ProofPurpose.Authentication)
)
}
Lifecycle Management
Archiving Credentials
1
2
3
4
5
6
7
8
9
10
11
if (wallet is CredentialLifecycle) {
// Archive old credentials
wallet.archive(oldCredentialId)
// Get archived credentials
val archived = wallet.getArchived()
println("Archived credentials: ${archived.size}")
// Unarchive if needed
wallet.unarchive(oldCredentialId)
}
Refreshing Credentials
1
2
3
4
5
6
7
if (wallet is CredentialLifecycle) {
// Refresh a credential (if refresh service available)
val refreshed = wallet.refreshCredential(credentialId)
if (refreshed != null) {
println("Credential refreshed")
}
}
Advanced Features
Wallet Statistics
Get an overview of your wallet:
1
2
3
4
5
6
7
8
9
10
11
val stats = wallet.getStatistics()
println("""
Wallet Statistics:
- Total credentials: ${stats.totalCredentials}
- Valid credentials: ${stats.validCredentials}
- Expired credentials: ${stats.expiredCredentials}
- Revoked credentials: ${stats.revokedCredentials}
- Collections: ${stats.collectionsCount}
- Tags: ${stats.tagsCount}
- Archived: ${stats.archivedCount}
""".trimIndent())
Type-Safe Capability Checking
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Check capabilities at compile-time
when {
wallet is CredentialOrganization && wallet is CredentialPresentation -> {
// Full-featured wallet
wallet.createCollection("My Collection")
wallet.createPresentation(...)
}
wallet is CredentialOrganization -> {
// Organization-only wallet
wallet.createCollection("My Collection")
}
else -> {
// Basic wallet
wallet.store(credential)
}
}
Extension Functions
Use extension functions for elegant code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Organization features
wallet.withOrganization { org ->
val collectionId = org.createCollection("Work")
org.tagCredential(credentialId, setOf("important"))
}
// Lifecycle features
wallet.withLifecycle { lifecycle ->
lifecycle.archive(oldCredentialId)
}
// Presentation features
wallet.withPresentation { presentation ->
val vp = presentation.createPresentation(...)
}
Wallet Directory
Manage multiple wallets with an instance-scoped directory:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.trustweave.testkit.credential.BasicWallet
import org.trustweave.testkit.credential.InMemoryWallet
import org.trustweave.wallet.CredentialOrganization
import org.trustweave.wallet.WalletDirectory
val directory = WalletDirectory()
// Register wallets
val wallet1 = BasicWallet()
val wallet2 = InMemoryWallet()
directory.register(wallet1)
directory.register(wallet2)
// Find wallets
val retrieved = directory.get(wallet1.walletId)
val byDid = directory.getByDid("did:key:wallet")
// Find wallets with specific capabilities (compile-time, reified)
val orgWallets: List<CredentialOrganization> = directory.findByCapability()
// Or by capability feature name (runtime, from WalletCapabilities)
val walletsWithCollections = directory.findByCapability("collections")
Complete Example
Here’s a complete example combining all features:
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
// 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.KmsProviders
import org.trustweave.trust.types.getOrThrow
import org.trustweave.credential.model.vc.VerifiableCredential
import org.trustweave.credential.proof.ProofOptions
import org.trustweave.credential.proof.ProofPurpose
import org.trustweave.wallet.CredentialOrganization
import org.trustweave.wallet.CredentialPresentation
import org.trustweave.wallet.DidManagement
fun main() = runBlocking {
val trustWeave = TrustWeave.build {
keys { provider(KmsProviders.IN_MEMORY); algorithm(KeyAlgorithms.ED25519) }
did { method(DidMethods.KEY) { algorithm(KeyAlgorithms.ED25519) } }
}
val wallet = trustWeave.wallet {
holder("did:key:holder")
provider("inMemory")
enablePresentation()
}.getOrThrow()
// `credential1`/`credential2` come from trustWeave.issue { ... }.getOrThrow()
// — see the credential-issuance tutorial for the issuance DSL.
val credential1: VerifiableCredential = TODO("issue with trustWeave.issue { ... }")
val credential2: VerifiableCredential = TODO("issue with trustWeave.issue { ... }")
val id1 = wallet.store(credential1)
val id2 = wallet.store(credential2)
// Organize credentials (requires CredentialOrganization capability)
if (wallet is CredentialOrganization) {
val workCollection = wallet.createCollection("Work Credentials")
wallet.addToCollection(id1, workCollection)
wallet.tagCredential(id1, setOf("important", "verified"))
}
// Query credentials
val important = wallet.query {
byIssuer("did:key:issuer")
valid()
}
// Create presentation (requires CredentialPresentation capability)
val holderDid = (wallet as? DidManagement)?.holderDid ?: "did:key:holder"
if (wallet is CredentialPresentation) {
val presentation = wallet.createPresentation(
credentialIds = listOf(id1),
holderDid = holderDid,
options = ProofOptions(purpose = ProofPurpose.Authentication)
)
println("Created presentation with ${presentation.verifiableCredential.size} credentials")
}
// Get statistics
val stats = wallet.getStatistics()
println("Wallet has ${stats.totalCredentials} credentials")
}
Best Practices
- Use type-safe checks (
wallet is CredentialOrganization) when possible - Organize credentials early using collections and tags
- Query efficiently by combining filters
- Use selective disclosure to minimize data exposure
- Archive instead of delete to maintain history
- Monitor statistics to track wallet health
Next Steps
- Explore the Wallet API Reference
- Learn about DIDs and Verifiable Credentials
- Check out Advanced Topics for custom implementations