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: DAO SDK #1925

Closed
wants to merge 121 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
f677f1c
feat: DA0-DA0 port
Sep 18, 2023
135287a
feat: social feed and moderation dao by @hthieu1110
Sep 18, 2023
6cc1280
chore: remove duplicates and unversion packages
Sep 18, 2023
ce2465a
chore: reset gnovm changes
Sep 18, 2023
d375b61
fix: make social feed and moderation work with latest dao packages
Sep 18, 2023
d8800be
chore: move daodao contracts under teritori dir
Sep 19, 2023
0fa396f
chore: move ujson under teritori dir
Sep 19, 2023
86d4fcc
chore: move binutils under teritori dir
Sep 19, 2023
fd7a5b3
chore: move flags_index under teritori dir
Sep 19, 2023
9c89420
chore: move havl under teritori dir
Sep 19, 2023
06d722f
chore: move markdown_utils under teritori dir
Sep 19, 2023
f9f376d
chore: move utf16 under teritori dir
Sep 19, 2023
3532d57
chore: update modboards golden test
Sep 19, 2023
380f7e7
chore: move dao_realm under teritori dir
Sep 19, 2023
3d12ce1
chore: move dao_registry under teritori dir
Sep 19, 2023
6a8e185
chore: fork groups into teritori dir
Sep 19, 2023
6ba2ba2
chore: move modboards under teritori dir
Sep 19, 2023
3ab1751
chore: move social_feeds under teritori dir
Sep 19, 2023
13b1337
chore: move social_feeds_dao under teritori dir
Sep 19, 2023
b416f44
chore: move tori under teritori dir
Sep 19, 2023
f320770
chore: update modboards golden test
Sep 19, 2023
85302e4
chore: reset gnovm changes
Sep 19, 2023
69dd461
chore: reset .gitignore changes
Sep 19, 2023
507039d
feat: escrow contract by @go7066
Sep 19, 2023
5a77310
chore: move escrow under teritori dir
Sep 19, 2023
0c01047
feat: cosmos-style voting DAO by @go7066
Sep 19, 2023
9e826d7
chore: move gnodaos under teritori dir
Sep 19, 2023
911d788
chore: add disclaimer in gnodaos
Sep 19, 2023
ea09b63
feat: justicedao and vrf by @go7066
Sep 19, 2023
225aa19
chore: move justicedao and vrf under teritori dir
Sep 19, 2023
93ac190
chore: disable test targeting test3 avl
Sep 19, 2023
34d62bb
chore: move daodao contracts at teritori root
Sep 19, 2023
f5f82eb
chore: add teritori contracts overview
Sep 19, 2023
94e02fd
feat: abstract modules config query
Sep 19, 2023
28fd066
fix: add missing imports in gno.mods
Sep 19, 2023
66ad360
feat: add tutorial to create a DAO
Sep 20, 2023
a73db3d
chore: clean dao core
Sep 21, 2023
10345cd
chore: add moderation DAO documentation
Sep 26, 2023
54f55a2
feat(ujson): add union support
Sep 26, 2023
12692b4
chore: use ujson union
Sep 26, 2023
97ac41f
feat: add voting durations
Sep 26, 2023
f0a1b10
chore: clearer error messages
Sep 26, 2023
0281ad3
fix: pass examples CI tests
Sep 27, 2023
2d7a15d
feat: check expiration in vote procedure
Sep 27, 2023
5c227f7
chore: typo in doc
Sep 27, 2023
29bdb6d
chore: fmt
Sep 28, 2023
c2a5707
feat: add social follow system (#15)
omarsy Feb 18, 2024
9cce73e
chore: tidy utf16
n0izn0iz Mar 11, 2024
f1fdc46
chore: clean ujson
n0izn0iz Mar 11, 2024
91c8303
chore: clean flags_index
n0izn0iz Mar 11, 2024
eef83fe
chore: clean dao_interfaces
n0izn0iz Mar 11, 2024
af10b75
chore: clean social_feeds
n0izn0iz Mar 11, 2024
1a729f2
chore: clean havl
n0izn0iz Mar 11, 2024
98631b5
chore: clean havl groups
n0izn0iz Mar 11, 2024
f3ed282
chore: clean markdown_utils
n0izn0iz Mar 11, 2024
397d156
chore: clean dao_core
n0izn0iz Mar 11, 2024
d92a828
chore: clean dao_utils
n0izn0iz Mar 11, 2024
76d7200
chore: clean dao_proposal_single
n0izn0iz Mar 11, 2024
6f67bef
chore: clean dao_voting_group
n0izn0iz Mar 11, 2024
f22248d
chore: clean dao_registry
n0izn0iz Mar 11, 2024
3b9983e
fix: disable broken registry in dao
n0izn0iz Mar 11, 2024
9e37291
chore: clean modboard
n0izn0iz Mar 13, 2024
215068d
chore: clean tori
n0izn0iz Mar 13, 2024
3915cb3
chore: clean dao_realm
n0izn0iz Mar 13, 2024
19e50eb
chore: clean escrow package
n0izn0iz Mar 13, 2024
dc1474c
chore: rename escrow -> projects_manager
n0izn0iz Mar 13, 2024
852a499
chore: remove vrf and justicedao
n0izn0iz Apr 10, 2024
eaf6792
chore: remove unused package
n0izn0iz Apr 10, 2024
2157ff3
chore: remove unrelated packages
n0izn0iz Apr 10, 2024
5a1307e
chore: update golden tests
n0izn0iz Apr 10, 2024
865c6d3
chore: fmt imports
n0izn0iz Apr 10, 2024
4dc53b5
chore: remove duplicate utf16
n0izn0iz Apr 10, 2024
b35749e
chore: replace ujson with official json
n0izn0iz Apr 11, 2024
6195695
chore: remove moderation stuff
n0izn0iz Apr 11, 2024
af3a8ef
feat: improve render
n0izn0iz Apr 11, 2024
c471f46
chore: remove markdown_utils
n0izn0iz Apr 11, 2024
70b461e
feat: render supported messages
n0izn0iz Apr 11, 2024
2629c68
fix: pass gno2go check
n0izn0iz Apr 11, 2024
27e4829
fix: update test
n0izn0iz Apr 11, 2024
9235af4
chore: remove obsolete comment
n0izn0iz Apr 11, 2024
1f0f2b6
chore: move docs
n0izn0iz Apr 11, 2024
d88b16d
Merge remote-tracking branch 'teritori/master' into daosdk
n0izn0iz Apr 11, 2024
67126bf
chore: improve docs
n0izn0iz Apr 11, 2024
346ca7a
chore: remove default proposal in exemple
n0izn0iz Apr 11, 2024
73f84dc
chore: precise todo
n0izn0iz Apr 11, 2024
b5a5150
chore: remove leftovers
n0izn0iz Apr 11, 2024
ef96580
feat: allow to change tori admin
n0izn0iz Apr 12, 2024
893907c
chore: remove obsolete comment
n0izn0iz Apr 12, 2024
1555f35
feat: improve dao doc
n0izn0iz Apr 12, 2024
7d4e448
Merge branch 'master' into daosdk
n0izn0iz Apr 12, 2024
a6689df
chore: fix test
n0izn0iz Apr 12, 2024
165c1a6
chore: use strings.Builder instead of concatenation
n0izn0iz Apr 13, 2024
05433bd
chore: update doc
n0izn0iz Apr 13, 2024
2fd99f5
Merge branch 'master' into daosdk
n0izn0iz Apr 14, 2024
3501f28
Merge branch 'master' into daosdk
n0izn0iz Apr 15, 2024
d7cdd9c
Merge branch 'master' into daosdk
n0izn0iz Apr 17, 2024
c1c4d97
Merge branch 'master' into daosdk
n0izn0iz Apr 22, 2024
f863190
Merge remote-tracking branch 'origin/master' into daosdk
n0izn0iz May 4, 2024
a3251f1
chore: add space after blocks
n0izn0iz May 4, 2024
e701f83
chore: improve doc
n0izn0iz May 4, 2024
66a4854
chore: improve docs
n0izn0iz May 4, 2024
5eaf156
chore: improve docs
n0izn0iz May 4, 2024
f51719c
chore: better comment
n0izn0iz May 6, 2024
7956e63
chore: rename teritori -> dao-maker
n0izn0iz May 6, 2024
9c4463d
Merge remote-tracking branch 'origin/master' into daosdk
n0izn0iz May 6, 2024
00b499f
chore: mod tidy
n0izn0iz May 6, 2024
58a8385
chore: rename dao-maker -> dao_maker because - is not supported in re…
n0izn0iz May 6, 2024
1b78823
Merge branch 'master' into daosdk
n0izn0iz May 14, 2024
f4f54a2
Merge branch 'master' into daosdk
n0izn0iz May 22, 2024
db663c7
chore: update docs
n0izn0iz Jun 17, 2024
63e3de2
chore: update docs
n0izn0iz Jun 17, 2024
6834121
feat: add update to dao_interfaces
MikaelVallenet Dec 17, 2024
af91c7f
Merge branch 'master' into daosdk
n0izn0iz Dec 17, 2024
2ca5706
chore: move everything under teritori namespace
n0izn0iz Dec 17, 2024
b690ec0
fix: remove require and tidy
n0izn0iz Dec 17, 2024
508e831
chore: gno fmt
n0izn0iz Dec 17, 2024
58c1011
chore: update tori with new grc20 apis
n0izn0iz Dec 17, 2024
98afc2f
chore: update usage after interface change
n0izn0iz Dec 17, 2024
1e87380
Merge branch 'master' into daosdk
n0izn0iz Dec 17, 2024
648a09d
fix: gnoweb UI styles (#3349)
alexiscolin Dec 17, 2024
252b21a
Merge remote-tracking branch 'origin/master' into daosdk
n0izn0iz Dec 17, 2024
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
15 changes: 15 additions & 0 deletions examples/gno.land/p/demo/users/types.gno
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package users

import (
"std"
)

type AddressOrName string

func (aon AddressOrName) IsName() bool {
Expand All @@ -12,3 +16,14 @@ func (aon AddressOrName) GetName() (string, bool) {
}
return "", false
}

func (aon AddressOrName) IsValid() bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about using users.Resolve(aon).IsValid()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't call the realm method users.Resolve from a p package

if len(aon) == 0 {
return false
}
if aon[0] == '@' {
// TODO: validate name better
return len(aon) >= 2
}
return std.Address(aon).IsValid()
}
57 changes: 57 additions & 0 deletions examples/gno.land/p/demo/users/users_test.gno
Original file line number Diff line number Diff line change
@@ -1 +1,58 @@
package users

import (
"testing"
)

func TestAddressOrNameValidation(t *testing.T) {
tests := []struct {
name string
address string
expected bool
}{
{
name: "Valid address",
address: "g18syxa0vh0vmne90mwhtynjet0zgeqf6prh3ryy",
expected: true,
},
{
name: "Invalid address",
address: "0x123456789012345678901234567890123456789",
expected: false,
},
{
name: "Valid name",
address: "@test",
expected: true,
},
{
name: "Invalid name",
address: "test@",
expected: false,
},
{
name: "Empty",
address: "",
expected: false,
},
{
name: "Only @",
address: "@",
expected: false,
},
{
name: "One letter",
address: "@a",
expected: true,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result := AddressOrName(test.address).IsValid()
if result != test.expected {
t.Errorf("Expected %v, got %v", test.expected, result)
}
})
}
}
206 changes: 206 additions & 0 deletions examples/gno.land/p/teritori/dao_core/dao_core.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package core

