Kind Realm (renderable)
Name v1
Namespace gnoswap / gov / governance
Exported functions n/a — Gnoland RPC unavailable (functions): rpc abci_query: HTTP 500
Module gno.land/r/gnoswap/gov/governance/v1
gno 0.9 proposal.gno gno
⧉
1 package governance 2 3 import ( 4 "errors" 5 6 "gno.land/r/gnoswap/gov/governance" 7 ) 8 Gnoland RPC unavailable (functions): rpc abci_query: HTTP 500
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
Render unavailable
rate limit exceeded — the render query is served by the Gnoland archive RPC.
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.
9 type ProposalResolver struct {
10 *governance.Proposal
11 statusResolver *ProposalStatusResolver
12 dataResolver *ProposalDataResolver
13 metadataResolver *ProposalMetadataResolver
14 }
15
16 // NewProposalResolver wraps a persisted governance proposal and initializes
17 // resolvers for its status, type-specific data, and metadata.
18 //
19 // Parameters:
20 // - proposal: persisted proposal to resolve
21 //
22 // Returns:
23 // - *ProposalResolver: resolver backed by proposal and its nested state
24 func NewProposalResolver(proposal *governance.Proposal) *ProposalResolver {
25 statusResolver := NewProposalStatusResolver(proposal.Status())
26 dataResolver := NewProposalDataResolver(proposal.Data())
27 metadataResolver := NewProposalMetadataResolver(proposal.Metadata())
28 return &ProposalResolver{
29 Proposal: proposal,
30 statusResolver: statusResolver,
31 dataResolver: dataResolver,
32 metadataResolver: metadataResolver,
33 }
34 }
35
36 // VotingTotalWeight returns the total weight of all votes cast by combining
37 // the proposal's yes and no tallies.
38 //
39 // Returns:
40 // - int64: combined weight of all recorded votes
41 func (r *ProposalResolver) VotingTotalWeight() int64 {
42 return r.statusResolver.TotalVoteWeight()
43 }
44
45 // IsActive determines whether the proposal is active at current.
46 // Upcoming, voting, and passed executable proposals are active; rejected,
47 // expired, executed, canceled, and passed text proposals are inactive.
48 //
49 // Parameters:
50 // - current: timestamp at which the proposal status is evaluated
51 //
52 // Returns:
53 // - bool: true when the proposal can still be voted on or executed at current
54 func (r *ProposalResolver) IsActive(current int64 ) bool {
55 // Calculate status once and reuse to avoid redundant computations
56 status := r.statusResolver.StatusType(current)
57
58 switch status {
59 case governance.StatusRejected,
60 governance.StatusExpired,
61 governance.StatusExecuted,
62 governance.StatusCanceled:
63 return false
64 case governance.StatusPassed:
65 // Text proposals become inactive once they pass (no execution needed)
66 return !r.IsTextType()
67 default :
68 // StatusUpcoming, StatusActive, StatusExecutable are considered active
69 return true
70 }
71 }
72
73 // Validate performs comprehensive validation of the proposal's type-specific
74 // data and metadata before the proposal is stored.
75 //
76 // Returns:
77 // - error: nil when both data and metadata validate; the first validation error otherwise
78 func (r *ProposalResolver) Validate() error {
79 // Validate type-specific proposal data
80 if err := r.dataResolver.Validate(); err != nil {
81 return err
82 }
83
84 // Validate proposal metadata (title and description)
85 if err := r.metadataResolver.Validate(); err != nil {
86 return err
87 }
88
89 return nil
90 }
91
92 // Status returns the current status string of the proposal at current.
93 //
94 // Parameters:
95 // - current: timestamp at which the proposal status is evaluated
96 //
97 // Returns:
98 // - string: human-readable status name for the proposal at current
99 func (r *ProposalResolver) Status(current int64 ) string {
100 return r.statusResolver.StatusType(current).String()
101 }
102
103 // StatusType returns the current status type of the proposal at current.
104 //
105 // Parameters:
106 // - current: timestamp at which the proposal status is evaluated
107 //
108 // Returns:
109 // - governance.ProposalStatusType: lifecycle status at current
110 func (r *ProposalResolver) StatusType(current int64 ) governance.ProposalStatusType {
111 return r.statusResolver.StatusType(current)
112 }
113
114 // IsVotingPeriod reports whether votedAt falls within the proposal's active
115 // voting status.
116 //
117 // Parameters:
118 // - votedAt: timestamp at which voting eligibility is checked
119 //
120 // Returns:
121 // - bool: true when the proposal status at votedAt is StatusActive
122 func (r *ProposalResolver) IsVotingPeriod(votedAt int64 ) bool {
123 return r.StatusType(votedAt) == governance.StatusActive
124 }
125
126 // IsExecutable determines whether the proposal can be executed at current.
127 // The proposal type must support execution and its status must be executable.
128 //
129 // Parameters:
130 // - current: timestamp at which execution eligibility is evaluated
131 //
132 // Returns:
133 // - bool: true when this type and current lifecycle state permit execution
134 func (r *ProposalResolver) IsExecutable(current int64 ) bool {
135 // Only certain proposal types can be executed
136 if !r.dataResolver.ProposalType().IsExecutable() {
137 return false
138 }
139
140 return r.statusResolver.IsExecutable(current)
141 }
142
143 // CommunityPoolSpendTokenPath returns the token path for a community pool spend proposal.
144 // It returns an empty string when the proposal has no community-pool spend data.
145 //
146 // Returns:
147 // - string: token package path to spend, or empty string for other proposal types
148 func (r *ProposalResolver) CommunityPoolSpendTokenPath() string {
149 if r.Data() == nil {
150 return ""
151 }
152
153 communityPoolSpend := r.dataResolver.CommunityPoolSpend()
154 if communityPoolSpend == nil {
155 return ""
156 }
157
158 return communityPoolSpend.TokenPath()
159 }
160
161 // Vote records a vote for this proposal and updates its yes or no tally.
162 // This is an internal method called during the voting process.
163 //
164 // Parameters:
165 // - votedYes: true to add weight to the yes tally; false to add it to no
166 // - weight: voting weight to add to the selected tally
167 //
168 // Returns:
169 // - error: nil when the selected tally is updated; an error from vote-status validation otherwise
170 func (r *ProposalResolver) Vote(votedYes bool , weight int64 ) error {
171 return r.statusResolver.vote(votedYes, weight)
172 }
173
174 // execute marks the proposal as executed and records execution details.
175 // This method validates execution conditions before proceeding.
176 func (r *ProposalResolver) execute(
177 executedAt, executedHeight int64 ,
178 executedBy address,
179 ) error {
180 // Verify proposal is in executable state
181 if !r.IsExecutable(executedAt) {
182 return errors.New(errProposalNotExecutable)
183 }
184
185 // Mark proposal as executed
186 return r.statusResolver.execute(executedAt, executedHeight, executedBy)
187 }
188
189 // cancel marks the proposal as canceled and records cancellation details.
190 // This method validates cancellation conditions before proceeding.
191 func (r *ProposalResolver) cancel(
192 canceledAt, canceledHeight int64 ,
193 canceledBy address,
194 ) error {
195 if r.statusResolver.IsCanceled(canceledAt) {
196 return errors.New(errAlreadyCanceledProposal)
197 }
198
199 if !r.statusResolver.IsUpcoming(canceledAt) {
200 return errors.New(errUnableToCancelVotingProposal)
201 }
202
203 // Mark proposal as canceled
204 return r.statusResolver.cancel(canceledAt, canceledHeight, canceledBy)
205 }
206