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

getter.gno

32.29 Kb · 963 lines
  1package staker
  2
  3import (
  4	"chain/runtime"
  5	"errors"
  6	"time"
  7
  8	rotree "gno.land/p/nt/bptree/rotree/v0"
  9	ufmt "gno.land/p/nt/ufmt/v0"
 10
 11	u256 "gno.land/p/gnoswap/uint256/v1"
 12
 13	sr "gno.land/r/gnoswap/staker"
 14)
 15
 16// findPoolByPoolPath retrieves the pool by its path, or nil when it does not
 17// exist. Read-only views use it so a missing pool reads as nil rather than
 18// aborting the caller's transaction.
 19func (s *stakerV1) findPoolByPoolPath(poolPath string) *sr.Pool {
 20	result := s.store.GetPools().Get(poolPath)
 21	if result == nil {
 22		return nil
 23	}
 24
 25	pool, ok := result.(*sr.Pool)
 26	if !ok {
 27		return nil
 28	}
 29
 30	return pool
 31}
 32
 33// getPoolByPoolPath retrieves the pool by its path.
 34func (s *stakerV1) getPoolByPoolPath(poolPath string) (*sr.Pool, error) {
 35	result := s.store.GetPools().Get(poolPath)
 36	if result == nil {
 37		return nil, makeErrorWithDetails(
 38			errDataNotFound,
 39			ufmt.Sprintf("poolPath(%s) pool does not exist", poolPath),
 40		)
 41	}
 42
 43	pool, ok := result.(*sr.Pool)
 44	if !ok {
 45		return nil, makeErrorWithDetails(
 46			errDataNotFound,
 47			ufmt.Sprintf("poolPath(%s) pool does not exist", poolPath),
 48		)
 49	}
 50
 51	return pool, nil
 52}
 53
 54// GetPool returns the pool for the given path.
 55//
 56// Parameters:
 57//   - poolPath: Pool path whose pool entry is queried.
 58//
 59// Returns:
 60//   - *sr.Pool: Pool registered at poolPath, or nil when the lookup fails.
 61//   - error: Non-nil when poolPath has no valid pool entry; nil on success.
 62func (s *stakerV1) GetPool(poolPath string) (*sr.Pool, error) {
 63	pool, err := s.getPoolByPoolPath(poolPath)
 64	if err != nil {
 65		return nil, err
 66	}
 67	return pool, nil
 68}
 69
 70// getIncentive retrieves an external incentive by ID.
 71func (s *stakerV1) getIncentive(poolPath string, incentiveId string) (*sr.ExternalIncentive, error) {
 72	pool, err := s.getPoolByPoolPath(poolPath)
 73	if err != nil {
 74		return nil, err
 75	}
 76
 77	incentives := pool.Incentives()
 78	incentive := incentives.IncentiveTrees().Get(incentiveId)
 79	if incentive == nil {
 80		return nil, ufmt.Errorf("incentiveId(%s) incentive does not exist", incentiveId)
 81	}
 82
 83	ictv, ok := incentive.(*sr.ExternalIncentive)
 84	if !ok {
 85		return nil, ufmt.Errorf("failed to cast incentive to *ExternalIncentive: %T", incentive)
 86	}
 87	return ictv, nil
 88}
 89
 90// GetIncentiveStartTimestamp returns the start timestamp of an incentive.
 91//
 92// Parameters:
 93//   - poolPath: Pool path containing the incentive.
 94//   - incentiveId: External incentive identifier whose start time is queried.
 95//
 96// Returns:
 97//   - int64: Incentive start timestamp in Unix seconds.
 98//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
 99func (s *stakerV1) GetIncentiveStartTimestamp(poolPath string, incentiveId string) (int64, error) {
100	incentive, err := s.getIncentive(poolPath, incentiveId)
101	if err != nil {
102		return 0, err
103	}
104
105	return incentive.StartTimestamp(), nil
106}
107
108// GetIncentiveEndTimestamp returns the end timestamp of an incentive.
109//
110// Parameters:
111//   - poolPath: Pool path containing the incentive.
112//   - incentiveId: External incentive identifier whose end time is queried.
113//
114// Returns:
115//   - int64: Incentive end timestamp in Unix seconds.
116//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
117func (s *stakerV1) GetIncentiveEndTimestamp(poolPath string, incentiveId string) (int64, error) {
118	incentive, err := s.getIncentive(poolPath, incentiveId)
119	if err != nil {
120		return 0, err
121	}
122
123	return incentive.EndTimestamp(), nil
124}
125
126// GetTargetPoolPathByIncentiveId returns the target pool path of an incentive.
127//
128// Parameters:
129//   - poolPath: Pool path containing the incentive.
130//   - incentiveId: External incentive identifier whose target pool is queried.
131//
132// Returns:
133//   - string: Pool path targeted by the incentive.
134//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
135func (s *stakerV1) GetTargetPoolPathByIncentiveId(poolPath string, incentiveId string) (string, error) {
136	incentive, err := s.getIncentive(poolPath, incentiveId)
137	if err != nil {
138		return "", err
139	}
140
141	return incentive.TargetPoolPath(), nil
142}
143
144// GetCreatedHeightOfIncentive returns the creation height of an incentive.
145//
146// Parameters:
147//   - poolPath: Pool path containing the incentive.
148//   - incentiveId: External incentive identifier whose creation height is queried.
149//
150// Returns:
151//   - int64: Chain height at which the incentive was created.
152//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
153func (s *stakerV1) GetCreatedHeightOfIncentive(poolPath string, incentiveId string) (int64, error) {
154	incentive, err := s.getIncentive(poolPath, incentiveId)
155	if err != nil {
156		return 0, err
157	}
158
159	return incentive.CreatedHeight(), nil
160}
161
162// GetIncentiveCreatedTimestamp returns the creation timestamp of an incentive.
163//
164// Parameters:
165//   - poolPath: Pool path containing the incentive.
166//   - incentiveId: External incentive identifier whose creation time is queried.
167//
168// Returns:
169//   - int64: Incentive creation timestamp in Unix seconds.
170//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
171func (s *stakerV1) GetIncentiveCreatedTimestamp(poolPath string, incentiveId string) (int64, error) {
172	incentive, err := s.getIncentive(poolPath, incentiveId)
173	if err != nil {
174		return 0, err
175	}
176
177	return incentive.CreatedTimestamp(), nil
178}
179
180// GetIncentiveTotalRewardAmount returns the total reward amount of an incentive.
181//
182// Parameters:
183//   - poolPath: Pool path containing the incentive.
184//   - incentiveId: External incentive identifier whose configured reward is queried.
185//
186// Returns:
187//   - int64: Total reward amount configured for the incentive, in reward-token units.
188//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
189func (s *stakerV1) GetIncentiveTotalRewardAmount(poolPath string, incentiveId string) (int64, error) {
190	incentive, err := s.getIncentive(poolPath, incentiveId)
191	if err != nil {
192		return 0, err
193	}
194
195	return incentive.TotalRewardAmount(), nil
196}
197
198// GetIncentiveDistributedRewardAmount returns the distributed reward amount of an incentive.
199//
200// Parameters:
201//   - poolPath: Pool path containing the incentive.
202//   - incentiveId: External incentive identifier whose distribution total is queried.
203//
204// Returns:
205//   - int64: Reward amount already distributed by the incentive, in reward-token units.
206//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
207func (s *stakerV1) GetIncentiveDistributedRewardAmount(poolPath string, incentiveId string) (int64, error) {
208	incentive, err := s.getIncentive(poolPath, incentiveId)
209	if err != nil {
210		return 0, err
211	}
212
213	return incentive.DistributedRewardAmount(), nil
214}
215
216// GetIncentiveRemainingRewardAmount returns the remaining reward amount of an incentive.
217//
218// Parameters:
219//   - poolPath: Pool path containing the incentive.
220//   - incentiveId: External incentive identifier whose remaining balance is queried.
221//
222// Returns:
223//   - int64: Reward amount still available for collection, in reward-token units.
224//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
225func (s *stakerV1) GetIncentiveRemainingRewardAmount(poolPath string, incentiveId string) (int64, error) {
226	incentive, err := s.getIncentive(poolPath, incentiveId)
227	if err != nil {
228		return 0, err
229	}
230
231	return incentive.RewardAmount(), nil
232}
233
234// GetIncentiveAccumulatedPenaltyAmount returns the accumulated warmup penalty amount of an incentive.
235//
236// Parameters:
237//   - poolPath: Pool path containing the incentive.
238//   - incentiveId: External incentive identifier whose penalties are queried.
239//
240// Returns:
241//   - int64: Warm-up penalty accumulated for the incentive, in reward-token units.
242//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
243func (s *stakerV1) GetIncentiveAccumulatedPenaltyAmount(poolPath string, incentiveId string) (int64, error) {
244	incentive, err := s.getIncentive(poolPath, incentiveId)
245	if err != nil {
246		return 0, err
247	}
248
249	return incentive.AccumulatedPenaltyAmount(), nil
250}
251
252// GetIncentiveDepositGnsAmount returns the deposit GNS amount of an incentive.
253//
254// Parameters:
255//   - poolPath: Pool path containing the incentive.
256//   - incentiveId: External incentive identifier whose GNS deposit is queried.
257//
258// Returns:
259//   - int64: GNS amount deposited when the incentive was created.
260//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
261func (s *stakerV1) GetIncentiveDepositGnsAmount(poolPath string, incentiveId string) (int64, error) {
262	incentive, err := s.getIncentive(poolPath, incentiveId)
263	if err != nil {
264		return 0, err
265	}
266
267	return incentive.DepositGnsAmount(), nil
268}
269
270// GetIncentiveRefunded returns whether an incentive has been refunded.
271//
272// Parameters:
273//   - poolPath: Pool path containing the incentive.
274//   - incentiveId: External incentive identifier whose refund state is queried.
275//
276// Returns:
277//   - bool: true when the incentive has been finalized/refunded; false while it remains unrefunded.
278//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
279func (s *stakerV1) GetIncentiveRefunded(poolPath string, incentiveId string) (bool, error) {
280	incentive, err := s.getIncentive(poolPath, incentiveId)
281	if err != nil {
282		return false, err
283	}
284
285	return incentive.Refunded(), nil
286}
287
288// IsIncentiveActive reports whether an unrefunded incentive is active, including both start and end timestamps.
289//
290// Parameters:
291//   - poolPath: Pool path containing the incentive.
292//   - incentiveId: External incentive identifier whose activity is queried.
293//
294// Returns:
295//   - bool: true when the current Unix time is within the incentive's start/end window and it is unrefunded; false otherwise.
296//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
297func (s *stakerV1) IsIncentiveActive(poolPath string, incentiveId string) (bool, error) {
298	incentive, err := s.getIncentive(poolPath, incentiveId)
299	if err != nil {
300		return false, err
301	}
302	currentTime := time.Now().Unix()
303
304	resolver := NewExternalIncentiveResolver(incentive)
305	return resolver.isActive(currentTime) && !resolver.Refunded(), nil
306}
307
308// GetIncentiveRewardToken returns the reward token of an incentive.
309//
310// Parameters:
311//   - poolPath: Pool path containing the incentive.
312//   - incentiveId: External incentive identifier whose reward token is queried.
313//
314// Returns:
315//   - string: Reward-token package path configured for the incentive.
316//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
317func (s *stakerV1) GetIncentiveRewardToken(poolPath string, incentiveId string) (string, error) {
318	incentive, err := s.getIncentive(poolPath, incentiveId)
319	if err != nil {
320		return "", err
321	}
322
323	return incentive.RewardToken(), nil
324}
325
326// GetIncentiveRewardAmount returns the remaining reward amount of an incentive.
327//
328// Parameters:
329//   - poolPath: Pool path containing the incentive.
330//   - incentiveId: External incentive identifier whose remaining reward is queried.
331//
332// Returns:
333//   - *u256.Uint: Remaining reward amount as a uint256 value, or nil when lookup fails.
334//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
335func (s *stakerV1) GetIncentiveRewardAmount(poolPath string, incentiveId string) (*u256.Uint, error) {
336	incentive, err := s.getIncentive(poolPath, incentiveId)
337	if err != nil {
338		return nil, err
339	}
340
341	return u256.NewUintFromInt64(incentive.RewardAmount()), nil
342}
343
344// GetIncentiveRewardAmountAsString returns the remaining reward amount of an incentive as string.
345//
346// Parameters:
347//   - poolPath: Pool path containing the incentive.
348//   - incentiveId: External incentive identifier whose remaining reward is formatted.
349//
350// Returns:
351//   - string: Remaining reward amount encoded as a decimal string.
352//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
353func (s *stakerV1) GetIncentiveRewardAmountAsString(poolPath string, incentiveId string) (string, error) {
354	rewardAmount, err := s.GetIncentiveRewardAmount(poolPath, incentiveId)
355	if err != nil {
356		return "", err
357	}
358
359	return rewardAmount.ToString(), nil
360}
361
362// GetIncentiveRewardPerSecondX128 returns the Q128-scaled reward per second of
363// an incentive (i.e. actual rate = value / 2^128). The Q128 form preserves
364// sub-second precision that would otherwise be lost to int64 truncation.
365//
366// Parameters:
367//   - poolPath: Pool path containing the incentive.
368//   - incentiveId: External incentive identifier whose reward rate is queried.
369//
370// Returns:
371//   - *u256.Uint: Q128-scaled reward-per-second value; divide by 2^128 for the unscaled rate.
372//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
373func (s *stakerV1) GetIncentiveRewardPerSecondX128(poolPath string, incentiveId string) (*u256.Uint, error) {
374	incentive, err := s.getIncentive(poolPath, incentiveId)
375	if err != nil {
376		return nil, err
377	}
378
379	return incentive.RewardPerSecondX128(), nil
380}
381
382// GetIncentiveCreator returns the creator address of an incentive.
383//
384// Parameters:
385//   - poolPath: Pool path containing the incentive.
386//   - incentiveId: External incentive identifier whose creator is queried.
387//
388// Returns:
389//   - address: Address that created the incentive.
390//   - error: Non-nil when poolPath or incentiveId cannot be resolved; nil on success.
391func (s *stakerV1) GetIncentiveCreator(poolPath string, incentiveId string) (address, error) {
392	incentive, err := s.getIncentive(poolPath, incentiveId)
393	if err != nil {
394		return address(""), err
395	}
396
397	return incentive.Creator(), nil
398}
399
400// getDeposit retrieves a deposit by LP token ID.
401func (s *stakerV1) getDeposit(lpTokenId uint64) (*sr.Deposit, error) {
402	deposits := s.getDeposits()
403	if !deposits.Has(lpTokenId) {
404		return nil, makeErrorWithDetails(
405			errDataNotFound,
406			ufmt.Sprintf("lpTokenId(%d) deposit does not exist", lpTokenId),
407		)
408	}
409
410	return deposits.get(lpTokenId), nil
411}
412
413// assertIsCollectablePosition ensures the position is staked or holds an exit checkpoint.
414func (s *stakerV1) assertIsCollectablePosition(positionId uint64) error {
415	if s.getDeposits().Has(positionId) || s.getUnstakedPositions().Has(positionId) {
416		return nil
417	}
418
419	return makeErrorWithDetails(
420		errDataNotFound,
421		ufmt.Sprintf("lpTokenId(%d) deposit does not exist", positionId),
422	)
423}
424
425// GetDeposit returns the deposit for the given LP token ID.
426//
427// Parameters:
428//   - lpTokenId: LP position NFT token ID whose live deposit is queried.
429//
430// Returns:
431//   - *sr.Deposit: Stored live deposit, or nil when lookup fails.
432//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
433func (s *stakerV1) GetDeposit(lpTokenId uint64) (*sr.Deposit, error) {
434	return s.getDeposit(lpTokenId)
435}
436
437// CollectableEmissionReward returns the claimable internal reward amount for a position.
438// calculateCollectablePositionReward is read-only, so querying a collectable amount never mutates state.
439//
440// Parameters:
441//   - positionId: LP position NFT token ID or exit-checkpoint ID whose accrued GNS reward is estimated.
442//
443// Returns:
444//   - int64: Currently collectable GNS emission amount in GNS units; zero may be a valid accrued amount.
445//   - error: Non-nil when positionId is not staked/checked out or reward calculation fails; nil on success.
446func (s *stakerV1) CollectableEmissionReward(positionId uint64) (int64, error) {
447	currentTime := time.Now().Unix()
448	currentHeight := runtime.ChainHeight()
449	if err := s.assertIsCollectablePosition(positionId); err != nil {
450		return 0, err
451	}
452	reward, err := s.calculateCollectablePositionReward(currentHeight, currentTime, positionId)
453	if err != nil {
454		return 0, err
455	}
456	return reward.Internal, nil
457}
458
459// CollectableExternalIncentiveReward returns the claimable external reward amount for an incentive.
460// calculateCollectablePositionReward is read-only, so querying a collectable amount never mutates state.
461//
462// Parameters:
463//   - positionId: LP position NFT token ID or exit-checkpoint ID whose external reward is estimated.
464//   - incentiveId: External incentive identifier to inspect; an absent reward entry yields zero without error.
465//
466// Returns:
467//   - int64: Currently collectable reward amount for incentiveId, in that incentive's token units.
468//   - error: Non-nil when positionId is not staked/checked out or reward calculation fails; nil on success.
469func (s *stakerV1) CollectableExternalIncentiveReward(positionId uint64, incentiveId string) (int64, error) {
470	currentTime := time.Now().Unix()
471	currentHeight := runtime.ChainHeight()
472	if err := s.assertIsCollectablePosition(positionId); err != nil {
473		return 0, err
474	}
475	reward, err := s.calculateCollectablePositionReward(currentHeight, currentTime, positionId)
476	if err != nil {
477		return 0, err
478	}
479	amount, ok := reward.External[incentiveId]
480	if !ok {
481		return 0, nil
482	}
483	return amount, nil
484}
485
486// GetDepositOwner returns the owner of a deposit.
487//
488// Parameters:
489//   - lpTokenId: LP position NFT token ID whose owner is queried.
490//
491// Returns:
492//   - address: Address recorded as the deposit owner.
493//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
494func (s *stakerV1) GetDepositOwner(lpTokenId uint64) (address, error) {
495	deposit, err := s.getDeposit(lpTokenId)
496	if err != nil {
497		return address(""), err
498	}
499
500	return deposit.Owner(), nil
501}
502
503// GetDepositStakeTime returns the Unix timestamp at which a position was staked.
504//
505// Parameters:
506//   - lpTokenId: LP position NFT token ID whose stake time is queried.
507//
508// Returns:
509//   - int64: Unix timestamp at which the position was staked.
510//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
511func (s *stakerV1) GetDepositStakeTime(lpTokenId uint64) (int64, error) {
512	deposit, err := s.getDeposit(lpTokenId)
513	if err != nil {
514		return 0, err
515	}
516
517	return deposit.StakeTime(), nil
518}
519
520// GetDepositTargetPoolPath returns the target pool path of a deposit.
521//
522// Parameters:
523//   - lpTokenId: LP position NFT token ID whose pool target is queried.
524//
525// Returns:
526//   - string: Pool path targeted by the deposit.
527//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
528func (s *stakerV1) GetDepositTargetPoolPath(lpTokenId uint64) (string, error) {
529	deposit, err := s.getDeposit(lpTokenId)
530	if err != nil {
531		return "", err
532	}
533
534	return deposit.TargetPoolPath(), nil
535}
536
537// GetDepositTickLower returns the lower tick of a deposit.
538//
539// Parameters:
540//   - lpTokenId: LP position NFT token ID whose lower tick is queried.
541//
542// Returns:
543//   - int32: Signed lower tick boundary recorded by the deposit.
544//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
545func (s *stakerV1) GetDepositTickLower(lpTokenId uint64) (int32, error) {
546	deposit, err := s.getDeposit(lpTokenId)
547	if err != nil {
548		return 0, err
549	}
550
551	return deposit.TickLower(), nil
552}
553
554// GetDepositTickUpper returns the upper tick of a deposit.
555//
556// Parameters:
557//   - lpTokenId: LP position NFT token ID whose upper tick is queried.
558//
559// Returns:
560//   - int32: Signed upper tick boundary recorded by the deposit.
561//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
562func (s *stakerV1) GetDepositTickUpper(lpTokenId uint64) (int32, error) {
563	deposit, err := s.getDeposit(lpTokenId)
564	if err != nil {
565		return 0, err
566	}
567
568	return deposit.TickUpper(), nil
569}
570
571// GetDepositLiquidity returns the liquidity of a deposit.
572//
573// Parameters:
574//   - lpTokenId: LP position NFT token ID whose liquidity is queried.
575//
576// Returns:
577//   - *u256.Uint: Position liquidity as an unsigned 256-bit value, or nil when lookup fails.
578//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
579func (s *stakerV1) GetDepositLiquidity(lpTokenId uint64) (*u256.Uint, error) {
580	deposit, err := s.getDeposit(lpTokenId)
581	if err != nil {
582		return nil, err
583	}
584
585	return deposit.Liquidity(), nil
586}
587
588// GetDepositLiquidityAsString returns the liquidity of a deposit as string.
589//
590// Parameters:
591//   - lpTokenId: LP position NFT token ID whose liquidity is formatted.
592//
593// Returns:
594//   - string: Position liquidity encoded as a decimal string.
595//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
596func (s *stakerV1) GetDepositLiquidityAsString(lpTokenId uint64) (string, error) {
597	liquidity, err := s.GetDepositLiquidity(lpTokenId)
598	if err != nil {
599		return "", err
600	}
601
602	return liquidity.ToString(), nil
603}
604
605// GetDepositInternalRewardLastCollectTimestamp returns the last collect timestamp of a deposit.
606//
607// Parameters:
608//   - lpTokenId: LP position NFT token ID whose internal-reward cursor is queried.
609//
610// Returns:
611//   - int64: Unix timestamp of the deposit's last internal GNS reward collection.
612//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
613func (s *stakerV1) GetDepositInternalRewardLastCollectTimestamp(lpTokenId uint64) (int64, error) {
614	deposit, err := s.getDeposit(lpTokenId)
615	if err != nil {
616		return 0, err
617	}
618
619	return deposit.InternalRewardLastCollectTime(), nil
620}
621
622// GetDepositCollectedInternalReward returns the collected internal reward amount.
623//
624// Parameters:
625//   - lpTokenId: LP position NFT token ID whose collected GNS amount is queried.
626//
627// Returns:
628//   - int64: Cumulative internal GNS reward already collected for the deposit.
629//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
630func (s *stakerV1) GetDepositCollectedInternalReward(lpTokenId uint64) (int64, error) {
631	deposit, err := s.getDeposit(lpTokenId)
632	if err != nil {
633		return 0, err
634	}
635
636	return deposit.CollectedInternalReward(), nil
637}
638
639// GetDepositCollectedExternalReward returns the collected external reward amount for an incentive.
640//
641// Parameters:
642//   - lpTokenId: LP position NFT token ID whose external-reward history is queried.
643//   - incentiveId: External incentive identifier whose collected amount is queried.
644//
645// Returns:
646//   - int64: Cumulative reward collected from incentiveId, in its reward-token units.
647//   - error: Non-nil when the position deposit or its checkpoint data cannot be resolved; nil on success.
648func (s *stakerV1) GetDepositCollectedExternalReward(lpTokenId uint64, incentiveId string) (int64, error) {
649	depositResolver, err := s.getDepositResolver(lpTokenId)
650	if err != nil {
651		return 0, err
652	}
653	return depositResolver.CollectedExternalReward(incentiveId), nil
654}
655
656// GetDepositExternalRewardLastCollectTimestamp returns the last collect timestamp of a deposit.
657//
658// Parameters:
659//   - lpTokenId: LP position NFT token ID whose external-reward cursor is queried.
660//   - incentiveId: External incentive identifier whose collection time is queried.
661//
662// Returns:
663//   - int64: Unix timestamp of the deposit's last collection for incentiveId.
664//   - error: Non-nil when the position deposit or its checkpoint data cannot be resolved; nil on success.
665func (s *stakerV1) GetDepositExternalRewardLastCollectTimestamp(lpTokenId uint64, incentiveId string) (int64, error) {
666	depositResolver, err := s.getDepositResolver(lpTokenId)
667	if err != nil {
668		return 0, err
669	}
670	return depositResolver.ExternalRewardLastCollectTime(incentiveId), nil
671}
672
673// GetDepositWarmUp returns the warm-up records of a deposit.
674//
675// Parameters:
676//   - lpTokenId: LP position NFT token ID whose warm-up records are queried.
677//
678// Returns:
679//   - []sr.Warmup: Warm-up reward records currently associated with the deposit.
680//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
681func (s *stakerV1) GetDepositWarmUp(lpTokenId uint64) ([]sr.Warmup, error) {
682	deposit, err := s.getDeposit(lpTokenId)
683	if err != nil {
684		return nil, err
685	}
686
687	return deposit.Warmups(), nil
688}
689
690// GetDepositExternalIncentiveIdList returns external incentive IDs for a deposit.
691//
692// Parameters:
693//   - lpTokenId: LP position NFT token ID whose incentive index is queried.
694//
695// Returns:
696//   - []string: External incentive identifiers tracked by the deposit.
697//   - error: Non-nil data-not-found error when lpTokenId is not currently deposited; nil on success.
698func (s *stakerV1) GetDepositExternalIncentiveIdList(lpTokenId uint64) ([]string, error) {
699	deposit, err := s.getDeposit(lpTokenId)
700	if err != nil {
701		return nil, err
702	}
703
704	return deposit.GetExternalIncentiveIdList(), nil
705}
706
707// GetPoolTier returns the tier of a pool.
708//
709// Parameters:
710//   - poolPath: Pool path whose current emission tier is queried.
711//
712// Returns:
713//   - uint64: Current tier number; zero means the pool is not an internal-emission target.
714func (s *stakerV1) GetPoolTier(poolPath string) uint64 {
715	return s.getPoolTier().CurrentTier(poolPath)
716}
717
718// GetPoolTierRatio returns the current reward ratio for a pool's tier.
719//
720// Parameters:
721//   - poolPath: Pool path whose current tier ratio is queried.
722//
723// Returns:
724//   - uint64: Configured percentage weight (0-100) associated with the pool's current tier.
725//   - error: Non-nil when the pool's current tier has no configured ratio; nil on success.
726func (s *stakerV1) GetPoolTierRatio(poolPath string) (uint64, error) {
727	tier := s.GetPoolTier(poolPath)
728	ratio, err := s.getPoolTier().tierRatio.Get(tier)
729	if err != nil {
730		return 0, makeErrorWithDetails(errInvalidPoolTier, err.Error())
731	}
732
733	return ratio, nil
734}
735
736// GetPoolTierCount returns the number of pools in a tier.
737//
738// Parameters:
739//   - tier: Tier number whose current pool membership count is queried.
740//
741// Returns:
742//   - uint64: Number of pools currently assigned to tier; zero is returned for tier zero.
743func (s *stakerV1) GetPoolTierCount(tier uint64) uint64 {
744	if tier == 0 {
745		return 0
746	}
747	return uint64(s.getPoolTier().CurrentCount(tier))
748}
749
750// GetPoolReward returns the current reward amount for a tier.
751//
752// Parameters:
753//   - tier: Emission tier whose current per-pool reward is queried.
754//
755// Returns:
756//   - int64: Current GNS reward allocation per second for one pool in tier.
757//   - error: Non-nil when tier is outside the configured range or the emission rate cannot be read; nil on success.
758func (s *stakerV1) GetPoolReward(tier uint64) (int64, error) {
759	if tier == 0 || tier >= AllTierCount {
760		return 0, makeErrorWithDetails(
761			errInvalidPoolTier,
762			ufmt.Sprintf("tier(%d) must be between 1 and %d", tier, AllTierCount-1),
763		)
764	}
765	return s.getPoolTier().CurrentReward(tier)
766}
767
768// GetPoolStakedLiquidity returns the current total staked liquidity of a pool.
769//
770// Parameters:
771//   - poolPath: Pool path whose current staked liquidity is queried.
772//
773// Returns:
774//   - string: Current staked liquidity encoded as a decimal unsigned-integer string.
775//   - error: Non-nil when poolPath has no registered pool; nil on success.
776func (s *stakerV1) GetPoolStakedLiquidity(poolPath string) (string, error) {
777	pool, err := s.getPoolByPoolPath(poolPath)
778	if err != nil {
779		return "", err
780	}
781	liquidity := NewPoolResolver(pool).CurrentStakedLiquidity(time.Now().Unix())
782	if liquidity == nil {
783		return u256.Zero().ToString(), nil
784	}
785
786	return liquidity.ToString(), nil
787}
788
789// GetPoolsByTier returns the list of pools in a tier.
790//
791// Parameters:
792//   - tier: Tier number whose pool membership is listed.
793//
794// Returns:
795//   - []string: Pool paths currently assigned to tier, or an empty slice for tier zero.
796//   - error: Non-nil when stored tier membership cannot be cast to uint64; nil on success.
797func (s *stakerV1) GetPoolsByTier(tier uint64) ([]string, error) {
798	if tier == 0 {
799		return []string{}, nil
800	}
801
802	pools := make([]string, 0)
803	var iterErr error
804	s.getPoolTier().membership.Iterate("", "", func(poolPath string, value any) bool {
805		currentTier, ok := value.(uint64)
806		if !ok {
807			iterErr = errors.New("failed to cast tier to uint64")
808			return true
809		}
810		if currentTier == tier {
811			pools = append(pools, poolPath)
812		}
813		return false
814	})
815	if iterErr != nil {
816		return nil, iterErr
817	}
818
819	return pools, nil
820}
821
822// GetTotalEmissionSent returns the total GNS emission sent.
823//
824// Returns:
825//   - int64: Cumulative GNS emission amount sent by the staker.
826func (s *stakerV1) GetTotalEmissionSent() int64 {
827	return s.store.GetTotalEmissionSent()
828}
829
830// GetAllowedTokens returns the allowed external incentive token list.
831//
832// Returns:
833//   - []string: Token paths currently allowed for external incentives.
834func (s *stakerV1) GetAllowedTokens() []string {
835	return s.store.GetAllowedTokens()
836}
837
838// GetDeniedRewardTokens returns the denied external incentive reward token list.
839//
840// Returns:
841//   - []string: Token paths currently denied for newly created external incentives.
842func (s *stakerV1) GetDeniedRewardTokens() []string {
843	return s.store.GetDeniedRewardTokens()
844}
845
846// GetWarmupTemplate returns the current warmup template.
847//
848// Returns:
849//   - []sr.Warmup: Current warm-up percentage and duration records used for reward calculations.
850func (s *stakerV1) GetWarmupTemplate() []sr.Warmup {
851	return s.store.GetWarmupTemplate()
852}
853
854// IsStaked returns whether a position is staked.
855//
856// Parameters:
857//   - positionId: LP position NFT token ID whose live-staking status is queried.
858//
859// Returns:
860//   - bool: true when positionId has a live deposit; false when it is not staked.
861func (s *stakerV1) IsStaked(positionId uint64) bool {
862	return s.getDeposits().Has(positionId)
863}
864
865// GetExternalIncentiveByPoolPath returns all external incentives for a pool.
866//
867// Parameters:
868//   - poolPath: Pool path whose external incentives are listed.
869//
870// Returns:
871//   - []sr.ExternalIncentive: External incentives targeting poolPath, or an empty slice when none exist.
872//   - error: Non-nil when an external-incentive entry has an incompatible stored type; nil on success.
873func (s *stakerV1) GetExternalIncentiveByPoolPath(poolPath string) ([]sr.ExternalIncentive, error) {
874	incentives := make([]sr.ExternalIncentive, 0)
875	var iterErr error
876
877	s.store.GetExternalIncentives().Iterate("", "", func(_ string, value any) bool {
878		incentive, ok := value.(*sr.ExternalIncentive)
879		if !ok {
880			iterErr = errors.New("failed to cast value to *ExternalIncentive")
881			return true
882		}
883		if incentive.TargetPoolPath() == poolPath {
884			incentives = append(incentives, *incentive)
885		}
886		return false
887	})
888	if iterErr != nil {
889		return nil, iterErr
890	}
891
892	return incentives, nil
893}
894
895// GetPoolRewardCaches returns a read-only view of a pool's reward cache, keyed
896// by the encoded block timestamp. nil is returned when the pool does not exist.
897//
898// Parameters:
899//   - poolPath: Pool path whose reward-cache view is requested.
900//
901// Returns:
902//   - *rotree.ReadOnlyTree: Read-only tree keyed by encoded Unix timestamps with int64 reward rates; nil when poolPath is absent or malformed.
903func (s *stakerV1) GetPoolRewardCaches(poolPath string) *rotree.ReadOnlyTree {
904	pool := s.findPoolByPoolPath(poolPath)
905	if pool == nil {
906		return nil
907	}
908
909	return pool.RewardCache().ReadOnly(rewardCacheEntry)
910}
911
912// GetPoolIncentives returns a read-only view of a pool's external incentives,
913// keyed by incentive ID. nil is returned when the pool does not exist.
914//
915// Parameters:
916//   - poolPath: Pool path whose external-incentive view is requested.
917//
918// Returns:
919//   - *rotree.ReadOnlyTree: Read-only tree keyed by incentive ID with cloned external-incentive values; nil when poolPath is absent or malformed.
920func (s *stakerV1) GetPoolIncentives(poolPath string) *rotree.ReadOnlyTree {
921	pool := s.findPoolByPoolPath(poolPath)
922	if pool == nil {
923		return nil
924	}
925
926	return rotree.Wrap(pool.Incentives().IncentiveTrees(), cloneExternalIncentiveEntry)
927}
928
929// GetPoolGlobalRewardRatioAccumulations returns a read-only view of a pool's
930// global reward ratio accumulation, keyed by the encoded block timestamp.
931// nil is returned when the pool does not exist.
932//
933// Parameters:
934//   - poolPath: Pool path whose global reward-ratio history is requested.
935//
936// Returns:
937//   - *rotree.ReadOnlyTree: Read-only tree keyed by encoded Unix timestamps with string-encoded accumulations; nil when poolPath is absent or malformed.
938func (s *stakerV1) GetPoolGlobalRewardRatioAccumulations(poolPath string) *rotree.ReadOnlyTree {
939	pool := s.findPoolByPoolPath(poolPath)
940	if pool == nil {
941		return nil
942	}
943
944	return pool.GlobalRewardRatioAccumulation().ReadOnly(accumulationEntry)
945}
946
947// GetPoolHistoricalTicks returns a read-only view of a pool's historical ticks,
948// keyed by the encoded block timestamp with the int32 tick as the value.
949// nil is returned when the pool does not exist.
950//
951// Parameters:
952//   - poolPath: Pool path whose historical tick view is requested.
953//
954// Returns:
955//   - *rotree.ReadOnlyTree: Read-only tree keyed by encoded Unix timestamps with int32 tick values; nil when poolPath is absent or malformed.
956func (s *stakerV1) GetPoolHistoricalTicks(poolPath string) *rotree.ReadOnlyTree {
957	pool := s.findPoolByPoolPath(poolPath)
958	if pool == nil {
959		return nil
960	}
961
962	return pool.HistoricalTick().ReadOnly(historicalTickEntry)
963}