import (
"std"
"strconv"
"strings"

dao_interfaces "gno.land/p/teritori/dao_interfaces"
)

// TODO: add wrapper message handler to handle multiple proposal modules messages

type daoCore struct {
dao_interfaces.IDAOCore

votingModule dao_interfaces.IVotingModule
proposalModules []dao_interfaces.ActivableProposalModule
activeProposalModuleCount int
realm std.Realm
registry *dao_interfaces.MessagesRegistry
}

func NewDAOCore(
votingModuleFactory dao_interfaces.VotingModuleFactory,
proposalModulesFactories []dao_interfaces.ProposalModuleFactory,
messageHandlersFactories []dao_interfaces.MessageHandlerFactory,
) dao_interfaces.IDAOCore {
if votingModuleFactory == nil {
panic("Missing voting module factory")
}

if len(proposalModulesFactories) == 0 {
panic("No proposal modules factories")
}

core := &daoCore{
realm: std.CurrentRealm(),
activeProposalModuleCount: len(proposalModulesFactories),
registry: dao_interfaces.NewMessagesRegistry(),
proposalModules: make([]dao_interfaces.ActivableProposalModule, len(proposalModulesFactories)),
}

core.votingModule = votingModuleFactory(core)
if core.votingModule == nil {
panic("voting module factory returned nil")
}

for i, modFactory := range proposalModulesFactories {
mod := modFactory(core)
if mod == nil {
panic("proposal module factory returned nil")
}

core.proposalModules[i] = dao_interfaces.ActivableProposalModule{
Enabled: true,
Module: mod,
}
}

// this registry is specific to gno since we can't do dynamic calls
core.registry.Register(NewUpdateVotingModuleMessageHandler(core))
core.registry.Register(NewUpdateProposalModulesMessageHandler(core))
for _, handlerFactory := range messageHandlersFactories {
handler := handlerFactory(core)
if handler == nil {
panic("message handler factory returned nil")
}

core.registry.Register(handler)
}

return core
}

