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}