Smart Contract: Parametric Insurance Scenario
Building Parametric Insurance with TrustWeave Smart Contracts
This guide demonstrates how to build a parametric insurance system using TrustWeave’s Smart Contract abstraction. You’ll learn how to create contracts that automatically execute based on Earth Observation (EO) data triggers, with verifiable credentials and blockchain anchoring for trust and auditability.
What You’ll Build
By the end of this tutorial, you’ll have:
- ✅ Created a parametric insurance contract using SmartContract
- ✅ Bound the contract with verifiable credentials
- ✅ Anchored the contract to blockchain
- ✅ Executed the contract based on EO data triggers
- ✅ Generated automatic payouts when conditions are met
Architecture Overview
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
┌─────────────────────────────────────────────────────────────┐
│ Parametric Insurance Contract │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ EO Provider │ │ Insurance │ │ Blockchain │ │
│ │ (DID) │ │ (DID) │ │ Anchor │ │
│ └──────┬───────┘ └──────┬──────┘ └──────┬───────┘ │
│ │ │ │ │
│ │ Issues VC │ Issues VC │ Anchors │
│ │ │ │ │
│ ┌──────▼─────────────────▼─────────────────▼──────┐ │
│ │ TrustWeave Smart Contract Service │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ Contract Lifecycle Management │ │ │
│ │ │ - Create Draft │ │ │
│ │ │ - Bind (Issue VC + Anchor) │ │ │
│ │ │ - Activate │ │ │
│ │ │ - Execute (Evaluate Conditions) │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ Condition Evaluation │ │ │
│ │ │ - Parametric Triggers │ │ │
│ │ │ - Threshold Checks │ │ │
│ │ │ - Payout Calculation │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Step 1: Setup TrustWeave
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.trustweave.TrustWeave
import org.trustweave.contract.models.*
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import java.time.Instant
// Initialize TrustWeave with blockchain anchoring
val TrustWeave = TrustWeave.create {
blockchains {
"algorand:mainnet" to algorandClient
}
}
// Create DIDs for parties
val insurerDid = trustWeave.createDid { method(KEY) }
val insuredDid = trustWeave.createDid { method(KEY) }
val eoProviderDid = trustWeave.createDid { method(KEY) }
Step 2: Create Contract Draft
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
suspend fun createFloodInsuranceContract(
TrustWeave: TrustWeave,
insurerDid: String,
insuredDid: String,
coverageAmount: Double,
location: Location
): SmartContract {
val contract = trustWeave.contracts.draft(
request = ContractDraftRequest(
contractType = ContractType.Insurance,
executionModel = ExecutionModel.Parametric(
triggerType = TriggerType.EarthObservation,
evaluationEngine = "parametric-insurance"
),
parties = ContractParties(
primaryPartyDid = insurerDid,
counterpartyDid = insuredDid
),
terms = ContractTerms(
obligations = listOf(
Obligation(
id = "payout-obligation",
partyDid = insurerDid,
description = "Pay out based on flood depth tier",
obligationType = ObligationType.PAYMENT
)
),
conditions = listOf(
ContractCondition(
id = "flood-threshold-20cm",
description = "Flood depth >= 20cm (Tier 1)",
conditionType = ConditionType.THRESHOLD,
expression = "$.floodDepthCm >= 20"
),
ContractCondition(
id = "flood-threshold-50cm",
description = "Flood depth >= 50cm (Tier 2)",
conditionType = ConditionType.THRESHOLD,
expression = "$.floodDepthCm >= 50"
),
ContractCondition(
id = "flood-threshold-100cm",
description = "Flood depth >= 100cm (Tier 3)",
conditionType = ConditionType.THRESHOLD,
expression = "$.floodDepthCm >= 100"
)
),
penalties = null,
rewards = null,
jurisdiction = "US",
governingLaw = "State of North Carolina"
),
effectiveDate = Instant.now().toString(),
expirationDate = Instant.now().plusSeconds(365 * 24 * 60 * 60).toString(),
contractData = buildJsonObject {
put("productType", "SarFlood")
put("coverageAmount", coverageAmount)
put("location", buildJsonObject {
put("latitude", location.latitude)
put("longitude", location.longitude)
put("address", location.address)
put("region", location.region)
})
put("thresholds", buildJsonObject {
put("tier1Cm", 20.0)
put("tier2Cm", 50.0)
put("tier3Cm", 100.0)
})
put("payoutTiers", buildJsonObject {
put("tier1", 0.25) // 25% of coverage
put("tier2", 0.50) // 50% of coverage
put("tier3", 1.0) // 100% of coverage
})
}
)
).getOrThrow()
println("✅ Contract draft created: ${contract.id}")
println(" Contract Number: ${contract.contractNumber}")
println(" Status: ${contract.status}")
return contract
}
data class Location(
val latitude: Double,
val longitude: Double,
val address: String,
val region: String
)
Step 3: Bind Contract
Binding issues a verifiable credential and anchors to blockchain:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
suspend fun bindInsuranceContract(
TrustWeave: TrustWeave,
contract: SmartContract,
insurerDid: String,
insurerKeyId: String
): BoundContract {
val bound = trustWeave.contracts.bindContract(
contractId = contract.id,
issuerDid = insurerDid,
issuerKeyId = insurerKeyId,
chainId = "algorand:mainnet"
).getOrThrow()
println("✅ Contract bound:")
println(" Credential ID: ${bound.credentialId}")
println(" Anchor TX: ${bound.anchorRef.txHash}")
println(" Chain: ${bound.anchorRef.chainId}")
println(" Status: ${bound.contract.status}")
return bound
}
Step 4: Activate Contract
1
2
3
4
5
6
7
8
9
10
11
12
13
14
suspend fun activateContract(
TrustWeave: TrustWeave,
contractId: String
): SmartContract {
val active = trustWeave.contracts.activateContract(contractId).getOrThrow()
println("✅ Contract activated: ${active.id}")
println(" Status: ${active.status}")
println(" Effective: ${active.effectiveDate}")
println(" Expires: ${active.expirationDate}")
return active
}
Step 5: Process EO Data and Execute Contract
When EO data arrives (e.g., SAR flood data), process it and execute the contract:
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
suspend fun processFloodDataAndExecute(
TrustWeave: TrustWeave,
contract: SmartContract,
floodDepthCm: Double,
eoDataCredential: VerifiableCredential
): ExecutionResult {
// Create execution context with trigger data
val executionContext = ExecutionContext(
triggerData = buildJsonObject {
put("floodDepthCm", floodDepthCm)
put("credentialId", eoDataCredential.id)
put("timestamp", Instant.now().toString())
}
)
// Execute contract
val result = trustWeave.contracts.executeContract(
contract = contract,
executionContext = executionContext
).getOrThrow()
if (result.executed) {
println("✅ Contract executed!")
println(" Execution Type: ${result.executionType}")
println(" Outcomes: ${result.outcomes.size}")
result.outcomes.forEach { outcome ->
println(" - ${outcome.description}")
outcome.monetaryImpact?.let {
println(" Amount: ${it.amount} ${it.currency}")
}
}
} else {
println("⚠️ Contract conditions not met")
result.outcomes.forEach { outcome ->
println(" - ${outcome.description}")
}
}
return result
}
Step 6: Complete Workflow
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
suspend fun completeParametricInsuranceWorkflow() {
val TrustWeave = TrustWeave.create {
blockchains {
"algorand:mainnet" to algorandClient
}
}
// Step 1: Create DIDs
import org.trustweave.trust.types.getOrThrowDid
import org.trustweave.trust.types.getOrThrow
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 insurerDid = trustWeave.createDid { method(KEY) }.getOrThrowDid()
val insuredDid = trustWeave.createDid { method(KEY) }.getOrThrowDid()
val eoProviderDid = trustWeave.createDid { method(KEY) }.getOrThrowDid()
val insurerDoc = trustWeave.resolveDid(insurerDid).getOrThrow()
val insurerKeyId = insurerDoc.verificationMethod.firstOrNull()?.extractKeyId()
?: throw IllegalStateException("No key found")
val eoProviderDoc = trustWeave.resolveDid(eoProviderDid).getOrThrow()
val eoProviderKeyId = eoProviderDoc.verificationMethod.firstOrNull()?.extractKeyId()
?: throw IllegalStateException("No key found")
// Step 2: Create contract draft
val contract = createFloodInsuranceContract(
TrustWeave = trustWeave,
insurerDid = insurerDid.value,
insuredDid = insuredDid.value,
coverageAmount = 1_000_000.0,
location = Location(
latitude = 35.2271,
longitude = -80.8431,
address = "Charlotte, NC",
region = "North Carolina"
)
)
// Step 3: Bind contract
val bound = bindInsuranceContract(
TrustWeave = trustWeave,
contract = contract,
insurerDid = insurerDid.value,
insurerKeyId = insurerKeyId
)
// Step 4: Activate contract
val active = activateContract(trustWeave, bound.contract.id)
// Step 5: Simulate flood event
// In production, this would come from EO data provider
val floodDepth = 75.0 // cm
// Issue EO data credential (simplified - in production, EO provider issues this)
import org.trustweave.trust.types.IssuanceResult
val eoDataIssuanceResult = trustWeave.issue {
credential {
type("EarthObservationCredential")
issuer(eoProviderDid)
subject {
"floodDepthCm" to floodDepth
"timestamp" to Instant.now().toString()
}
issued(Instant.now())
}
signedBy(eoProviderDid)
}
import org.trustweave.trust.types.getOrThrow
val eoDataCredential = eoDataIssuanceResult.getOrThrow()
// Step 6: Execute contract
val executionResult = processFloodDataAndExecute(
TrustWeave = TrustWeave,
contract = active,
floodDepthCm = floodDepth,
eoDataCredential = eoDataCredential
)
// Step 7: Process payout (application-specific)
if (executionResult.executed) {
processPayout(executionResult)
}
}
Advanced: Custom Condition Evaluation
For production use, implement custom condition evaluators:
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
class FloodConditionEvaluator : ConditionEvaluator {
override suspend fun evaluate(
condition: ContractCondition,
inputData: JsonElement,
contract: SmartContract
): Boolean {
when (condition.conditionType) {
ConditionType.THRESHOLD -> {
val threshold = extractThreshold(condition.expression)
val value = extractValue(inputData, "floodDepthCm")
return value >= threshold
}
else -> throw UnsupportedOperationException(
"Condition type ${condition.conditionType} not supported"
)
}
}
private fun extractThreshold(expression: String): Double {
// Parse expression like "$.floodDepthCm >= 50"
val match = Regex(">= (\\d+\\.?\\d*)").find(expression)
return match?.groupValues?.get(1)?.toDouble() ?: 0.0
}
private fun extractValue(data: JsonElement, key: String): Double {
return data.jsonObject[key]?.jsonPrimitive?.content?.toDouble() ?: 0.0
}
}
Benefits of Using Smart Contracts
- Standardization: W3C-compliant format works across all contract types
- Trust: Cryptographic proof of contract terms prevents disputes
- Automation: Parametric execution enables instant payouts
- Auditability: Blockchain anchoring provides immutable audit trails
- Multi-Party: DIDs enable complex multi-party contracts
- Extensibility: Pluggable execution models for different use cases
Next Steps
- Review Smart Contracts Core Concepts for detailed API documentation
- Explore Parametric Insurance MGA Guide for complete MGA implementation
- See Blockchain Anchoring for anchoring details
- Check API Reference for complete API documentation