How to do on ledger maker checker?
App Development3 posts260 viewsLast activity Apr 2023
FE
Felix_KamOP
Apr 2023In 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 ()
BE
bernhard
Apr 2023Yes, it’s not an uncommon pattern to have an “operator” party that’s only actively involved during application bootstrapping and upgrades, and during normal operations only signs through delegations.
FE
Felix_Kam
Apr 2023Thank you !