Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}