daokit.gno
1.81 Kb ยท 85 lines
1package daokit
2
3import (
4 "time"
5
6 "gno.land/p/samcrew/daocond"
7)
8
9type DAO interface {
10 Propose(req ProposalRequest) uint64
11 Execute(id uint64)
12 Vote(id uint64, vote daocond.Vote)
13}
14
15func InstantExecute(d DAO, req ProposalRequest) uint64 {
16 id := d.Propose(req)
17 d.Vote(id, daocond.VoteYes)
18 d.Execute(id)
19 return id
20}
21
22type Core struct {
23 Resources *ResourcesStore
24 Proposals *ProposalsStore
25}
26
27func NewCore() *Core {
28 return &Core{
29 Resources: NewResourcesStore(),
30 Proposals: NewProposalsStore(),
31 }
32}
33
34func (d *Core) Vote(voterID string, proposalID uint64, vote daocond.Vote) {
35 proposal := d.Proposals.GetProposal(proposalID)
36 if proposal == nil {
37 panic("proposal not found")
38 }
39
40 if proposal.Status != ProposalStatusOpen {
41 panic("proposal is not open")
42 }
43
44 proposal.Ballot.Vote(voterID, daocond.Vote(vote))
45}
46
47func (d *Core) Execute(proposalID uint64) {
48 proposal := d.Proposals.GetProposal(proposalID)
49 if proposal == nil {
50 panic("proposal not found")
51 }
52
53 if proposal.Status != ProposalStatusOpen {
54 panic("proposal is not open")
55 }
56
57 if !proposal.Condition.Eval(proposal.Ballot) {
58 panic("proposal condition is not met")
59 }
60
61 proposal.UpdateStatus()
62 if proposal.Status != ProposalStatusPassed {
63 panic("proposal does not meet the condition(s) or is already closed/executed")
64 }
65
66 d.Resources.Get(proposal.Action.Type()).Handler.Execute(proposal.Action)
67 proposal.Status = ProposalStatusExecuted
68 proposal.ExecutedAt = time.Now()
69}
70
71func (d *Core) Propose(proposerID string, req ProposalRequest) uint64 {
72 actionType := req.Action.Type()
73
74 resource := d.Resources.Get(actionType)
75 if resource == nil {
76 panic("action type is not registered as a resource")
77 }
78
79 prop := d.Proposals.newProposal(proposerID, req, resource.Condition)
80 return uint64(prop.ID)
81}
82
83func (d *Core) ResourcesCount() int {
84 return d.Resources.Tree.Size()
85}