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}