getter.gno
11.69 Kb · 342 lines
1package staker
2
3import (
4 "strconv"
5 "time"
6
7 gnsmath "gno.land/p/gnoswap/gnsmath"
8 "gno.land/p/gnoswap/uint256"
9 ufmt "gno.land/p/nt/ufmt/v0"
10
11 "gno.land/r/gnoswap/emission"
12 "gno.land/r/gnoswap/gov/staker"
13 "gno.land/r/gnoswap/gov/xgns"
14)
15
16// GetTotalxGnsSupply returns the total amount of xGNS supply.
17func (gs *govStakerV1) GetTotalxGnsSupply() int64 {
18 return xgns.TotalSupply()
19}
20
21// GetTotalDelegated returns the total amount of xGNS delegated.
22func (gs *govStakerV1) GetTotalDelegated() int64 {
23 return gs.store.GetTotalDelegatedAmount()
24}
25
26// GetTotalLockedAmount returns the total amount of locked GNS.
27func (gs *govStakerV1) GetTotalLockedAmount() int64 {
28 return gs.store.GetTotalLockedAmount()
29}
30
31// GetUnDelegationLockupPeriod returns the undelegation lockup period in seconds.
32func (gs *govStakerV1) GetUnDelegationLockupPeriod() int64 {
33 return gs.store.GetUnDelegationLockupPeriod()
34}
35
36// GetDelegationCount returns the total number of delegations.
37func (gs *govStakerV1) GetDelegationCount() int {
38 delegations := gs.store.GetAllDelegations()
39 return delegations.Size()
40}
41
42// GetDelegationIDs returns a paginated list of delegation IDs.
43func (gs *govStakerV1) GetDelegationIDs(offset, count int) []int64 {
44 delegations := gs.store.GetAllDelegations()
45
46 ids := make([]int64, 0)
47
48 delegations.IterateByOffset(offset, count, func(key string, _ any) bool {
49 delegationID, err := strconv.ParseInt(key, 10, 64)
50 if err != nil {
51 return false
52 }
53
54 ids = append(ids, delegationID)
55 return false
56 })
57
58 return ids
59}
60
61// ExistsDelegation checks if a delegation exists.
62func (gs *govStakerV1) ExistsDelegation(delegationID int64) bool {
63 return gs.store.HasDelegation(delegationID)
64}
65
66// GetDelegation returns the delegation for the given ID.
67func (gs *govStakerV1) GetDelegation(delegationID int64) (*staker.Delegation, error) {
68 delegation, exists := gs.store.GetDelegation(delegationID)
69 if !exists {
70 return nil, makeErrorWithDetails(errDataNotFound, ufmt.Sprintf("delegation not found: %d", delegationID))
71 }
72 return delegation, nil
73}
74
75// GetDelegatorDelegateeCount returns the number of delegatees for a specific delegator.
76func (gs *govStakerV1) GetDelegatorDelegateeCount(delegator address) int {
77 delegationManager := gs.store.GetDelegationManager()
78 delegatorTree, exists := delegationManager.GetDelegatorDelegations(delegator.String())
79 if !exists {
80 return 0
81 }
82
83 return delegatorTree.Size()
84}
85
86// GetDelegatorDelegateeAddresses returns a paginated list of delegatee addresses for a specific delegator.
87func (gs *govStakerV1) GetDelegatorDelegateeAddresses(delegator address, offset, count int) []address {
88 delegationManager := gs.store.GetDelegationManager()
89 delegatorTree, exists := delegationManager.GetDelegatorDelegations(delegator.String())
90 if !exists {
91 return []address{}
92 }
93
94 delegateeAddresses := make([]address, 0)
95
96 delegatorTree.IterateByOffset(offset, count, func(delegatee string, _ any) bool {
97 delegateeAddresses = append(delegateeAddresses, address(delegatee))
98 return false
99 })
100
101 return delegateeAddresses
102}
103
104// GetUserDelegationCount returns the number of delegations for a specific delegator-delegatee pair.
105func (gs *govStakerV1) GetUserDelegationCount(delegator address, delegatee address) int {
106 delegationManager := gs.store.GetDelegationManager()
107 delegationIDs, exists := delegationManager.GetDelegationIDs(delegator.String(), delegatee.String())
108 if !exists {
109 return 0
110 }
111 return len(delegationIDs)
112}
113
114// GetUserDelegationIDs returns a paginated list of delegation IDs for a specific delegator and delegatee.
115func (gs *govStakerV1) GetUserDelegationIDs(delegator address, delegatee address) []int64 {
116 delegationManager := gs.store.GetDelegationManager()
117
118 delegationIDs, exists := delegationManager.GetDelegationIDs(delegator.String(), delegatee.String())
119 if !exists {
120 return []int64{}
121 }
122
123 return delegationIDs
124}
125
126// HasDelegationSnapshotsKey returns true if delegation history exists.
127func (gs *govStakerV1) HasDelegationSnapshotsKey() bool {
128 return gs.store.HasTotalDelegationHistoryStoreKey()
129}
130
131// GetTotalDelegationAmountAtSnapshot returns the total delegation amount at a specific snapshot time.
132// Uses ReverseIterate to find the most recent entry at or before the snapshot time.
133//
134// Parameters:
135// - snapshotTime: timestamp to retrieve the snapshot for
136//
137// Returns:
138// - int64: total delegation amount at the specified time
139// - bool: true if snapshot was exists, false otherwise
140func (gs *govStakerV1) GetTotalDelegationAmountAtSnapshot(snapshotTime int64) (int64, bool) {
141 history := gs.store.GetTotalDelegationHistory()
142 if history.Size() == 0 {
143 return 0, false
144 }
145
146 var (
147 totalAmount int64
148 exists bool
149 )
150
151 // ReverseIterate from 0 to snapshotTime to find the most recent entry at or before snapshotTime
152 history.ReverseIterate(0, snapshotTime, func(key int64, value any) bool {
153 amountInt, ok := value.(int64)
154 if !ok {
155 panic(ufmt.Sprintf("invalid amount type: %T", value))
156 }
157
158 totalAmount = amountInt
159 exists = true
160
161 return true // stop after first (most recent) entry
162 })
163
164 return totalAmount, exists
165}
166
167// GetUserDelegationAmountAtSnapshot returns the delegation amount for a specific user at a specific snapshot time.
168// Structure: single BPTree keyed by composite key "addrStr|paddedTimestamp" -> int64
169// Uses ReverseIterate over the user's prefix range to find the most recent entry at or before the snapshot time.
170//
171// Parameters:
172// - userAddr: address of the user to get delegation amount for
173// - snapshotTime: timestamp to retrieve the snapshot for
174//
175// Returns:
176// - int64: user delegation amount at the specified time
177// - bool: true if snapshot was exists, false otherwise
178func (gs *govStakerV1) GetUserDelegationAmountAtSnapshot(userAddr address, snapshotTime int64) (int64, bool) {
179 history := gs.store.GetUserDelegationHistory()
180
181 addrStr := userAddr.String()
182 lo, _ := userHistoryKeyRange(addrStr)
183 // Inclusive upper bound: largest key for this address at or before snapshotTime.
184 hi := makeUserHistoryKey(addrStr, snapshotTime)
185
186 var (
187 userAmount int64
188 exists bool
189 )
190
191 // ReverseIterate from hi down to lo to find the most recent entry at or before snapshotTime
192 history.ReverseIterate(lo, hi, func(_ string, value any) bool {
193 amountInt, ok := value.(int64)
194 if !ok {
195 panic(ufmt.Sprintf("invalid amount type: %T", value))
196 }
197
198 userAmount = amountInt
199 exists = true
200
201 return true // stop after first (most recent) entry
202 })
203
204 return userAmount, exists
205}
206
207// GetClaimableRewardByAddress returns claimable reward for address.
208//
209// Returns:
210// - int64: emission reward amount
211// - map[string]int64: protocol fee rewards by token path
212func (gs *govStakerV1) GetClaimableRewardByAddress(addr address) (int64, map[string]int64, error) {
213 return gs.GetClaimableRewardByRewardID(addr.String())
214}
215
216// GetClaimableRewardByLaunchpad returns claimable reward for launchpad.
217//
218// Returns:
219// - int64: emission reward amount
220// - map[string]int64: protocol fee rewards by token path
221func (gs *govStakerV1) GetClaimableRewardByLaunchpad(addr address) (int64, map[string]int64, error) {
222 return gs.GetClaimableRewardByRewardID(gs.makeLaunchpadRewardID(addr.String()))
223}
224
225// GetClaimableRewardByRewardID returns claimable reward by ID.
226//
227// Returns:
228// - int64: emission reward amount
229// - map[string]int64: protocol fee rewards by token path
230func (gs *govStakerV1) GetClaimableRewardByRewardID(rewardID string) (int64, map[string]int64, error) {
231 emissionDistributedAmount := emission.GetAccuDistributedToGovStaker()
232 emissionRewardManager := gs.store.GetEmissionRewardManager()
233 emissionResolver := NewEmissionRewardManagerResolver(emissionRewardManager)
234 emissionReward, err := emissionResolver.GetClaimableRewardAmount(emissionDistributedAmount, rewardID, time.Now().Unix())
235 if err != nil {
236 return 0, make(map[string]int64), err
237 }
238
239 protocolFeeDistributedAmounts := gs.getDistributedProtocolFees()
240 protocolFeeRewardManager := gs.store.GetProtocolFeeRewardManager()
241 protocolFeeResolver := NewProtocolFeeRewardManagerResolver(protocolFeeRewardManager)
242 protocolFeeRewards, err := protocolFeeResolver.GetClaimableRewardAmounts(protocolFeeDistributedAmounts, rewardID, time.Now().Unix())
243 if err != nil {
244 return 0, make(map[string]int64), err
245 }
246
247 return emissionReward, protocolFeeRewards, nil
248}
249
250// GetLaunchpadProjectDeposit returns the deposit amount for a launchpad project.
251func (gs *govStakerV1) GetLaunchpadProjectDeposit(projectAddr string) (int64, bool) {
252 launchpadDeposits := gs.store.GetLaunchpadProjectDeposits()
253 return launchpadDeposits.GetDeposit(gs.makeLaunchpadRewardID(projectAddr))
254}
255
256// GetDelegationWithdrawCount returns the total number of delegation withdraws for a specific delegation.
257func (gs *govStakerV1) GetDelegationWithdrawCount(delegationID int64) int {
258 delegation, exists := gs.store.GetDelegation(delegationID)
259 if !exists {
260 return 0
261 }
262 return len(delegation.Withdraws())
263}
264
265// GetDelegationWithdraws returns a paginated list of delegation withdraws for a specific delegation.
266func (gs *govStakerV1) GetDelegationWithdraws(delegationID int64, offset, count int) ([]staker.DelegationWithdraw, error) {
267 delegation, exists := gs.store.GetDelegation(delegationID)
268 if !exists {
269 return []staker.DelegationWithdraw{}, nil
270 }
271
272 withdraws := delegation.Withdraws()
273 size := len(withdraws)
274 if offset >= size {
275 return []staker.DelegationWithdraw{}, nil
276 }
277
278 end := offset + count
279 if end > size {
280 end = size
281 }
282
283 return withdraws[offset:end], nil
284}
285
286// GetCollectableWithdrawAmount returns the collectable withdraw amount for a specific delegation.
287func (gs *govStakerV1) GetCollectableWithdrawAmount(delegationID int64) int64 {
288 delegation, exists := gs.store.GetDelegation(delegationID)
289 if !exists {
290 return 0
291 }
292
293 totalAmount := int64(0)
294 currentTime := time.Now().Unix()
295 for _, withdraw := range delegation.Withdraws() {
296 resolver := NewDelegationWithdrawResolver(&withdraw)
297 totalAmount = gnsmath.SafeAddInt64(totalAmount, resolver.CollectableAmount(currentTime))
298 }
299
300 return totalAmount
301}
302
303// GetProtocolFeeAccumulatedX128PerStake returns the accumulated protocol fee per stake (Q128) for a token path.
304func (gs *govStakerV1) GetProtocolFeeAccumulatedX128PerStake(tokenPath string) *uint256.Uint {
305 protocolFeeRewardManager := gs.store.GetProtocolFeeRewardManager()
306 accumulatedFee := protocolFeeRewardManager.GetAccumulatedProtocolFeeX128PerStake(tokenPath)
307 if accumulatedFee == nil {
308 return uint256.NewUint(0)
309 }
310
311 return accumulatedFee
312}
313
314// GetProtocolFeeAmount returns the protocol fee amounts for a token path.
315func (gs *govStakerV1) GetProtocolFeeAmount(tokenPath string) int64 {
316 protocolFeeRewardManager := gs.store.GetProtocolFeeRewardManager()
317 return protocolFeeRewardManager.GetProtocolFeeAmount(tokenPath)
318}
319
320// GetProtocolFeeAccumulatedTimestamp returns the accumulated timestamp for protocol fee rewards.
321func (gs *govStakerV1) GetProtocolFeeAccumulatedTimestamp() int64 {
322 protocolFeeRewardManager := gs.store.GetProtocolFeeRewardManager()
323 return protocolFeeRewardManager.GetAccumulatedTimestamp()
324}
325
326// GetEmissionAccumulatedX128PerStake returns the accumulated emission per stake (Q128).
327func (gs *govStakerV1) GetEmissionAccumulatedX128PerStake() *uint256.Uint {
328 emissionRewardManager := gs.store.GetEmissionRewardManager()
329 return emissionRewardManager.GetAccumulatedRewardX128PerStake()
330}
331
332// GetEmissionDistributedAmount returns the total distributed emission amount.
333func (gs *govStakerV1) GetEmissionDistributedAmount() int64 {
334 emissionRewardManager := gs.store.GetEmissionRewardManager()
335 return emissionRewardManager.GetDistributedAmount()
336}
337
338// GetEmissionAccumulatedTimestamp returns the accumulated timestamp for emission rewards.
339func (gs *govStakerV1) GetEmissionAccumulatedTimestamp() int64 {
340 emissionRewardManager := gs.store.GetEmissionRewardManager()
341 return emissionRewardManager.GetAccumulatedTimestamp()
342}