getter.gno
16.85 Kb · 483 lines
1package governance
2
3import (
4 "errors"
5 "time"
6
7 rotree "gno.land/p/nt/bptree/rotree/v0"
8 ufmt "gno.land/p/nt/ufmt/v0"
9
10 "gno.land/r/gnoswap/gov/governance"
11)
12
13// GetLatestConfigVersion returns the current governance configuration version.
14//
15// Returns:
16// - int64: latest configuration version stored by governance.
17func (gv *governanceV1) GetLatestConfigVersion() int64 {
18 return gv.getCurrentConfigVersion()
19}
20
21// GetCurrentProposalID returns the current proposal ID counter.
22//
23// Returns:
24// - int64: current proposal ID counter used for newly created proposals.
25func (gv *governanceV1) GetCurrentProposalID() int64 {
26 return gv.getCurrentProposalID()
27}
28
29// GetMaxSmoothingPeriod returns the maximum smoothing period for delegation history cleanup.
30//
31// Returns:
32// - int64: maximum permitted smoothing period, in seconds.
33func (gv *governanceV1) GetMaxSmoothingPeriod() int64 {
34 return maxSmoothingPeriod
35}
36
37// GetLatestConfig returns the latest governance configuration.
38//
39// Returns:
40// - governance.Config: latest stored configuration for the current version.
41// - error: nil on success; an error when the current configuration is missing.
42func (gv *governanceV1) GetLatestConfig() (governance.Config, error) {
43 currentVersion := gv.getCurrentConfigVersion()
44 config, ok := gv.getConfig(currentVersion)
45 if !ok {
46 return governance.NewConfig(0, 0, 0, 0, 0, 0, 0), errors.New(errDataNotFound)
47 }
48
49 return config, nil
50}
51
52// GetConfig returns a specific governance configuration by version.
53//
54// Parameters:
55// - configVersion: configuration version to retrieve.
56//
57// Returns:
58// - governance.Config: configuration stored under configVersion.
59// - error: nil on success; an error when configVersion is not found.
60func (gv *governanceV1) GetConfig(configVersion int64) (governance.Config, error) {
61 config, ok := gv.getConfig(configVersion)
62 if !ok {
63 // Construct the zero Config via the domain constructor so it is
64 // allocated inside the governance domain realm (realm allocation check).
65 return governance.NewConfig(0, 0, 0, 0, 0, 0, 0), ufmt.Errorf("config version %d not found", configVersion)
66 }
67
68 return config, nil
69}
70
71// GetProposals returns a read-only view of every proposal, keyed by the decimal
72// string form of the proposal ID.
73//
74// Returns:
75// - *rotree.ReadOnlyTree: read-only proposal tree with decimal proposal IDs as keys.
76func (gv *governanceV1) GetProposals() *rotree.ReadOnlyTree {
77 return rotree.Wrap(gv.store.GetProposals(), cloneProposalEntry)
78}
79
80// ExistsProposal checks if a proposal exists.
81//
82// Parameters:
83// - proposalID: proposal identifier to look up.
84//
85// Returns:
86// - bool: true when proposalID is stored, otherwise false.
87func (gv *governanceV1) ExistsProposal(proposalID int64) bool {
88 _, exists := gv.store.GetProposal(proposalID)
89 return exists
90}
91
92// GetProposerByProposalId returns the proposer address of a proposal.
93//
94// Parameters:
95// - proposalId: proposal identifier to look up.
96//
97// Returns:
98// - address: address that submitted the proposal.
99// - error: nil on success; an error when the proposal does not exist.
100func (gv *governanceV1) GetProposerByProposalId(proposalId int64) (address, error) {
101 proposal, exists := gv.store.GetProposal(proposalId)
102 if !exists {
103 return "", ufmt.Errorf("proposal %d not found", proposalId)
104 }
105 return proposal.Proposer(), nil
106}
107
108// GetProposalTypeByProposalId returns the type of a proposal.
109//
110// Parameters:
111// - proposalId: proposal identifier to look up.
112//
113// Returns:
114// - governance.ProposalType: type recorded for the proposal.
115// - error: nil on success; an error when the proposal does not exist.
116func (gv *governanceV1) GetProposalTypeByProposalId(proposalId int64) (governance.ProposalType, error) {
117 proposal, exists := gv.store.GetProposal(proposalId)
118 if !exists {
119 return governance.ProposalType(0), ufmt.Errorf("proposal %d not found", proposalId)
120 }
121 return proposal.Type(), nil
122}
123
124// GetProposalCreatedAt returns the creation timestamp of a proposal.
125//
126// Parameters:
127// - proposalId: proposal identifier to look up.
128//
129// Returns:
130// - int64: Unix timestamp at which the proposal was created.
131// - error: nil on success; an error when the proposal does not exist.
132func (gv *governanceV1) GetProposalCreatedAt(proposalId int64) (int64, error) {
133 proposal, exists := gv.store.GetProposal(proposalId)
134 if !exists {
135 return 0, ufmt.Errorf("proposal %d not found", proposalId)
136 }
137 return proposal.CreatedAt(), nil
138}
139
140// GetProposalCreatedHeight returns the creation block height of a proposal.
141//
142// Parameters:
143// - proposalId: proposal identifier to look up.
144//
145// Returns:
146// - int64: block height at which the proposal was created.
147// - error: nil on success; an error when the proposal does not exist.
148func (gv *governanceV1) GetProposalCreatedHeight(proposalId int64) (int64, error) {
149 proposal, exists := gv.store.GetProposal(proposalId)
150 if !exists {
151 return 0, ufmt.Errorf("proposal %d not found", proposalId)
152 }
153 return proposal.CreatedHeight(), nil
154}
155
156// GetProposalCommunityPoolSpendInfo returns the community pool spend info for a proposal.
157//
158// Parameters:
159// - proposalID: proposal identifier to inspect.
160//
161// Returns:
162// - *governance.CommunityPoolSpendInfo: spend details stored in the proposal.
163// - error: nil on success; an error when the proposal is missing or is not a
164// community pool spend proposal.
165func (gv *governanceV1) GetProposalCommunityPoolSpendInfo(proposalID int64) (*governance.CommunityPoolSpendInfo, error) {
166 proposal, exists := gv.store.GetProposal(proposalID)
167 if !exists {
168 return nil, ufmt.Errorf("proposal %d not found", proposalID)
169 }
170
171 proposalData := proposal.Data()
172 if proposalData == nil || proposalData.CommunityPoolSpend() == nil {
173 return nil, ufmt.Errorf("proposal is not a community pool spend proposal")
174 }
175
176 return proposalData.CommunityPoolSpend(), nil
177}
178
179// GetProposalExecutionInfo returns the execution info for a proposal.
180//
181// Parameters:
182// - proposalID: proposal identifier to inspect.
183//
184// Returns:
185// - *governance.ExecutionInfo: execution messages and count stored in the proposal.
186// - error: nil on success; an error when the proposal is missing or is not a
187// parameter change proposal.
188func (gv *governanceV1) GetProposalExecutionInfo(proposalID int64) (*governance.ExecutionInfo, error) {
189 proposal, exists := gv.store.GetProposal(proposalID)
190 if !exists {
191 return nil, ufmt.Errorf("proposal %d not found", proposalID)
192 }
193
194 proposalData := proposal.Data()
195 if proposalData == nil || proposalData.Execution() == nil {
196 return nil, ufmt.Errorf("proposal is not a parameter change proposal")
197 }
198
199 return proposalData.Execution(), nil
200}
201
202// GetYeaByProposalId returns the yes vote weight of a proposal.
203//
204// Parameters:
205// - proposalId: proposal identifier to inspect.
206//
207// Returns:
208// - int64: total voting weight recorded for yes votes.
209// - error: nil on success; an error when the proposal does not exist.
210func (gv *governanceV1) GetYeaByProposalId(proposalId int64) (int64, error) {
211 proposal, exists := gv.store.GetProposal(proposalId)
212 if !exists {
213 return 0, ufmt.Errorf("proposal %d not found", proposalId)
214 }
215 return proposal.Status().YesWeight(), nil
216}
217
218// GetNayByProposalId returns the no vote weight of a proposal.
219//
220// Parameters:
221// - proposalId: proposal identifier to inspect.
222//
223// Returns:
224// - int64: total voting weight recorded for no votes.
225// - error: nil on success; an error when the proposal does not exist.
226func (gv *governanceV1) GetNayByProposalId(proposalId int64) (int64, error) {
227 proposal, exists := gv.store.GetProposal(proposalId)
228 if !exists {
229 return 0, ufmt.Errorf("proposal %d not found", proposalId)
230 }
231 return proposal.Status().NoWeight(), nil
232}
233
234// GetConfigVersionByProposalId returns the config version used by a proposal.
235//
236// Parameters:
237// - proposalId: proposal identifier to inspect.
238//
239// Returns:
240// - int64: governance configuration version captured by the proposal.
241// - error: nil on success; an error when the proposal does not exist.
242func (gv *governanceV1) GetConfigVersionByProposalId(proposalId int64) (int64, error) {
243 proposal, exists := gv.store.GetProposal(proposalId)
244 if !exists {
245 return 0, ufmt.Errorf("proposal %d not found", proposalId)
246 }
247 return proposal.ConfigVersion(), nil
248}
249
250// GetQuorumAmountByProposalId returns the quorum requirement for a proposal.
251//
252// Parameters:
253// - proposalId: proposal identifier to inspect.
254//
255// Returns:
256// - int64: minimum voting weight required for the proposal's quorum.
257// - error: nil on success; an error when the proposal does not exist.
258func (gv *governanceV1) GetQuorumAmountByProposalId(proposalId int64) (int64, error) {
259 proposal, exists := gv.store.GetProposal(proposalId)
260 if !exists {
261 return 0, ufmt.Errorf("proposal %d not found", proposalId)
262 }
263 return proposal.Status().VoteStatus().QuorumAmount(), nil
264}
265
266// GetTitleByProposalId returns the title of a proposal.
267//
268// Parameters:
269// - proposalId: proposal identifier to inspect.
270//
271// Returns:
272// - string: proposal title.
273// - error: nil on success; an error when the proposal does not exist.
274func (gv *governanceV1) GetTitleByProposalId(proposalId int64) (string, error) {
275 proposal, exists := gv.store.GetProposal(proposalId)
276 if !exists {
277 return "", ufmt.Errorf("proposal %d not found", proposalId)
278 }
279 return proposal.Metadata().Title(), nil
280}
281
282// GetDescriptionByProposalId returns the description of a proposal.
283//
284// Parameters:
285// - proposalId: proposal identifier to inspect.
286//
287// Returns:
288// - string: proposal description.
289// - error: nil on success; an error when the proposal does not exist.
290func (gv *governanceV1) GetDescriptionByProposalId(proposalId int64) (string, error) {
291 proposal, exists := gv.store.GetProposal(proposalId)
292 if !exists {
293 return "", ufmt.Errorf("proposal %d not found", proposalId)
294 }
295 return proposal.Metadata().Description(), nil
296}
297
298// GetProposalStatusByProposalId returns the current status of a proposal.
299//
300// Parameters:
301// - proposalId: proposal identifier to inspect.
302//
303// Returns:
304// - string: status computed from the proposal and the current Unix time.
305// - error: nil on success; an error when the proposal does not exist.
306func (gv *governanceV1) GetProposalStatusByProposalId(proposalId int64) (string, error) {
307 proposal, exists := gv.store.GetProposal(proposalId)
308 if !exists {
309 return "", ufmt.Errorf("proposal %d not found", proposalId)
310 }
311 proposalResolver := NewProposalResolver(proposal)
312 return proposalResolver.Status(time.Now().Unix()), nil
313}
314
315// GetVoteStatus returns the vote status of a proposal.
316//
317// Parameters:
318// - proposalId: proposal identifier to inspect.
319//
320// Returns:
321// - quorum: minimum vote weight required for proposal to pass.
322// - maxVotingWeight: maximum possible voting weight recorded for the proposal.
323// - yesWeight: total weight of "yes" votes.
324// - noWeight: total weight of "no" votes.
325// - err: nil on success; an error when the proposal does not exist.
326func (gv *governanceV1) GetVoteStatus(proposalId int64) (quorum, maxVotingWeight, yesWeight, noWeight int64, err error) {
327 proposal, exists := gv.store.GetProposal(proposalId)
328 if !exists {
329 return 0, 0, 0, 0, ufmt.Errorf("proposal %d not found", proposalId)
330 }
331 voting := proposal.Status().VoteStatus()
332 return voting.QuorumAmount(), voting.MaxVotingWeight(), voting.YesWeight(), voting.NoWeight(), nil
333}
334
335// GetVotingInfos returns a read-only view of a proposal's value-backed voting
336// infos, keyed by voter address. Existing proposals have an empty view before
337// the first vote; nil is returned only when the stored voting-info tree is absent.
338//
339// Parameters:
340// - proposalID: proposal identifier whose voting information is requested.
341//
342// Returns:
343// - *rotree.ReadOnlyTree: read-only voting-info tree keyed by voter address, or
344// nil when no tree is stored for proposalID.
345func (gv *governanceV1) GetVotingInfos(proposalID int64) *rotree.ReadOnlyTree {
346 votingInfos, exists := gv.getProposalUserVotingInfos(proposalID)
347 if !exists {
348 return nil
349 }
350 return rotree.Wrap(votingInfos, nil)
351}
352
353// ExistsVotingInfo checks if a voting info exists for a user on a proposal.
354//
355// Parameters:
356// - proposalID: proposal identifier to inspect.
357// - addr: voter address to look up within proposalID.
358//
359// Returns:
360// - bool: true when voting information exists for the proposal and address.
361func (gv *governanceV1) ExistsVotingInfo(proposalID int64, addr address) bool {
362 _, exists := gv.getProposalUserVotingInfo(proposalID, addr)
363 return exists
364}
365
366// GetVoteWeight returns the voting weight of an address for a proposal.
367//
368// Parameters:
369// - proposalID: proposal identifier to inspect.
370// - addr: voter address whose recorded vote weight is requested.
371//
372// Returns:
373// - int64: weight recorded for addr's vote.
374// - error: nil on success; an error when no voting information exists for the
375// proposal and address.
376func (gv *governanceV1) GetVoteWeight(proposalID int64, addr address) (int64, error) {
377 votingInfo, exists := gv.getProposalUserVotingInfo(proposalID, addr)
378 if !exists {
379 return 0, ufmt.Errorf("voting info not found for proposal %d and address %s", proposalID, addr.String())
380 }
381 return votingInfo.VotedWeight(), nil
382}
383
384// GetVotedHeight returns the block height when an address voted on a proposal.
385//
386// Parameters:
387// - proposalID: proposal identifier to inspect.
388// - addr: voter address whose vote height is requested.
389//
390// Returns:
391// - int64: block height recorded for addr's vote.
392// - error: nil on success; an error when no voting information exists for the
393// proposal and address.
394func (gv *governanceV1) GetVotedHeight(proposalID int64, addr address) (int64, error) {
395 votingInfo, exists := gv.getProposalUserVotingInfo(proposalID, addr)
396 if !exists {
397 return 0, ufmt.Errorf("voting info not found for proposal %d and address %s", proposalID, addr.String())
398 }
399 return votingInfo.VotedHeight(), nil
400}
401
402// GetVotedAt returns the timestamp when an address voted on a proposal.
403//
404// Parameters:
405// - proposalID: proposal identifier to inspect.
406// - addr: voter address whose vote timestamp is requested.
407//
408// Returns:
409// - int64: Unix timestamp recorded for addr's vote.
410// - error: nil on success; an error when no voting information exists for the
411// proposal and address.
412func (gv *governanceV1) GetVotedAt(proposalID int64, addr address) (int64, error) {
413 votingInfo, exists := gv.getProposalUserVotingInfo(proposalID, addr)
414 if !exists {
415 return 0, ufmt.Errorf("voting info not found for proposal %d and address %s", proposalID, addr.String())
416 }
417 return votingInfo.VotedAt(), nil
418}
419
420// GetUserProposals returns a read-only view of the proposals created per user,
421// keyed by creator address with the creator's proposal IDs as the value.
422//
423// Returns:
424// - *rotree.ReadOnlyTree: read-only user-proposal tree keyed by creator address.
425func (gv *governanceV1) GetUserProposals() *rotree.ReadOnlyTree {
426 return rotree.Wrap(gv.store.GetUserProposals(), cloneProposalIDsEntry)
427}
428
429// GetOldestActiveProposalSnapshotTime examines only the first timestamp-ordered index entry.
430// If it is inactive, the error identifies the proposal requiring maintenance
431// cleanup. An error must never be treated as an empty index when deleting
432// delegation history.
433//
434// Returns:
435// - int64: snapshot timestamp of the oldest active proposal, or zero when the
436// index is empty or an error occurs.
437// - bool: true when an active proposal was found at the oldest index entry.
438// - error: nil for an empty index or active entry; an error when the entry's
439// proposal is missing or inactive and the index needs cleanup.
440func (gv *governanceV1) GetOldestActiveProposalSnapshotTime() (int64, bool, error) {
441 index := gv.store.GetActiveProposalsBySnapshot()
442 if index.Size() == 0 {
443 return 0, false, nil
444 }
445
446 _, value := index.GetByIndex(0)
447 proposalID, ok := value.(int64)
448 if !ok {
449 panic(ufmt.Sprintf("failed to cast active proposal ID to int64: %T", value))
450 }
451
452 proposal, exists := gv.getProposal(proposalID)
453 if !exists {
454 return 0, false, makeErrorWithDetails(
455 errProposalNotFound, ufmt.Sprintf("proposalID: %d", proposalID),
456 )
457 }
458 if !NewProposalResolver(proposal).IsActive(time.Now().Unix()) {
459 return 0, false, makeErrorWithDetails(
460 errProposalIndexNeedsCleanup, ufmt.Sprintf("proposalID: %d", proposalID),
461 )
462 }
463
464 return proposal.SnapshotTime(), true, nil
465}
466
467// GetCurrentVotingWeightSnapshot returns the current total voting weight and
468// timestamp anchor computed with the configured smoothing duration.
469//
470// Returns:
471// - int64: total voting weight averaged over the configured smoothing window.
472// - int64: Unix timestamp used as the snapshot history anchor.
473// - error: nil on success; an error when the current configuration or snapshot
474// data cannot be retrieved.
475func (gv *governanceV1) GetCurrentVotingWeightSnapshot() (int64, int64, error) {
476 current := time.Now().Unix()
477 config, ok := gv.getCurrentConfig()
478 if !ok {
479 return 0, 0, ufmt.Errorf("current config not found")
480 }
481
482 return gv.getVotingWeightSnapshot(current, config.VotingWeightSmoothingDuration)
483}