How can I implement the case that the contract requires dynamic numbers of signatories?
App Development3 posts409 views5 likesLast activity Nov 2020
XU
XuyxOP
Nov 2020Here’s my code and I don’t kown how to continue.
template ContractWithMultiSignatories
with
signatories: [Party]
where
signatory signatories
template ContracProposal
with
contract: ContractWithMultiSignatories
submitter: Party
signed: [Party]
where
signatory submitter
observer contract.signatories
controller contract.signatories can
Accept : ContractId ContractWithMultiSignatories
do
assertMsg "Somebody hasn't signed" (contract.signatories == signed)
create contract
contract_with_multi_signatories_test = do
user1 <- allocateParty "user1"
user2 <- allocateParty "user2"
user3 <- allocateParty "user3"
proposalId1 <- submit user1 do
createCmd ContracProposal with
submitter = user1
signed = [user1]
contract = ContractWithMultiSignatories with
signatories = [user1, user2, user3]
Some proposal1 <- queryContractId user2 proposalId1
proposalId2 <- submit user2 do
createCmd proposal1 with
signed = user2 :: proposal1.signed
Some proposal2 <- queryContractId user3 proposalId2
proposalId3 <- submit user3 do
createCmd proposal2 with
signed = user3 :: proposal2.signed
contractId <- submit user3 do
exerciseCmd proposalId3 Accept
pure()
RI
Richard_Kapolnai
Nov 2020Here is an example below, where a selected signatory (I call it host) invites a new one. It does not allow concurrent invitations, but I wanted to keep it very simple.
You’ll probably find useful the following blogposts. The first show a slightly different approach, the second gives you some context on the flexible controller I used.
- Removing The Limits on Signatories - A Peek Behind The Curtain - DAML
- DAML does yoga: an introduction to flexible controllers - DAML
module Multi where
import Daml.Script
template ContractWithMultiSignatories
with
signatories: [Party]
where
signatory signatories
choice Invite : ContractId Invitation with
host : Party
invitee : Party
controller host
do
-- One could add constraints like: assert (host `elem` signatories)
create Invitation with
signatories
host
invitee
template Invitation
with
signatories: [Party]
host : Party
invitee : Party
where
signatory signatories
controller invitee can
Accept : ContractId ContractWithMultiSignatories
do
create ContractWithMultiSignatories with signatories = invitee::signatories
invite_two_more_signatories = do
user1 <- allocateParty "user1"
user2 <- allocateParty "user2"
user3 <- allocateParty "user3"
first <- submit user1 do
createCmd ContractWithMultiSignatories with
signatories = [user1]
invitationForUser2 <- submit user1 do
exerciseCmd first Invite with
host = user1
invitee = user2
second <- submit user2 do
exerciseCmd invitationForUser2 Accept
invitationForUser3 <- submit user1 do
exerciseCmd second Invite with
host = user1
invitee = user3
submit user3 do
exerciseCmd invitationForUser3 Accept
BE
bernhard
Nov 2020The syntax controller contract.signatories can means “all signatories together can do this thing”, ie you need all of their authority. What you want is for any of them to be able to sign. To do that, you need to use the advanced choice syntax @Richard_Kapolnai used in his example as well:
template ContractWithMultiSignatories
with
signatories: [Party]
where
signatory signatories
template ContracProposal
with
contract: ContractWithMultiSignatories
signed: [Party]
where
signatory signed
observer contract.signatories
choice Accept : ContractId ContractWithMultiSignatories
with
accepter : Party
controller accepter
do
assertMsg "accepter needs to be a signatory" (accepter `elem` contract.signatories)
assertMsg "Somebody hasn't signed" (dedupSort contract.signatories == dedupSort signed)
create contract
choice Sign : ContractId ContracProposal
with
signer : Party
controller signer
do
assertMsg "signer needs to be a signatory" (signer `elem` contract.signatories)
create this with
signed = dedupSort (signer :: signed)
contract_with_multi_signatories_test = do
user1 <- allocateParty "user1"
user2 <- allocateParty "user2"
user3 <- allocateParty "user3"
proposalId <- submit user1 do
createCmd ContracProposal with
signed = [user1]
contract = ContractWithMultiSignatories with
signatories = [user1, user2, user3]
proposalId <- submit user2 do
exerciseCmd proposalId Sign with
signer = user2
proposalId <- submit user3 do
exerciseCmd proposalId Sign with
signer = user3
contractId <- submit user3 do
exerciseCmd proposalId Accept with
accepter = user3
pure()