getter.gno
13.60 Kb · 406 lines
1package staker
2
3import (
4 "time"
5
6 gnsmath "gno.land/p/gnoswap/gnsmath/v1"
7 "gno.land/p/gnoswap/uint256/v1"
8 rotree "gno.land/p/nt/bptree/rotree/v0"
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, including
17// xGNS held by the launchpad.
18//
19// Returns:
20// - int64: total xGNS supply, including the launchpad balance.
21func (gs *govStakerV1) GetTotalxGnsSupply() int64 {
22 return xgns.TotalSupply()
23}
24
25// GetTotalDelegated returns the total amount of xGNS delegated.
26//
27// Returns:
28// - int64: total xGNS amount currently delegated.
29func (gs *govStakerV1) GetTotalDelegated() int64 {
30 return gs.store.GetTotalDelegatedAmount()
31}
32
33// GetTotalLockedAmount returns the total amount of locked GNS.
34//
35// Returns:
36// - int64: total GNS amount currently locked.
37func (gs *govStakerV1) GetTotalLockedAmount() int64 {
38 return gs.store.GetTotalLockedAmount()
39}
40
41// GetUnDelegationLockupPeriod returns the undelegation lockup period in seconds.
42//
43// Returns:
44// - int64: number of seconds an undelegation remains locked.
45func (gs *govStakerV1) GetUnDelegationLockupPeriod() int64 {
46 return gs.store.GetUnDelegationLockupPeriod()
47}
48
49// GetDelegations returns a read-only view of every delegation, keyed by the
50// decimal string form of the delegation ID.
51//
52// Returns:
53// - *rotree.ReadOnlyTree: read-only delegation tree keyed by decimal ID.
54func (gs *govStakerV1) GetDelegations() *rotree.ReadOnlyTree {
55 return rotree.Wrap(gs.store.GetAllDelegations(), cloneDelegationEntry)
56}
57
58// ExistsDelegation checks if a delegation exists.
59//
60// Parameters:
61// - delegationID: delegation identifier to look up.
62//
63// Returns:
64// - bool: true when delegationID is stored, otherwise false.
65func (gs *govStakerV1) ExistsDelegation(delegationID int64) bool {
66 return gs.store.HasDelegation(delegationID)
67}
68
69// GetDelegatorDelegations returns a read-only view of a delegator's delegations,
70// keyed by delegatee address with that pair's delegation IDs as the value.
71// nil is returned when the delegator has no delegations.
72//
73// Parameters:
74// - delegator: address whose outgoing delegations are requested.
75//
76// Returns:
77// - *rotree.ReadOnlyTree: read-only tree keyed by delegatee address, or nil
78// when delegator has no delegation entries.
79func (gs *govStakerV1) GetDelegatorDelegations(delegator address) *rotree.ReadOnlyTree {
80 delegationManager := gs.store.GetDelegationManager()
81 delegatorTree, exists := delegationManager.GetDelegatorDelegations(delegator.String())
82 if !exists {
83 return nil
84 }
85 return rotree.Wrap(delegatorTree, cloneDelegationIDsEntry)
86}
87
88// GetUserDelegationIDs returns the delegation IDs for a specific delegator and
89// delegatee.
90//
91// Parameters:
92// - delegator: address that created the delegations.
93// - delegatee: address receiving the delegations.
94//
95// Returns:
96// - []int64: delegation IDs for the delegator/delegatee pair, or an empty
97// slice when no pair is stored.
98func (gs *govStakerV1) GetUserDelegationIDs(delegator address, delegatee address) []int64 {
99 delegationManager := gs.store.GetDelegationManager()
100
101 delegationIDs, exists := delegationManager.GetDelegationIDs(delegator.String(), delegatee.String())
102 if !exists {
103 return []int64{}
104 }
105
106 return delegationIDs
107}
108
109// HasDelegationSnapshotsKey reports whether delegation history has been stored.
110//
111// Returns:
112// - bool: true when the total delegation history storage key exists.
113func (gs *govStakerV1) HasDelegationSnapshotsKey() bool {
114 return gs.store.HasTotalDelegationHistoryStoreKey()
115}
116
117// GetTotalDelegationAmountAtSnapshot returns the total delegation amount at a
118// Unix timestamp. It uses ReverseIterate to find the most recent history entry
119// at or before that timestamp; this is a timestamp lookup, not a block snapshot.
120//
121// Parameters:
122// - snapshotTime: Unix timestamp to retrieve the history value for
123//
124// Returns:
125// - int64: total delegation amount at the specified time
126// - bool: true when a history entry exists at or before the timestamp
127func (gs *govStakerV1) GetTotalDelegationAmountAtSnapshot(snapshotTime int64) (int64, bool) {
128 history := gs.store.GetTotalDelegationHistory()
129 if history.Size() == 0 {
130 return 0, false
131 }
132
133 var (
134 totalAmount int64
135 exists bool
136 )
137
138 // ReverseIterate from 0 to snapshotTime to find the most recent entry at or before snapshotTime
139 history.ReverseIterate(0, snapshotTime, func(key int64, value any) bool {
140 amountInt, ok := value.(int64)
141 if !ok {
142 panic(ufmt.Sprintf("invalid amount type: %T", value))
143 }
144
145 totalAmount = amountInt
146 exists = true
147
148 return true // stop after first (most recent) entry
149 })
150
151 return totalAmount, exists
152}
153
154// GetUserDelegationAmountAtSnapshot returns one user's delegation amount at a
155// Unix timestamp. The history is keyed by address and timestamp, and the
156// lookup returns the most recent entry at or before the requested time.
157//
158// Parameters:
159// - userAddr: address of the user
160// - snapshotTime: Unix timestamp to retrieve
161//
162// Returns:
163// - int64: user delegation amount at the specified time
164// - bool: true when a history entry exists at or before the timestamp
165func (gs *govStakerV1) GetUserDelegationAmountAtSnapshot(userAddr address, snapshotTime int64) (int64, bool) {
166 history := gs.store.GetUserDelegationHistory()
167
168 addrStr := userAddr.String()
169 lo, _ := userHistoryKeyRange(addrStr)
170 // Inclusive upper bound: largest key for this address at or before snapshotTime.
171 hi := makeUserHistoryKey(addrStr, snapshotTime)
172
173 var (
174 userAmount int64
175 exists bool
176 )
177
178 // ReverseIterate from hi down to lo to find the most recent entry at or before snapshotTime
179 history.ReverseIterate(lo, hi, func(_ string, value any) bool {
180 amountInt, ok := value.(int64)
181 if !ok {
182 panic(ufmt.Sprintf("invalid amount type: %T", value))
183 }
184
185 userAmount = amountInt
186 exists = true
187
188 return true // stop after first (most recent) entry
189 })
190
191 return userAmount, exists
192}
193
194// GetClaimableRewardByAddress returns the claimable rewards for an address.
195//
196// Parameters:
197// - addr: staker address whose emission and protocol fee rewards are requested.
198//
199// Returns:
200// - int64: claimable emission reward amount.
201// - map[string]int64: claimable protocol fee amounts keyed by token path.
202// - error: nil on success; an error when emission or protocol fee reward
203// resolution fails.
204func (gs *govStakerV1) GetClaimableRewardByAddress(addr address) (int64, map[string]int64, error) {
205 return gs.GetClaimableRewardByRewardID(addr.String())
206}
207
208// GetClaimableRewardByLaunchpad returns the claimable rewards for a launchpad
209// project address.
210//
211// Parameters:
212// - addr: launchpad project address used to derive its reward ID.
213//
214// Returns:
215// - int64: claimable emission reward amount for the launchpad project.
216// - map[string]int64: claimable protocol fee amounts keyed by token path.
217// - error: nil on success; an error when emission or protocol fee reward
218// resolution fails.
219func (gs *govStakerV1) GetClaimableRewardByLaunchpad(addr address) (int64, map[string]int64, error) {
220 return gs.GetClaimableRewardByRewardID(gs.makeLaunchpadRewardID(addr.String()))
221}
222
223// GetClaimableRewardByRewardID returns the claimable rewards for a reward ID.
224//
225// Parameters:
226// - rewardID: emission/protocol-fee reward state identifier to inspect.
227//
228// Returns:
229// - int64: claimable emission reward amount.
230// - map[string]int64: claimable protocol fee amounts keyed by token path.
231// - error: nil on success; an error when emission or protocol fee reward
232// resolution fails.
233func (gs *govStakerV1) GetClaimableRewardByRewardID(rewardID string) (int64, map[string]int64, error) {
234 emissionDistributedAmount := emission.GetAccuDistributedToGovStaker()
235 emissionRewardManager := gs.store.GetEmissionRewardManager()
236 emissionResolver := NewEmissionRewardManagerResolver(emissionRewardManager)
237 emissionReward, err := emissionResolver.GetClaimableRewardAmount(emissionDistributedAmount, rewardID, time.Now().Unix())
238 if err != nil {
239 return 0, make(map[string]int64), err
240 }
241
242 protocolFeeRewards, err := gs.getClaimableProtocolFeeRewards(rewardID)
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.
251//
252// Parameters:
253// - projectAddr: launchpad project address used to derive its reward ID.
254//
255// Returns:
256// - int64: stored launchpad project deposit amount.
257// - bool: true when a deposit exists for projectAddr, otherwise false.
258func (gs *govStakerV1) GetLaunchpadProjectDeposit(projectAddr string) (int64, bool) {
259 launchpadDeposits := gs.store.GetLaunchpadProjectDeposits()
260 return launchpadDeposits.GetDeposit(gs.makeLaunchpadRewardID(projectAddr))
261}
262
263// GetDelegationWithdrawCount returns the total number of delegation withdraws
264// for a specific delegation.
265//
266// Parameters:
267// - delegationID: delegation identifier whose withdrawals are counted.
268//
269// Returns:
270// - int: number of withdrawals recorded for delegationID, or zero when the
271// delegation does not exist.
272func (gs *govStakerV1) GetDelegationWithdrawCount(delegationID int64) int {
273 delegation, exists := gs.store.GetDelegation(delegationID)
274 if !exists {
275 return 0
276 }
277 return len(delegation.Withdraws())
278}
279
280// GetDelegationWithdraws returns a paginated list of delegation withdraws for a
281// specific delegation.
282//
283// Parameters:
284// - delegationID: delegation identifier whose withdrawals are requested.
285// - offset: zero-based index of the first withdrawal to return.
286// - count: maximum number of withdrawals to return.
287//
288// Returns:
289// - []staker.DelegationWithdraw: withdrawals in the requested range, or an
290// empty slice when the delegation or page is absent.
291// - error: nil; this accessor currently has no error path.
292func (gs *govStakerV1) GetDelegationWithdraws(delegationID int64, offset, count int) ([]staker.DelegationWithdraw, error) {
293 delegation, exists := gs.store.GetDelegation(delegationID)
294 if !exists {
295 return []staker.DelegationWithdraw{}, nil
296 }
297
298 withdraws := delegation.Withdraws()
299 size := len(withdraws)
300 if offset >= size {
301 return []staker.DelegationWithdraw{}, nil
302 }
303
304 end := offset + count
305 if end > size {
306 end = size
307 }
308
309 return withdraws[offset:end], nil
310}
311
312// GetCollectableWithdrawAmount returns the collectable withdraw amount for a
313// specific delegation as of the current Unix time.
314//
315// Parameters:
316// - delegationID: delegation identifier whose matured withdrawals are summed.
317//
318// Returns:
319// - int64: total amount currently collectable, or zero when the delegation
320// does not exist.
321func (gs *govStakerV1) GetCollectableWithdrawAmount(delegationID int64) int64 {
322 delegation, exists := gs.store.GetDelegation(delegationID)
323 if !exists {
324 return 0
325 }
326
327 totalAmount := int64(0)
328 currentTime := time.Now().Unix()
329 for _, withdraw := range delegation.Withdraws() {
330 resolver := NewDelegationWithdrawResolver(&withdraw)
331 totalAmount = gnsmath.SafeAddInt64(totalAmount, resolver.CollectableAmount(currentTime))
332 }
333
334 return totalAmount
335}
336
337// GetProtocolFeeAccumulatedX128PerStake returns the accumulated protocol fee per
338// stake (Q128) for a token path.
339//
340// Parameters:
341// - tokenPath: token identifier/path whose accumulator is requested.
342//
343// Returns:
344// - *uint256.Uint: accumulated protocol fee per stake scaled by 2^128, or a
345// zero value when no accumulator exists for tokenPath.
346func (gs *govStakerV1) GetProtocolFeeAccumulatedX128PerStake(tokenPath string) *uint256.Uint {
347 protocolFeeRewardManager := gs.store.GetProtocolFeeRewardManager()
348 accumulatedFee := protocolFeeRewardManager.GetAccumulatedProtocolFeeX128PerStake(tokenPath)
349 if accumulatedFee == nil {
350 return uint256.NewUint(0)
351 }
352
353 return accumulatedFee
354}
355
356// GetProtocolFeeAmount returns the protocol fee amount accumulated for a token
357// path.
358//
359// Parameters:
360// - tokenPath: token identifier/path whose folded fee amount is requested.
361//
362// Returns:
363// - int64: accumulated protocol fee amount for tokenPath.
364func (gs *govStakerV1) GetProtocolFeeAmount(tokenPath string) int64 {
365 protocolFeeRewardManager := gs.store.GetProtocolFeeRewardManager()
366 return protocolFeeRewardManager.GetProtocolFeeAmount(tokenPath)
367}
368
369// GetProtocolFeeAccumulatedTimestamp returns the accumulated timestamp for
370// protocol fee rewards.
371//
372// Returns:
373// - int64: Unix timestamp represented by protocol fee accumulation state.
374func (gs *govStakerV1) GetProtocolFeeAccumulatedTimestamp() int64 {
375 protocolFeeRewardManager := gs.store.GetProtocolFeeRewardManager()
376 return protocolFeeRewardManager.GetAccumulatedTimestamp()
377}
378
379// GetEmissionAccumulatedX128PerStake returns the accumulated emission per stake
380// (Q128).
381//
382// Returns:
383// - *uint256.Uint: accumulated emission reward per stake scaled by 2^128.
384func (gs *govStakerV1) GetEmissionAccumulatedX128PerStake() *uint256.Uint {
385 emissionRewardManager := gs.store.GetEmissionRewardManager()
386 return emissionRewardManager.GetAccumulatedRewardX128PerStake()
387}
388
389// GetEmissionDistributedAmount returns the total distributed emission amount.
390//
391// Returns:
392// - int64: total emission amount recorded as distributed to governance stakers.
393func (gs *govStakerV1) GetEmissionDistributedAmount() int64 {
394 emissionRewardManager := gs.store.GetEmissionRewardManager()
395 return emissionRewardManager.GetDistributedAmount()
396}
397
398// GetEmissionAccumulatedTimestamp returns the accumulated timestamp for emission
399// rewards.
400//
401// Returns:
402// - int64: Unix timestamp represented by emission accumulation state.
403func (gs *govStakerV1) GetEmissionAccumulatedTimestamp() int64 {
404 emissionRewardManager := gs.store.GetEmissionRewardManager()
405 return emissionRewardManager.GetAccumulatedTimestamp()
406}