types.gno
5.20 Kb ยท 224 lines
1package dao
2
3import (
4 "chain/runtime"
5 "errors"
6
7 "gno.land/p/nt/avl"
8 "gno.land/p/nt/seqid"
9)
10
11type ProposalID int64
12
13func (pid ProposalID) String() string {
14 return seqid.ID(pid).String()
15}
16
17// VoteOption is the limited voting option for a DAO proposal
18// New govDAOs can create their own VoteOptions if needed in the
19// future.
20type VoteOption string
21
22const (
23 AbstainVote VoteOption = "ABSTAIN" // Side is not chosen
24 YesVote VoteOption = "YES" // Proposal should be accepted
25 NoVote VoteOption = "NO" // Proposal should be rejected
26)
27
28type VoteRequest struct {
29 Option VoteOption
30 ProposalID ProposalID
31 Metadata interface{}
32}
33
34func NewProposalRequest(title string, description string, executor Executor) ProposalRequest {
35 return ProposalRequest{
36 title: title,
37 description: description,
38 executor: executor,
39 }
40}
41
42func NewProposalRequestWithFilter(title string, description string, executor Executor, filter Filter) ProposalRequest {
43 return ProposalRequest{
44 title: title,
45 description: description,
46 executor: executor,
47 filter: filter,
48 }
49}
50
51type Filter interface{}
52
53type ProposalRequest struct {
54 title string
55 description string
56 executor Executor
57 filter Filter
58}
59
60func (p *ProposalRequest) Title() string {
61 return p.title
62}
63
64func (p *ProposalRequest) Description() string {
65 return p.description
66}
67
68func (p *ProposalRequest) Filter() Filter {
69 return p.filter
70}
71
72type Proposal struct {
73 author address
74
75 title string
76 description string
77
78 executor Executor
79 allowedDAOs []string
80}
81
82func (p *Proposal) Author() address {
83 return p.author
84}
85
86func (p *Proposal) Title() string {
87 return p.title
88}
89
90func (p *Proposal) Description() string {
91 return p.description
92}
93
94func (p *Proposal) ExecutorString() string {
95 if p.executor != nil {
96 return p.executor.String()
97 }
98
99 return ""
100}
101
102func (p *Proposal) AllowedDAOs() []string {
103 return p.allowedDAOs
104}
105
106type Proposals struct {
107 seq seqid.ID
108 *avl.Tree // *avl.Tree[ProposalID]*Proposal
109}
110
111func NewProposals() *Proposals {
112 return &Proposals{Tree: avl.NewTree()}
113}
114
115func (ps *Proposals) SetProposal(p *Proposal) ProposalID {
116 pid := ProposalID(int64(ps.seq))
117 updated := ps.Set(pid.String(), p)
118 if updated {
119 panic("fatal error: Override proposals is not allowed")
120 }
121 ps.seq = ps.seq.Next()
122 return pid
123}
124
125func (ps *Proposals) GetProposal(pid ProposalID) *Proposal {
126 pv, ok := ps.Get(pid.String())
127 if !ok {
128 return nil
129 }
130
131 return pv.(*Proposal)
132}
133
134type Executor interface {
135 Execute(cur realm) error
136 String() string
137}
138
139func NewSimpleExecutor(callback func(realm) error, description string) *SimpleExecutor {
140 return &SimpleExecutor{
141 callback: callback,
142 desc: description,
143 }
144}
145
146// SimpleExecutor implements the Executor interface using
147// a callback function and a description string.
148type SimpleExecutor struct {
149 callback func(realm) error
150 desc string
151}
152
153func (e *SimpleExecutor) Execute(cur realm) error {
154 return e.callback(cross)
155}
156
157func (e *SimpleExecutor) String() string {
158 return e.desc
159}
160
161func NewSafeExecutor(e Executor) *SafeExecutor {
162 return &SafeExecutor{
163 e: e,
164 }
165}
166
167// SafeExecutor wraps an Executor to only allow its execution
168// by allowed govDAOs.
169type SafeExecutor struct {
170 e Executor
171}
172
173func (e *SafeExecutor) Execute(cur realm) error {
174 // Verify the caller is an adequate Realm
175 if !InAllowedDAOs(runtime.PreviousRealm().PkgPath()) {
176 return errors.New("execution only allowed by validated govDAOs")
177 }
178
179 return e.e.Execute(cross)
180}
181
182func (e *SafeExecutor) String() string {
183 return e.e.String()
184}
185
186type DAO interface {
187 // PreCreateProposal is called just before creating a new Proposal
188 // It is intended to be used to get the address of the proposal, that
189 // may vary depending on the DAO implementation, and to validate that
190 // the requester is allowed to do a proposal
191 PreCreateProposal(r ProposalRequest) (address, error)
192
193 // PostCreateProposal is called after creating the Proposal. It is
194 // intended to be used as a way to store a new proposal status, that
195 // depends on the actuall govDAO implementation
196 PostCreateProposal(r ProposalRequest, pid ProposalID)
197
198 // VoteOnProposal will send a petition to vote for a specific proposal
199 // to the actual govDAO implementation
200 VoteOnProposal(r VoteRequest) error
201
202 // PreGetProposal is called when someone is trying to get a proposal by ID.
203 // Is intended to be used to validate who can query proposals, just in case
204 // the actual govDAO implementation wants to limit the access.
205 PreGetProposal(pid ProposalID) error
206
207 // PostGetProposal is called after the proposal has been obtained. Intended to be
208 // used by govDAO implementations if they need to check Proposal data to know if
209 // the caller is allowed to get that kind of Proposal or not.
210 PostGetProposal(pid ProposalID, p *Proposal) error
211
212 // PreExecuteProposal is called when someone is trying to execute a proposal by ID.
213 // Is intended to be used to validate who can trigger the proposal execution.
214 PreExecuteProposal(pid ProposalID) (bool, error)
215
216 // Render will return a human-readable string in markdown format that
217 // will be used to show new data through the dao proxy entrypoint.
218 Render(pkgpath string, path string) string
219}
220
221type UpdateRequest struct {
222 DAO DAO
223 AllowedDAOs []string
224}