// mutations

func (d *daoCore) UpdateVotingModule(newVotingModule dao_interfaces.IVotingModule) {
if std.CurrentRealm().Addr() != d.realm.Addr() { // not sure this check necessary since the ownership system should protect against mutation from other realms
panic(ErrUnauthorized)
}

d.votingModule = newVotingModule
}

func (d *daoCore) UpdateProposalModules(toAdd []dao_interfaces.IProposalModule, toDisable []int) {
if std.CurrentRealm().Addr() != d.realm.Addr() { // not sure this check necessary since the ownership system should protect against mutation from other realms
panic(ErrUnauthorized)
}

for _, module := range toAdd {
d.addProposalModule(module)
}

for _, moduleIndex := range toDisable {
module := GetProposalModule(d, moduleIndex)

if !module.Enabled {
panic(ErrModuleAlreadyDisabled)
}

module.Enabled = false

d.activeProposalModuleCount--
if d.activeProposalModuleCount == 0 {
panic("no active proposal modules") // this -> `panic(ErrNoActiveProposalModules)` triggers `panic: reflect: reflect.Value.SetString using value obtained using unexported field`
}
}
}

// queries

func (d *daoCore) ProposalModules() []dao_interfaces.ActivableProposalModule {
return d.proposalModules
}

func (d *daoCore) VotingModule() dao_interfaces.IVotingModule {
return d.votingModule
}

