Search Apps Documentation Source Content File Folder Download Copy Actions Download

getter.gno

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