Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(comondao): change commondao package to use addrset for members #3813

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 7 additions & 32 deletions examples/gno.land/p/nt/commondao/commondao.gno
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import (
"gno.land/p/demo/avl"
"gno.land/p/demo/avl/rotree"
"gno.land/p/demo/seqid"
"gno.land/p/moul/addrset"
)

var (
ErrInvalidVoteChoice = errors.New("invalid vote choice")
ErrMemberExists = errors.New("member already exist")
ErrNotMember = errors.New("account is not a member of the DAO")
ErrOverflow = errors.New("next ID overflows uint64")
ErrProposalNotFound = errors.New("proposal not found")
Expand All @@ -24,7 +24,7 @@ type (
// CommonDAO defines a DAO.
CommonDAO struct {
parent *CommonDAO
members *avl.Tree // string(std.Address) -> struct{}
members *addrset.Set
genID seqid.ID
active *avl.Tree // string(proposal ID) -> *Proposal
finished *avl.Tree // string(proposal ID) -> *Proposal
Expand All @@ -41,7 +41,7 @@ type (
// New creates a new common DAO.
func New(options ...Option) *CommonDAO {
dao := &CommonDAO{
members: avl.NewTree(),
members: &addrset.Set{},
active: avl.NewTree(),
finished: avl.NewTree(),
}
Expand All @@ -58,33 +58,8 @@ func (dao CommonDAO) Parent() *CommonDAO {
}

// Members returns the list of DAO members.
func (dao CommonDAO) Members() []std.Address {
var members []std.Address
dao.members.Iterate("", "", func(key string, _ interface{}) bool {
members = append(members, std.Address(key))
return false
})
return members
}

// AddMember adds a new member to the DAO.
func (dao *CommonDAO) AddMember(user std.Address) error {
if dao.IsMember(user) {
return ErrMemberExists
}
dao.members.Set(user.String(), struct{}{})
return nil
}

// RemoveMember removes a member from the DAO.
func (dao *CommonDAO) RemoveMember(user std.Address) (removed bool) {
_, removed = dao.members.Remove(user.String())
return removed
}

// IsMember checks if a user is a member of the DAO.
func (dao CommonDAO) IsMember(user std.Address) bool {
return dao.members.Has(user.String())
func (dao CommonDAO) Members() *addrset.Set {
return dao.members
}

// ActiveProposals returns all active DAO proposals.
Expand Down Expand Up @@ -138,7 +113,7 @@ func (dao *CommonDAO) Vote(member std.Address, proposalID uint64, c VoteChoice)
return ErrInvalidVoteChoice
}

if !dao.IsMember(member) {
if !dao.Members().Has(member) {
return ErrNotMember
}

Expand All @@ -157,7 +132,7 @@ func (dao *CommonDAO) Tally(p *Proposal) Stats {
NayVotes: record.VoteCount(ChoiceNo),
}
votesCount := stats.YayVotes + stats.NayVotes
membersCount := len(dao.Members())
membersCount := dao.Members().Size()
stats.Abstained = membersCount - votesCount

percentage := float64(votesCount) / float64(membersCount)
Expand Down
38 changes: 22 additions & 16 deletions examples/gno.land/p/nt/commondao/commondao_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func TestNew(t *testing.T) {

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
membersCount := len(tc.members)
options := []Option{WithParent(tc.parent)}
for _, m := range tc.members {
options = append(options, WithMember(m))
Expand All @@ -54,39 +55,44 @@ func TestNew(t *testing.T) {
uassert.NotEqual(t, nil, dao.Parent())
}

urequire.Equal(t, len(tc.members), len(dao.Members()), "dao members")
for i, m := range dao.Members() {
uassert.Equal(t, tc.members[i], m)
}
urequire.Equal(t, membersCount, dao.Members().Size(), "dao members")

var i int
dao.Members().IterateByOffset(0, membersCount, func(addr std.Address) bool {
uassert.Equal(t, tc.members[i], addr)
i++
return false
})
})
}
}

func TestCommonDAOAddMember(t *testing.T) {
func TestCommonDAOMembersAdd(t *testing.T) {
member := std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
dao := New(WithMember("g1w4ek2u33ta047h6lta047h6lta047h6ldvdwpn"))

err := dao.AddMember(member)
urequire.NoError(t, err)
uassert.Equal(t, 2, len(dao.Members()))
uassert.True(t, dao.IsMember(member))
added := dao.Members().Add(member)
urequire.True(t, added)

uassert.Equal(t, 2, dao.Members().Size())
uassert.True(t, dao.Members().Has(member))

err = dao.AddMember(member)
uassert.ErrorIs(t, err, ErrMemberExists)
added = dao.Members().Add(member)
urequire.False(t, added)
}

func TestCommonDAORemoveMember(t *testing.T) {
func TestCommonDAOMembersRemove(t *testing.T) {
member := std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
dao := New(WithMember(member))

removed := dao.RemoveMember(member)
removed := dao.Members().Remove(member)
urequire.True(t, removed)

removed = dao.RemoveMember(member)
removed = dao.Members().Remove(member)
urequire.False(t, removed)
}

func TestCommonDAOIsMember(t *testing.T) {
func TestCommonDAOMembersHas(t *testing.T) {
cases := []struct {
name string
member std.Address
Expand All @@ -108,7 +114,7 @@ func TestCommonDAOIsMember(t *testing.T) {

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := tc.dao.IsMember(tc.member)
got := tc.dao.Members().Has(tc.member)
uassert.Equal(t, got, tc.want)
})
}
Expand Down
19 changes: 17 additions & 2 deletions examples/gno.land/p/nt/commondao/options.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package commondao

import "std"
import (
"std"

"gno.land/p/moul/addrset"
)

// Option configures the CommonDAO.
type Option func(*CommonDAO)
Expand All @@ -15,6 +19,17 @@ func WithParent(p *CommonDAO) Option {
// WithMember assigns a member to the DAO.
func WithMember(addr std.Address) Option {
return func(dao *CommonDAO) {
dao.members.Set(addr.String(), struct{}{})
dao.members.Add(addr)
}
}

// WithMembers assigns multiple members to the DAO.
// An empty member set is used by default when specified members set is nil.
func WithMembers(members *addrset.Set) Option {
return func(dao *CommonDAO) {
if members == nil {
members = &addrset.Set{}
}
dao.members = members
}
}
Loading