Search Apps Documentation Source Content File Folder Download Copy Actions Download 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}