Reputation: 148
I'm new to DAML and have been scratching my head over this for two solid days. In this voting system specified in "template Voting", an actor has the ability to add a voter party to a list of voters specified as "choice Add". This voters list (I presume a list) is defined as "voters : Set Party", (of which I can't seem to find the definition), and some conditions are defined in "Choice Vote" and "Choice Decide".
I'm trying to remove the "Choice Add" ability and instead pre-define all voters in a list defined in a separate template. If I understand correctly these predefined voters must be declared as a list: [Party] I created a template called "Creation" containing some variables in conjunction with a custom type called "CreationRights" containing the to be voters list which must be referenced from the voting template. However, I can't seem to refer to this list in any way. Changing the voters data type to [Party] also gives an error for "voters" in Choice Decide and Choice Vote. rendering the conditions specified unusable:
Couldn't match expected type 'Set a1' with actual type '[Party]'
How can I reference to the predefined voters (votingRight) list while still applying the condition set? Any tips are very welcome!
Code:
data CreationRights = CreationRights
with
votingRight : [Party]
deriving (Eq, Show)
template Creation
with
actor : Party
creationId : Text
title : Text
votingRight : CreationRights
where
signatory actor
template Voting
with
actor : Party
claim : Claim
voters : Set Party
voted : Set Party
votes : [Bool]
where
signatory actor, voted
observer voters
key (actor, claim) : VotingKey
maintainer key._1
---choice Add : ()
---with voter : Party
---controller actor
---do
---create this with voters = S.insert voter voters
---pure ()
choice Decide : ContractId Decision
controller actor
do
assertMsg "At least 60% must have voted" $ ((size voters / 100) * 60) <= length votes
let approvals = length $ L.filter (\v -> v) votes
let disapprovals = length $ L.filter (\v -> not v) votes
let accept = approvals > disapprovals
create Decision with ..
choice Vote : ()
with
voter : Party
accept : Bool
controller voter
do
assertMsg "Voter not added" $ member voter voters
assertMsg "Voter already voted" $ not $ member voter voted
create this with voted = S.insert voter voted; votes = accept :: votes
pure ()
template Decision
with
actor : Party
claim : Claim
voters : Set Party
accept : Bool
where
signatory actor, voters
Upvotes: 1
Views: 184
Reputation: 3585
You don't have to do any of this to create a Voting
instance without using Add
. Voting
defines its signatories to be actor, voted
, so if voted
is either empty or a singleton containing the same party, then the initial Voting
instance only has one signatory. That means it can be created directly by actor
without further interactions. I have included a simplified demonstration of this at the end of this answer.
Given you have created an instance of the Creation
, you will have a copy of your list of voters on the ledger. At that point, if you want to use that list, you will have to either exercise a choice on that contract or read that contract off the ledger. You can do the latter with fetch
, fetchByKey
, lookup
, and lookupByKey
within a choice on another contract (although you will need to provide either the key or contractId). However as this template instance represents an authority to create Voting
instances, representing this authority directly as a choice on Creation
is recommended.
Finally, if you change the datatype of voters
from a Set
to a List
then you will also have to change the corresponding functions that use that parameter. So, for instance, S.insert voter voted
would have to become voter :: voted
or similar.
daml 1.2
module Voting where
import DA.Next.Set as S
import DA.List as L
type Claim = Text
type VotingKey = (Party, Claim)
template Voting
with
actor : Party
claim : Claim
voters : Set Party
voted : Set Party
votes : [Bool]
where
signatory actor, voted
observer voters
key (actor, claim) : VotingKey
maintainer key._1
choice Decide : ContractId Decision
controller actor
do
assertMsg "At least 60% must have voted" $ ((size voters / 100) * 60) <= length votes
let approvals = length $ L.filter identity votes
let disapprovals = length $ L.filter not votes
let accept = approvals > disapprovals
create Decision with actor; claim; voters; accept
choice Vote : ContractId Voting
with
voter : Party
accept : Bool
controller voter
do
assertMsg "Voter not added" $ member voter voters
assertMsg "Voter already voted" . not $ member voter voted
create this with voted = S.insert voter voted; votes = accept :: votes
template Decision
with
actor : Party
claim : Claim
voters : Set Party
accept : Bool
where
signatory actor, voters
test = scenario do
alice <- getParty "Alice"
bob <- getParty "Bob"
charlie <- getParty "Charlie"
alice `submit` create
Voting with
actor = alice
claim = "Pizza"
voters = fromList [ alice, bob, charlie ]
voted = empty
votes = []
Upvotes: 2