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