Skip to content

Commit

Permalink
Add GetVoteByMember to proposal API
Browse files Browse the repository at this point in the history
  • Loading branch information
zivkovicmilos committed Jul 14, 2024
1 parent 3a7ba00 commit 00056a5
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 22 deletions.
41 changes: 39 additions & 2 deletions examples/gno.land/p/demo/simpledao/propstore.gno
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import (
pproposal "gno.land/p/gov/proposal"
)

var errMissingProposal = errors.New("proposal is missing")
var (
errMissingProposal = errors.New("proposal is missing")
errMissingVote = errors.New("member has not voted")
)

// proposal is the internal simpledao proposal implementation
type proposal struct {
Expand All @@ -36,7 +39,41 @@ func (p *proposal) GetStatus() dao.Status {
}

func (p *proposal) GetVotes() []dao.Vote {
return p.votes.getVotes()
var (
voters = p.votes.getVoters()
votes = make([]dao.Vote, 0, voters.Size())
)

voters.Iterate("", "", func(key string, val interface{}) bool {
option := val.(dao.VoteOption)

vote := dao.Vote{
Address: std.Address(key),
Option: option,
}

votes = append(votes, vote)

return false
})

return votes
}

func (p *proposal) GetVoteByMember(address std.Address) (dao.Vote, error) {
voters := p.votes.getVoters()

optionRaw, exists := voters.Get(address.String())
if !exists {
return dao.Vote{}, errMissingVote
}

vote := dao.Vote{
Address: address,
Option: optionRaw.(dao.VoteOption),
}

return vote, nil
}

// PropStore implements the dao.PropStore abstraction
Expand Down
38 changes: 38 additions & 0 deletions examples/gno.land/p/demo/simpledao/propstore_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,44 @@ func TestProposal_Data(t *testing.T) {
}
}
})

t.Run("vote by member", func(t *testing.T) {
t.Parallel()

var (
members = generateMembers(t, 50)
p = &proposal{
votes: newVotes(),
}
)

for _, m := range members {
urequire.NoError(t, p.votes.castVote(m, dao.YesVote))
}

votes := p.GetVotes()
urequire.Equal(t, len(members), len(votes))

vote, err := p.GetVoteByMember(members[0].Address)
urequire.NoError(t, err)

uassert.Equal(t, dao.YesVote.String(), vote.Option.String())
uassert.Equal(t, members[0].Address.String(), vote.Address.String())
})

t.Run("missing vote by member", func(t *testing.T) {
t.Parallel()

p := &proposal{
votes: newVotes(),
}

votes := p.GetVotes()
urequire.Equal(t, 0, len(votes))

_, err := p.GetVoteByMember(testutils.TestAddress("dummy"))
uassert.ErrorIs(t, err, errMissingVote)
})
}

func TestPropStore_GetProposals(t *testing.T) {
Expand Down
23 changes: 3 additions & 20 deletions examples/gno.land/p/demo/simpledao/vote.gno
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package simpledao
import (
"errors"

"std"

"gno.land/p/demo/avl"
"gno.land/p/gov/dao"
)
Expand Down Expand Up @@ -55,22 +53,7 @@ func (v *votes) getTally() (uint64, uint64) {
return v.yays, v.nays
}

// getVotes fetches the currently active vote set
func (v *votes) getVotes() []dao.Vote {
votes := make([]dao.Vote, 0, v.voters.Size())

v.voters.Iterate("", "", func(key string, val interface{}) bool {
option := val.(dao.VoteOption)

vote := dao.Vote{
Address: std.Address(key),
Option: option,
}

votes = append(votes, vote)

return false
})

return votes
// getVoters returns the current voter set
func (v *votes) getVoters() *avl.Tree {
return v.voters
}
3 changes: 3 additions & 0 deletions examples/gno.land/p/gov/dao/proposal.gno
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,7 @@ type Proposal interface {

// GetVotes returns the votes of the proposal
GetVotes() []Vote

// GetVoteByMember returns the proposal vote by the member, if any
GetVoteByMember(address std.Address) (Vote, error)
}

0 comments on commit 00056a5

Please sign in to comment.