-- ContractKeys.daml
module ContractKeys where
import Daml.Script
template Account
with
bank : Party
owner : Party
accountId : Text
balance : Decimal
where
signatory bank
observer owner
ensure balance >= 0.0
-- The key uniquely identifies this contract.
-- No two active Account contracts may share the same key.
-- The key type is declared after the colon.
key (bank, accountId) : (Party, Text)
-- The maintainer is responsible for key uniqueness.
-- It must be a subset of the signatories.
-- key._1 accesses the first element of the tuple (bank).
maintainer key._1
choice Deposit : ContractId Account
with amount : Decimal
controller owner
do
assertMsg "amount must be positive" (amount > 0.0)
create this with balance = balance + amount
choice Withdraw : ContractId Account
with amount : Decimal
controller owner
do
assertMsg "amount must be positive" (amount > 0.0)
assertMsg "insufficient balance" (amount <= balance)
create this with balance = balance - amount
-- ── Key lookup in a Script ───────────────────────────────
keyDemo : Script ()
keyDemo = do
bank <- allocateParty "Bank"
alice <- allocateParty "Alice"
-- Create an account
_cid <- submit bank do
createCmd Account with
bank = bank
owner = alice
accountId = "ACC-001"
balance = 0.0
-- Deposit via ContractId (normal exercise)
cid2 <- submit alice do
exerciseCmd _cid Deposit with amount = 500.0
-- Fetch by key — no ContractId needed
(cid3, account) <- submit bank do
fetchByKeyCmd @Account (bank, "ACC-001")
assert (account.balance == 500.0)
-- lookupByKey returns Optional — safe if key may not exist
mCid <- submit bank do
lookupByKeyCmd @Account (bank, "NONEXISTENT")
assert (mCid == None)