Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}