In a maker checker setup, does it make sense to have a Party that doesn’t have a User post initialisation, and only acts indirectly via a role template that guards it with a maker checker workflow ?
Using the simple Asset in the skeleton
project as an example , some motivations here I have are:
- I don’t want to modify the Asset template’s Give choice, because Charlie may not care about
institution
's internal maker checker process. - Similarly they may not want to see Alice & Bob as signatories on Asset. If Institution changes its approval process to 2 of Alice, Bob, David, we probably don’t want to upgrade Asset as a result of that ?
- Reuse potentially complex maker-checker logic in one place, and not place it into every maker checker guarded choices
- Preserve the audit trail on Alice & Bob’s actions on ledger, vs elsewhere in the system
Code below:
module Main where
import Daml.Script
type AssetId = ContractId Asset
-- Unmodified Asset
template Asset
with
issuer : Party
owner : Party
name : Text
where
ensure name /= ""
signatory issuer
observer owner
choice Give : AssetId
with
newOwner : Party
controller owner
do create this with
owner = newOwner
template GiveProposed
with
actor : Party
give: Give
assetId: AssetId
maker: Party
checker: Party
where
signatory maker, actor
observer checker
choice Approve: AssetId
controller checker
do exercise assetId give
template MakerChecker
with
actor: Party
maker: Party
checker: Party
where
signatory actor
observer maker, checker
nonconsuming choice Give': ContractId GiveProposed
with
give: Give
assetId: AssetId
controller maker
do create GiveProposed with
give
actor
maker
checker
assetId
Daml Script:
run : Script ()
run = script do
-- user_setup_begin
institution <- allocatePartyWithHint "Institution" (PartyIdHint "Institution")
alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")
bob <- allocatePartyWithHint "Bob" (PartyIdHint "Bob")
charlie <- allocatePartyWithHint "Charlie" (PartyIdHint "Charlie")
aliceId <- validateUserId "alice"
bobId <- validateUserId "bob"
institutionId <- validateUserId "institution"
charlieId <- validateUserId "bob"
createUser (User aliceId (Some alice)) [CanActAs alice, CanReadAs institution]
createUser (User bobId (Some bob)) [CanActAs bob, CanReadAs institution]
createUser (User institutionId (Some institution)) [CanActAs institution]
-- user_setup_end
aliceTV <- submitUser institutionId do
createCmd Asset with
issuer = institution
owner = institution
name = "TV"
mcId <- submitUser institutionId do
createCmd MakerChecker with
actor = institution
maker = alice
checker = bob
deleteUser institutionId
--No one can act as the institution Party directly from here onwards
--Alice is maker, Bob is Checker
pId <- submit alice do
exerciseCmd mcId Give' with
give = Give with
newOwner = charlie
assetId = aliceTV
submitUser bobId do
exerciseCmd pId Approve
pure ()