Skip to content

Commit

Permalink
feat(gno/dao): handle vote
Browse files Browse the repository at this point in the history
  • Loading branch information
MikaelVallenet committed Jan 9, 2025
1 parent 5462332 commit a798fe1
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 45 deletions.
39 changes: 37 additions & 2 deletions gno/p/dao_roles_based/dao_roles_based.gno
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,48 @@ func NewDaoRolesBasedJSON(rolesJSON, membersJSON, resourcesJSON string) *DaoRole
return dao
}

func (d *DaoRolesBased) NewProposal(title, description string) {
func (d *DaoRolesBased) Vote(proposalID uint64, vote string) {
// 3th caller is the voter, 2nd is the dao realm, 1st is the dao_roles_based module
voter := std.GetCallerAt(3)
if !d.MemberModule.IsMember(voter.String()) {
panic("voter is not a member")
}

proposal := d.ProposalModule.getProposal(proposalID)
if proposal == nil {
panic("proposal not found")
}

if proposal.status != ProposalStatusOpen {
panic("proposal is not open")
}

if daocond.Vote(vote) != daocond.VoteYes && daocond.Vote(vote) != daocond.VoteNo && daocond.Vote(vote) != daocond.VoteAbstain {
panic("invalid vote")
}

e := &daocond.EventVote{
VoterID: voter.String(),
Vote: daocond.Vote(vote),
}

proposal.state.HandleEvent(e, proposal.votes)
proposal.votes[voter.String()] = daocond.Vote(vote)

}

func (d *DaoRolesBased) NewProposal(title, description, resource string) {
// 3th caller is the proposer, 2nd is the dao realm, 1st is the dao_roles_based module
proposer := std.GetCallerAt(3)
if !d.MemberModule.IsMember(proposer.String()) {
panic("proposer is not a member")
}

condition := d.ResourcesModule.getResource(resource)
if condition == nil {
panic("resource not found")
}

if len(title) < 9 {
panic("title should be at least 9 characters long")
}
Expand All @@ -49,7 +84,7 @@ func (d *DaoRolesBased) NewProposal(title, description string) {
panic("description should be at least 15 characters long")
}

d.ProposalModule.newProposal(title, description, proposer)
d.ProposalModule.newProposal(title, description, proposer, condition.NewState())
}

func (d *DaoRolesBased) HasRole(memberId string, role string) bool {
Expand Down
47 changes: 26 additions & 21 deletions gno/p/dao_roles_based/proposals.gno
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"gno.land/p/demo/avl"
"gno.land/p/demo/seqid"
"gno.land/p/teritori/daocond"
)

type ProposalStatus int
Expand All @@ -28,26 +29,21 @@ func (s ProposalStatus) String() string {
}
}

type Votes struct {
Yes uint64
No uint64
Abstain uint64
}

type Proposal struct {
ID seqid.ID
Title string
Description string
Proposer std.Address
id seqid.ID
title string
description string
proposer std.Address
resource string
state daocond.State
// StartHeight int64
//MinVotingPeriod dao_utils.Expiration // copy here the dao_utils.Expiration type from gno/p/dao_utils/expiration.gno
//Expiration dao_utils.Expiration // copy here the dao_utils.Expiration type from gno/p/dao_utils/expiration.gno
// Threshold Threshold: Treshold should be handle in the conditions
//Message dao_interfaces.ExecutableMessage // copy here the dao_interfaces.ExecutableMessage type from gno/p/dao_interfaces/messages.gno
Status ProposalStatus
Votes Votes
status ProposalStatus
// AllowRevoting bool not handled in this proposal
Ballots *avl.Tree // std.Address -> Ballot
votes map[string]daocond.Vote
}

type ProposalModule struct {
Expand All @@ -61,16 +57,25 @@ func newProposalModule() *ProposalModule {
}
}

func (p *ProposalModule) newProposal(title, description string, proposer std.Address) {
func (p *ProposalModule) newProposal(title, description string, proposer std.Address, state daocond.State) {
id := p.proposalIDCounter.Next()
proposal := &Proposal{
ID: id,
Title: title,
Description: description,
Proposer: proposer,
Status: ProposalStatusOpen,
Votes: Votes{},
Ballots: avl.NewTree(),
id: id,
title: title,
description: description,
proposer: proposer,
status: ProposalStatusOpen,
state: state,
votes: map[string]daocond.Vote{},
}
p.proposals.Set(id.String(), proposal)
}

func (p *ProposalModule) getProposal(id uint64) *Proposal {
value, ok := p.proposals.Get(seqid.ID(id).String())
if !ok {
return nil
}
proposal := value.(*Proposal)
return proposal
}
10 changes: 5 additions & 5 deletions gno/p/dao_roles_based/render.gno
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ func (p *ProposalModule) Render() string {
i := 1
p.proposals.Iterate("", "", func(key string, value interface{}) bool {
proposal := value.(*Proposal)
sb.WriteString((ufmt.Sprintf("**Proposal %d: %s**\n\n", i, proposal.Title)))
sb.WriteString((ufmt.Sprintf("Description: %s\n\n", proposal.Description)))
sb.WriteString((ufmt.Sprintf("Proposer: %s\n\n", proposal.Proposer)))
sb.WriteString((ufmt.Sprintf("Status: %s\n\n", proposal.Status.String())))
sb.WriteString((ufmt.Sprintf("Votes: Yes: %d, No: %d, Abstain: %d\n\n", proposal.Votes.Yes, proposal.Votes.No, proposal.Votes.Abstain)))
sb.WriteString((ufmt.Sprintf("**Proposal %d: %s**\n\n", i, proposal.title)))
sb.WriteString((ufmt.Sprintf("Description: %s\n\n", proposal.description)))
sb.WriteString((ufmt.Sprintf("Proposer: %s\n\n", proposal.proposer)))
sb.WriteString((ufmt.Sprintf("Status: %s\n\n", proposal.status.String())))
sb.WriteString((ufmt.Sprintf("State: %s\n\n", proposal.state.RenderJSON(proposal.votes).String())))
sb.WriteString((ufmt.Sprintf("\n--------------------------------\n")))
i += 1
return false
Expand Down
12 changes: 11 additions & 1 deletion gno/p/dao_roles_based/resources.gno
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package dao_roles_based

import (
"gno.land/p/demo/avl"
"gno.land/p/teritori/daocond"
)

type ResourcesModule struct {
resources *avl.Tree // string -> daocond.Condition
resources *avl.Tree // string -> *daocond.Condition
}

func newResourcesModule() *ResourcesModule {
Expand All @@ -17,3 +18,12 @@ func newResourcesModule() *ResourcesModule {
func (r *ResourcesModule) setResources(resources *avl.Tree) {
r.resources = resources
}

func (r *ResourcesModule) getResource(name string) daocond.Condition {
value, ok := r.resources.Get(name)
if !ok {
return nil
}
condition := value.(daocond.Condition)
return condition
}
15 changes: 0 additions & 15 deletions gno/p/dao_roles_based/voting.gno

This file was deleted.

6 changes: 5 additions & 1 deletion gno/r/dao_realm2/dao_realm2.gno
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ func init() {
}

func Proposal(title, description string) {
dao.NewProposal(title, description)
dao.NewProposal(title, description, "social.publish_post")
}

func Vote(proposalID uint64, vote string) {
dao.Vote(proposalID, vote)
}

func Render(path string) string {
Expand Down

0 comments on commit a798fe1

Please sign in to comment.