Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}