Migrating to TrustWeave 1.0.0
This guide helps you migrate from earlier versions of TrustWeave to version 1.0.0.
Overview of Changes
Version 1.0.0 introduces several improvements:
- Type-safe options: Replaces map-based configuration with typed options classes
- Result-based APIs: All operations return
Result<T>for consistent error handling - Enhanced error types: Structured error hierarchy with rich context
- Plugin lifecycle: New lifecycle management APIs
Migration Checklist
- Update dependencies to 0.6.0
- Migrate to type-safe options
- Update error handling to use
Result<T> - Update plugin lifecycle calls
- Test thoroughly
- Update documentation references
1. Migrating to Type-Safe Options
Before (Map-based)
1
2
3
4
5
6
7
val client = AlgorandBlockchainAnchorClient(
chainId = "algorand:testnet",
options = mapOf(
"algodUrl" to "https://testnet-api.algonode.cloud",
"privateKey" to "base64-key"
)
)
After (Type-safe)
1
2
3
4
5
6
7
8
9
import org.trustweave.anchor.options.AlgorandOptions
import org.trustweave.anchor.ChainId
val chainId = ChainId.Algorand.Testnet
val options = AlgorandOptions(
algodUrl = "https://testnet-api.algonode.cloud",
privateKey = "base64-key"
)
val client = AlgorandBlockchainAnchorClient(chainId.toString(), options)
Benefits:
- Compile-time validation
- Better IDE autocomplete
- Type safety prevents configuration errors
2. Migrating to Result-Based APIs
Before (Exception-based)
1
2
3
4
5
6
try {
val result = client.writePayload(payload)
println("Anchored: ${result.ref.txHash}")
} catch (e: TrustWeaveException) {
println("Error: ${e.message}")
}
After (Result-based)
Anchoring is exposed through the trustWeave.blockchains service (a BlockchainService). anchor(...) is suspend and returns an AnchorResult on success — failures surface as typed BlockchainException subclasses. Wrap with runCatching to use a Result<T> flow:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.trustweave.anchor.exceptions.BlockchainException
val result = runCatching {
trustWeave.blockchains.anchor(data, serializer, chainId)
}
result.fold(
onSuccess = { anchor ->
println("Anchored: ${anchor.ref.txHash}")
},
onFailure = { error ->
when (error) {
is BlockchainException.ChainNotRegistered -> {
println("Chain not registered: ${error.chainId}")
println("Available chains: ${error.availableChains}")
}
else -> println("Error: ${error.message}")
}
}
)
Benefits:
- Explicit error handling
- Structured error types
- Better error context
3. Migrating Error Handling
Before
1
2
3
4
5
6
7
try {
val did = TrustWeave.createDid()
} catch (e: IllegalArgumentException) {
println("Invalid argument: ${e.message}")
} catch (e: Exception) {
println("Error: ${e.message}")
}
After
TrustWeave.createDid(...) is a suspend method that returns the sealed DidCreationResult. Pattern-match instead of calling .fold on a Result<T>:
1
2
3
4
5
6
7
8
9
10
11
12
import org.trustweave.trust.types.DidCreationResult
val trustWeave = TrustWeave.quickStart()
when (val result = trustWeave.createDid()) {
is DidCreationResult.Success -> println("Created: ${result.did}")
is DidCreationResult.Failure.MethodNotRegistered -> {
println("Method not registered: ${result.method}")
println("Available methods: ${result.availableMethods}")
}
is DidCreationResult.Failure -> println("Error: $result")
}
4. Migrating Plugin Lifecycle
Before
1
2
3
// No explicit lifecycle management
val trustWeave = TrustWeave.quickStart()
// Use immediately; resources released when GC’d (not ideal for production)
After
1
2
3
4
5
6
7
8
9
10
11
import kotlinx.coroutines.runBlocking
import org.trustweave.trust.TrustWeave
fun main() = runBlocking {
val trustWeave = TrustWeave.quickStart()
try {
// Use trustWeave
} finally {
trustWeave.close()
}
}
If your own adapters implement PluginLifecycle, call your hooks from the same composition root (see Plugin lifecycle). The TrustWeave facade does not expose initialize() / start() / stop().
5. Migrating Type-Safe Chain IDs
Before
1
val chainId = "algorand:testnet" // Typo-prone string
After
1
2
3
4
5
import org.trustweave.anchor.ChainId
val chainId = ChainId.Algorand.Testnet // Compile-time safe
// Or use string with validation
val chainId = "algorand:testnet" // Still supported, but less safe
Common Migration Issues
Issue 1: Missing Error Handling
Problem: Code assumes operations always succeed
Solution: Always handle Result<T> with fold() or getOrThrow() (only for tests)
Issue 2: Type Mismatches
Problem: Using old map-based options with new APIs
Solution: Migrate to type-safe options classes
Issue 3: Missing Lifecycle Calls
Problem: Plugins not initialized before use
Solution: The TrustWeave facade does not expose initialize() / start() / stop(). Build it via TrustWeave.build { … } (or TrustWeave.quickStart()) and call trustWeave.close() on shutdown. If your own adapters implement PluginLifecycle, drive their hooks from the same composition root — see Plugin lifecycle.
Testing Your Migration
- Run Tests: Ensure all tests pass with new APIs
- Check Error Handling: Verify error handling works correctly
- Validate Configuration: Ensure type-safe options are configured correctly
- Test Lifecycle: Verify plugin lifecycle is managed properly
Getting Help
If you encounter issues during migration:
- Check Error Handling for error patterns
- Review API Reference for API changes
- Open an issue on GitHub with migration details
- Contact support at www.geoknoesis.com