func (d *daoCore) VotingPowerAtHeight(address std.Address, height int64) uint64 {
return d.VotingModule().VotingPowerAtHeight(address, height, []string{})
}

func (d *daoCore) ActiveProposalModuleCount() int {
return d.activeProposalModuleCount
}

func (d *daoCore) Render(path string) string {
sb := strings.Builder{}
sb.WriteString("# DAO Core\n")
votingInfo := d.votingModule.Info()
sb.WriteString("## Voting Module: ")
sb.WriteString(votingInfo.String())
sb.WriteRune('\n')
sb.WriteString(d.votingModule.Render(""))
sb.WriteString("## Supported Messages:\n")
sb.WriteString(d.registry.Render())

sb.WriteString("## Proposal Modules:\n")
for i, propMod := range d.proposalModules {
if !propMod.Enabled {
continue
}

info := propMod.Module.Info()
sb.WriteString("### #")
sb.WriteString(strconv.Itoa(i))
sb.WriteString(": ")
sb.WriteString(info.String())
sb.WriteRune('\n')
sb.WriteString(propMod.Module.Render(""))
}

sb.WriteRune('\n')
return sb.String()
}

func (d *daoCore) Registry() *dao_interfaces.MessagesRegistry {
return d.registry
}

// TODO: move this helper in dao interfaces

func GetProposalModule(core dao_interfaces.IDAOCore, moduleIndex int) *dao_interfaces.ActivableProposalModule {
if moduleIndex < 0 {
panic("module index must be >= 0")
}

mods := core.ProposalModules()
if moduleIndex >= len(mods) {
panic("invalid module index")
}

return &mods[moduleIndex]
}

// internal

func (d *daoCore) executeMsgs(msgs []dao_interfaces.ExecutableMessage) {
for _, msg := range msgs {
d.registry.Execute(msg)
}
}

func (d *daoCore) addProposalModule(proposalMod dao_interfaces.IProposalModule) {
for _, mod := range d.proposalModules {
if mod.Module != proposalMod {
continue
}

if mod.Enabled {
panic(ErrModuleAlreadyAdded)
}

mod.Enabled = true
d.activeProposalModuleCount++
return
}

d.proposalModules = append(d.proposalModules, dao_interfaces.ActivableProposalModule{
Enabled: true,
Module: proposalMod,
})

d.activeProposalModuleCount++
}
Loading
Loading