Search Apps Documentation Source Content File Folder Download Copy Actions Download

getter.gno

10.54 Kb ยท 343 lines
  1package v1
  2
  3import (
  4	"time"
  5
  6	"gno.land/p/nt/ufmt"
  7
  8	"gno.land/r/gnoswap/gov/governance"
  9)
 10
 11
 12// GetLatestConfigVersion returns the current config version.
 13func (gv *governanceV1) GetLatestConfigVersion() int64 {
 14	return gv.getCurrentConfigVersion()
 15}
 16
 17// GetCurrentProposalID returns the current proposal ID counter.
 18func (gv *governanceV1) GetCurrentProposalID() int64 {
 19	return gv.getCurrentProposalID()
 20}
 21
 22// GetMaxSmoothingPeriod returns the maximum smoothing period for delegation history cleanup.
 23func (gv *governanceV1) GetMaxSmoothingPeriod() int64 {
 24	return maxSmoothingPeriod
 25}
 26
 27
 28// GetLatestConfig returns the latest governance configuration.
 29func (gv *governanceV1) GetLatestConfig() governance.Config {
 30	currentVersion := gv.getCurrentConfigVersion()
 31	config, ok := gv.getConfig(currentVersion)
 32	if !ok {
 33		panic(errDataNotFound)
 34	}
 35
 36	return config
 37}
 38
 39// GetConfig returns a specific governance configuration by version.
 40func (gv *governanceV1) GetConfig(configVersion int64) (governance.Config, error) {
 41	config, ok := gv.getConfig(configVersion)
 42	if !ok {
 43		return governance.Config{}, ufmt.Errorf("config version %d not found", configVersion)
 44	}
 45
 46	return config, nil
 47}
 48
 49
 50// GetProposalCount returns the total number of proposals.
 51func (gv *governanceV1) GetProposalCount() int {
 52	return gv.store.GetProposals().Size()
 53}
 54
 55// GetProposalIDs returns a paginated list of proposal IDs.
 56func (gv *governanceV1) GetProposalIDs(offset, count int) []int64 {
 57	proposals := gv.store.GetProposals()
 58	size := proposals.Size()
 59
 60	if offset >= size {
 61		return []int64{}
 62	}
 63
 64	end := offset + count
 65	if end > size {
 66		end = size
 67	}
 68
 69	ids := make([]int64, 0, end-offset)
 70	proposals.IterateByOffset(offset, end-offset, func(key string, value any) bool {
 71		proposal := value.(*governance.Proposal)
 72		ids = append(ids, proposal.ID())
 73		return false
 74	})
 75
 76	return ids
 77}
 78
 79// ExistsProposal checks if a proposal exists.
 80func (gv *governanceV1) ExistsProposal(proposalID int64) bool {
 81	_, exists := gv.store.GetProposal(proposalID)
 82	return exists
 83}
 84
 85// GetProposal returns a proposal by ID.
 86func (gv *governanceV1) GetProposal(proposalID int64) (*governance.Proposal, error) {
 87	proposal, exists := gv.store.GetProposal(proposalID)
 88	if !exists {
 89		return nil, ufmt.Errorf("proposal %d not found", proposalID)
 90	}
 91	return proposal, nil
 92}
 93
 94// GetProposerByProposalId returns the proposer address of a proposal.
 95func (gv *governanceV1) GetProposerByProposalId(proposalId int64) (address, error) {
 96	proposal, exists := gv.store.GetProposal(proposalId)
 97	if !exists {
 98		return "", ufmt.Errorf("proposal %d not found", proposalId)
 99	}
100	return proposal.Proposer(), nil
101}
102
103// GetProposalTypeByProposalId returns the type of a proposal.
104func (gv *governanceV1) GetProposalTypeByProposalId(proposalId int64) (governance.ProposalType, error) {
105	proposal, exists := gv.store.GetProposal(proposalId)
106	if !exists {
107		return governance.ProposalType(0), ufmt.Errorf("proposal %d not found", proposalId)
108	}
109	return proposal.Type(), nil
110}
111
112// GetYeaByProposalId returns the yes vote weight of a proposal.
113func (gv *governanceV1) GetYeaByProposalId(proposalId int64) (int64, error) {
114	proposal, exists := gv.store.GetProposal(proposalId)
115	if !exists {
116		return 0, ufmt.Errorf("proposal %d not found", proposalId)
117	}
118	return proposal.Status().YesWeight(), nil
119}
120
121// GetNayByProposalId returns the no vote weight of a proposal.
122func (gv *governanceV1) GetNayByProposalId(proposalId int64) (int64, error) {
123	proposal, exists := gv.store.GetProposal(proposalId)
124	if !exists {
125		return 0, ufmt.Errorf("proposal %d not found", proposalId)
126	}
127	return proposal.Status().NoWeight(), nil
128}
129
130// GetConfigVersionByProposalId returns the config version used by a proposal.
131func (gv *governanceV1) GetConfigVersionByProposalId(proposalId int64) (int64, error) {
132	proposal, exists := gv.store.GetProposal(proposalId)
133	if !exists {
134		return 0, ufmt.Errorf("proposal %d not found", proposalId)
135	}
136	return proposal.ConfigVersion(), nil
137}
138
139// GetQuorumAmountByProposalId returns the quorum requirement for a proposal.
140func (gv *governanceV1) GetQuorumAmountByProposalId(proposalId int64) (int64, error) {
141	proposal, exists := gv.store.GetProposal(proposalId)
142	if !exists {
143		return 0, ufmt.Errorf("proposal %d not found", proposalId)
144	}
145	return proposal.Status().VoteStatus().QuorumAmount(), nil
146}
147
148// GetTitleByProposalId returns the title of a proposal.
149func (gv *governanceV1) GetTitleByProposalId(proposalId int64) (string, error) {
150	proposal, exists := gv.store.GetProposal(proposalId)
151	if !exists {
152		return "", ufmt.Errorf("proposal %d not found", proposalId)
153	}
154	return proposal.Metadata().Title(), nil
155}
156
157// GetDescriptionByProposalId returns the description of a proposal.
158func (gv *governanceV1) GetDescriptionByProposalId(proposalId int64) (string, error) {
159	proposal, exists := gv.store.GetProposal(proposalId)
160	if !exists {
161		return "", ufmt.Errorf("proposal %d not found", proposalId)
162	}
163	return proposal.Metadata().Description(), nil
164}
165
166// GetProposalStatusByProposalId returns the current status of a proposal.
167func (gv *governanceV1) GetProposalStatusByProposalId(proposalId int64) (string, error) {
168	proposal, exists := gv.store.GetProposal(proposalId)
169	if !exists {
170		return "", ufmt.Errorf("proposal %d not found", proposalId)
171	}
172	proposalResolver := NewProposalResolver(proposal)
173	return proposalResolver.Status(time.Now().Unix()), nil
174}
175
176
177// GetVoteStatus returns the vote status of a proposal.
178//
179// Returns:
180//   - quorum: minimum vote weight required for proposal to pass
181//   - maxVotingWeight: maximum possible voting weight
182//   - yesWeight: total weight of "yes" votes
183//   - noWeight: total weight of "no" votes
184func (gv *governanceV1) GetVoteStatus(proposalId int64) (quorum, maxVotingWeight, yesWeight, noWeight int64, err error) {
185	proposal, exists := gv.store.GetProposal(proposalId)
186	if !exists {
187		return 0, 0, 0, 0, ufmt.Errorf("proposal %d not found", proposalId)
188	}
189	voting := proposal.Status().VoteStatus()
190	return voting.QuorumAmount(), voting.MaxVotingWeight(), voting.YesWeight(), voting.NoWeight(), nil
191}
192
193// GetVotingInfoCount returns the number of voters for a proposal.
194func (gv *governanceV1) GetVotingInfoCount(proposalID int64) int {
195	votingInfos, exists := gv.getProposalUserVotingInfos(proposalID)
196	if !exists {
197		return 0
198	}
199	return votingInfos.Size()
200}
201
202// GetVotingInfoAddresses returns a paginated list of voter addresses for a proposal.
203func (gv *governanceV1) GetVotingInfoAddresses(proposalID int64, offset, count int) []address {
204	votingInfos, exists := gv.getProposalUserVotingInfos(proposalID)
205	if !exists {
206		return []address{}
207	}
208
209	size := votingInfos.Size()
210	if offset >= size {
211		return []address{}
212	}
213
214	end := offset + count
215	if end > size {
216		end = size
217	}
218
219	addrs := make([]address, 0, end-offset)
220	votingInfos.IterateByOffset(offset, end-offset, func(key string, value any) bool {
221		addrs = append(addrs, address(key))
222		return false
223	})
224
225	return addrs
226}
227
228// ExistsVotingInfo checks if a voting info exists for a user on a proposal.
229func (gv *governanceV1) ExistsVotingInfo(proposalID int64, addr address) bool {
230	_, exists := gv.getProposalUserVotingInfo(proposalID, addr)
231	return exists
232}
233
234// GetVotingInfo returns the voting info for a user on a proposal.
235func (gv *governanceV1) GetVotingInfo(proposalID int64, addr address) (*governance.VotingInfo, error) {
236	votingInfo, exists := gv.getProposalUserVotingInfo(proposalID, addr)
237	if !exists {
238		return nil, ufmt.Errorf("voting info not found for proposal %d and address %s", proposalID, addr.String())
239	}
240	return votingInfo, nil
241}
242
243// GetVoteWeight returns the voting weight of an address for a proposal.
244func (gv *governanceV1) GetVoteWeight(proposalID int64, addr address) (int64, error) {
245	votingInfo, exists := gv.getProposalUserVotingInfo(proposalID, addr)
246	if !exists {
247		return 0, ufmt.Errorf("voting info not found for proposal %d and address %s", proposalID, addr.String())
248	}
249	return votingInfo.VotedWeight(), nil
250}
251
252// GetVotedHeight returns the block height when an address voted on a proposal.
253func (gv *governanceV1) GetVotedHeight(proposalID int64, addr address) (int64, error) {
254	votingInfo, exists := gv.getProposalUserVotingInfo(proposalID, addr)
255	if !exists {
256		return 0, ufmt.Errorf("voting info not found for proposal %d and address %s", proposalID, addr.String())
257	}
258	return votingInfo.VotedHeight(), nil
259}
260
261// GetVotedAt returns the timestamp when an address voted on a proposal.
262func (gv *governanceV1) GetVotedAt(proposalID int64, addr address) (int64, error) {
263	votingInfo, exists := gv.getProposalUserVotingInfo(proposalID, addr)
264	if !exists {
265		return 0, ufmt.Errorf("voting info not found for proposal %d and address %s", proposalID, addr.String())
266	}
267	return votingInfo.VotedAt(), nil
268}
269
270
271// GetUserProposalCount returns the number of proposals created by a user.
272func (gv *governanceV1) GetUserProposalCount(user address) int {
273	proposalIDs, exists := gv.store.GetUserProposalIDs(user.String())
274	if !exists {
275		return 0
276	}
277	return len(proposalIDs)
278}
279
280// GetUserProposalIDs returns a paginated list of proposal IDs created by a user.
281func (gv *governanceV1) GetUserProposalIDs(user address, offset, count int) []int64 {
282	proposalIDs, exists := gv.store.GetUserProposalIDs(user.String())
283	if !exists {
284		return []int64{}
285	}
286
287	size := len(proposalIDs)
288	if offset >= size {
289		return []int64{}
290	}
291
292	end := offset + count
293	if end > size {
294		end = size
295	}
296
297	return proposalIDs[offset:end]
298}
299
300
301// GetOldestActiveProposalSnapshotTime returns the oldest snapshot time among active proposals.
302// This is used by gov/staker to prevent cleanup of delegation history that is still needed
303// by active proposals for voting weight calculation.
304func (gv *governanceV1) GetOldestActiveProposalSnapshotTime() (int64, bool) {
305	currentTime := time.Now().Unix()
306	currentProposalID := gv.getCurrentProposalID()
307
308	var (
309		oldestSnapshotTime int64
310		hasActiveProposal  bool
311	)
312
313	for id := int64(1); id <= currentProposalID; id++ {
314		proposal, exists := gv.getProposal(id)
315		if !exists {
316			continue
317		}
318
319		proposalResolver := NewProposalResolver(proposal)
320
321		if proposalResolver.IsActive(currentTime) {
322			snapshotTime := proposal.SnapshotTime()
323			if !hasActiveProposal || snapshotTime < oldestSnapshotTime {
324				oldestSnapshotTime = snapshotTime
325				hasActiveProposal = true
326			}
327		}
328	}
329
330	return oldestSnapshotTime, hasActiveProposal
331}
332
333
334// GetCurrentVotingWeightSnapshot returns the current voting weight snapshot.
335func (gv *governanceV1) GetCurrentVotingWeightSnapshot() (int64, int64, error) {
336	current := time.Now().Unix()
337	config, ok := gv.getCurrentConfig()
338	if !ok {
339		return 0, 0, ufmt.Errorf("current config not found")
340	}
341
342	return gv.getVotingWeightSnapshot(current, config.VotingWeightSmoothingDuration)
343}