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

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}