Search Apps Documentation Source Content File Folder Download Copy Actions Download

types.gno

5.39 Kb ยท 233 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 append([]string(nil), 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	if callback == nil {
141		panic("executor callback must not be nil")
142	}
143
144	return &SimpleExecutor{
145		callback: callback,
146		desc:     description,
147	}
148}
149
150// SimpleExecutor implements the Executor interface using
151// a callback function and a description string.
152type SimpleExecutor struct {
153	callback func(realm) error
154	desc     string
155}
156
157func (e *SimpleExecutor) Execute(cur realm) error {
158	// Check if executor was created using the constructor func
159	if e.callback == nil {
160		return nil
161	}
162
163	return e.callback(cross)
164}
165
166func (e *SimpleExecutor) String() string {
167	return e.desc
168}
169
170func NewSafeExecutor(e Executor) *SafeExecutor {
171	return &SafeExecutor{
172		e: e,
173	}
174}
175
176// SafeExecutor wraps an Executor to only allow its execution
177// by allowed govDAOs.
178type SafeExecutor struct {
179	e Executor
180}
181
182func (e *SafeExecutor) Execute(cur realm) error {
183	// Verify the caller is an adequate Realm
184	if !InAllowedDAOs(runtime.PreviousRealm().PkgPath()) {
185		return errors.New("execution only allowed by validated govDAOs")
186	}
187
188	return e.e.Execute(cross)
189}
190
191func (e *SafeExecutor) String() string {
192	return e.e.String()
193}
194
195type DAO interface {
196	// PreCreateProposal is called just before creating a new Proposal
197	// It is intended to be used to get the address of the proposal, that
198	// may vary depending on the DAO implementation, and to validate that
199	// the requester is allowed to do a proposal
200	PreCreateProposal(r ProposalRequest) (address, error)
201
202	// PostCreateProposal is called after creating the Proposal. It is
203	// intended to be used as a way to store a new proposal status, that
204	// depends on the actuall govDAO implementation
205	PostCreateProposal(r ProposalRequest, pid ProposalID)
206
207	// VoteOnProposal will send a petition to vote for a specific proposal
208	// to the actual govDAO implementation
209	VoteOnProposal(r VoteRequest) error
210
211	// PreGetProposal is called when someone is trying to get a proposal by ID.
212	// Is intended to be used to validate who can query proposals, just in case
213	// the actual govDAO implementation wants to limit the access.
214	PreGetProposal(pid ProposalID) error
215
216	// PostGetProposal is called after the proposal has been obtained. Intended to be
217	// used by govDAO implementations if they need to check Proposal data to know if
218	// the caller is allowed to get that kind of Proposal or not.
219	PostGetProposal(pid ProposalID, p *Proposal) error
220
221	// PreExecuteProposal is called when someone is trying to execute a proposal by ID.
222	// Is intended to be used to validate who can trigger the proposal execution.
223	PreExecuteProposal(pid ProposalID) (bool, error)
224
225	// Render will return a human-readable string in markdown format that
226	// will be used to show new data through the dao proxy entrypoint.
227	Render(pkgpath string, path string) string
228}
229
230type UpdateRequest struct {
231	DAO         DAO
232	AllowedDAOs []string
233}