Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}