deposit.gno
9.68 Kb ยท 338 lines
1package staker
2
3import (
4 "math"
5
6 u256 "gno.land/p/gnoswap/uint256"
7 "gno.land/p/nt/avl"
8)
9
10type Deposit struct {
11 warmups []Warmup // warmup information
12 liquidity *u256.Uint // liquidity
13 targetPoolPath string // staked position's pool path
14 owner address // owner address
15 stakeTime int64 // staked time
16 internalRewardLastCollectTime int64 // last collect time for internal reward
17 collectedInternalReward int64 // collected internal reward
18 collectedExternalRewards *avl.Tree // collected external reward by incentive id (incentiveID -> int64)
19 externalRewardLastCollectTimes *avl.Tree // last collect time for external rewards by incentive id (incentiveID -> int64)
20 externalIncentiveIds *avl.Tree // external incentive ids for this deposit (incentiveID -> bool)
21 lastExternalIncentiveUpdatedAt int64 // last time when external incentive ids were synced
22 tickLower int32 // tick lower
23 tickUpper int32 // tick upper
24}
25
26func (d *Deposit) Owner() address {
27 return d.owner
28}
29
30func (d *Deposit) SetOwner(owner address) {
31 d.owner = owner
32}
33
34func (d *Deposit) TargetPoolPath() string {
35 return d.targetPoolPath
36}
37
38func (d *Deposit) SetTargetPoolPath(targetPoolPath string) {
39 d.targetPoolPath = targetPoolPath
40}
41
42func (d *Deposit) Liquidity() *u256.Uint {
43 return d.liquidity
44}
45
46func (d *Deposit) SetLiquidity(liquidity *u256.Uint) {
47 d.liquidity = liquidity
48}
49
50func (d *Deposit) StakeTime() int64 {
51 return d.stakeTime
52}
53
54func (d *Deposit) SetStakeTime(stakeTime int64) {
55 d.stakeTime = stakeTime
56}
57
58func (d *Deposit) InternalRewardLastCollectTime() int64 {
59 return d.internalRewardLastCollectTime
60}
61
62func (d *Deposit) SetInternalRewardLastCollectTime(internalRewardLastCollectTime int64) {
63 d.internalRewardLastCollectTime = internalRewardLastCollectTime
64}
65
66func (d *Deposit) CollectedInternalReward() int64 {
67 return d.collectedInternalReward
68}
69
70func (d *Deposit) SetCollectedInternalReward(collectedInternalReward int64) {
71 d.collectedInternalReward = collectedInternalReward
72}
73
74func (d *Deposit) CollectedExternalRewards() *avl.Tree {
75 return d.collectedExternalRewards
76}
77
78func (d *Deposit) SetCollectedExternalRewards(collectedExternalRewards *avl.Tree) {
79 d.collectedExternalRewards = collectedExternalRewards
80}
81
82// GetCollectedExternalReward returns the collected external reward for the given incentive ID.
83// Returns 0 if the incentive ID does not exist.
84func (d *Deposit) GetCollectedExternalReward(incentiveID string) (int64, bool) {
85 if d.collectedExternalRewards == nil {
86 return 0, false
87 }
88
89 value, exists := d.collectedExternalRewards.Get(incentiveID)
90 if !exists {
91 return 0, false
92 }
93
94 v, ok := value.(int64)
95 if !ok {
96 panic("failed to cast value to int64")
97 }
98 return v, true
99}
100
101func (d *Deposit) SetCollectedExternalReward(incentiveID string, reward int64) {
102 if d.collectedExternalRewards == nil {
103 d.collectedExternalRewards = avl.NewTree()
104 }
105 d.collectedExternalRewards.Set(incentiveID, reward)
106}
107
108func (d *Deposit) ExternalRewardLastCollectTimes() *avl.Tree {
109 return d.externalRewardLastCollectTimes
110}
111
112func (d *Deposit) SetExternalRewardLastCollectTimes(externalRewardLastCollectTimes *avl.Tree) {
113 d.externalRewardLastCollectTimes = externalRewardLastCollectTimes
114}
115
116// GetExternalRewardLastCollectTime returns the last collect time for the given incentive ID.
117// Returns 0 if the incentive ID does not exist.
118func (d *Deposit) GetExternalRewardLastCollectTime(incentiveID string) (int64, bool) {
119 if d.externalRewardLastCollectTimes == nil {
120 return 0, false
121 }
122
123 value, exists := d.externalRewardLastCollectTimes.Get(incentiveID)
124 if !exists {
125 return 0, false
126 }
127
128 v, ok := value.(int64)
129 if !ok {
130 panic("failed to cast value to int64")
131 }
132 return v, true
133}
134
135func (d *Deposit) SetExternalRewardLastCollectTime(incentiveID string, currentTime int64) {
136 if d.externalRewardLastCollectTimes == nil {
137 d.externalRewardLastCollectTimes = avl.NewTree()
138 }
139 d.externalRewardLastCollectTimes.Set(incentiveID, currentTime)
140}
141
142func (d *Deposit) TickLower() int32 {
143 return d.tickLower
144}
145
146func (d *Deposit) SetTickLower(tickLower int32) {
147 d.tickLower = tickLower
148}
149
150func (d *Deposit) TickUpper() int32 {
151 return d.tickUpper
152}
153
154func (d *Deposit) SetTickUpper(tickUpper int32) {
155 d.tickUpper = tickUpper
156}
157
158func (d *Deposit) ExternalIncentiveIds() *avl.Tree {
159 return d.externalIncentiveIds
160}
161
162func (d *Deposit) SetExternalIncentiveIds(externalIncentiveIds *avl.Tree) {
163 d.externalIncentiveIds = externalIncentiveIds
164}
165
166// AddExternalIncentiveId adds an external incentive id to the deposit.
167func (d *Deposit) AddExternalIncentiveId(incentiveId string) {
168 if d.externalIncentiveIds == nil {
169 d.externalIncentiveIds = avl.NewTree()
170 }
171 d.externalIncentiveIds.Set(incentiveId, true)
172}
173
174// HasExternalIncentiveId checks if the deposit has the given external incentive id.
175func (d *Deposit) HasExternalIncentiveId(incentiveId string) bool {
176 if d.externalIncentiveIds == nil {
177 return false
178 }
179 return d.externalIncentiveIds.Has(incentiveId)
180}
181
182// RemoveExternalIncentiveId removes an external incentive id from the deposit.
183func (d *Deposit) RemoveExternalIncentiveId(incentiveId string) {
184 if d.externalIncentiveIds == nil {
185 return
186 }
187 d.externalIncentiveIds.Remove(incentiveId)
188}
189
190// GetExternalIncentiveIdList returns a list of external incentive ids for the deposit.
191func (d *Deposit) GetExternalIncentiveIdList() []string {
192 if d.externalIncentiveIds == nil {
193 return []string{}
194 }
195
196 ids := make([]string, 0, d.externalIncentiveIds.Size())
197 d.externalIncentiveIds.Iterate("", "", func(key string, _ any) bool {
198 ids = append(ids, key)
199 return false
200 })
201 return ids
202}
203
204// IterateExternalIncentiveIds iterates over external incentive IDs without allocating a slice.
205// The callback function receives each incentive ID and should return false to continue iteration,
206// or true to stop early. This method is more memory-efficient than GetExternalIncentiveIdList
207// for cases where you only need to process IDs sequentially.
208func (d *Deposit) IterateExternalIncentiveIds(fn func(incentiveId string) bool) {
209 if d.externalIncentiveIds == nil {
210 return
211 }
212 d.externalIncentiveIds.Iterate("", "", func(key string, _ any) bool {
213 return fn(key)
214 })
215}
216
217func (d *Deposit) Warmups() []Warmup {
218 return d.warmups
219}
220
221func (d *Deposit) SetWarmups(warmups []Warmup) {
222 d.warmups = warmups
223}
224
225func (d *Deposit) LastExternalIncentiveUpdatedAt() int64 {
226 return d.lastExternalIncentiveUpdatedAt
227}
228
229func (d *Deposit) SetLastExternalIncentiveUpdatedAt(timestamp int64) {
230 d.lastExternalIncentiveUpdatedAt = timestamp
231}
232
233// Clone returns a deep copy of the deposit.
234func (d *Deposit) Clone() *Deposit {
235 if d == nil {
236 return nil
237 }
238
239 return &Deposit{
240 warmups: cloneWarmups(d.warmups),
241 liquidity: d.liquidity.Clone(),
242 targetPoolPath: d.targetPoolPath,
243 owner: d.owner,
244 stakeTime: d.stakeTime,
245 internalRewardLastCollectTime: d.internalRewardLastCollectTime,
246 collectedInternalReward: d.collectedInternalReward,
247 collectedExternalRewards: cloneAvlTree(d.collectedExternalRewards),
248 externalRewardLastCollectTimes: cloneAvlTree(d.externalRewardLastCollectTimes),
249 externalIncentiveIds: cloneAvlTree(d.externalIncentiveIds),
250 lastExternalIncentiveUpdatedAt: d.lastExternalIncentiveUpdatedAt,
251 tickLower: d.tickLower,
252 tickUpper: d.tickUpper,
253 }
254}
255
256func NewDeposit(
257 owner address,
258 targetPoolPath string,
259 liquidity *u256.Uint,
260 currentTime int64,
261 tickLower, tickUpper int32,
262 warmups []Warmup,
263) *Deposit {
264 return &Deposit{
265 owner: owner,
266 targetPoolPath: targetPoolPath,
267 liquidity: liquidity,
268 warmups: warmups,
269 stakeTime: currentTime,
270 tickLower: tickLower,
271 tickUpper: tickUpper,
272 internalRewardLastCollectTime: currentTime,
273 externalRewardLastCollectTimes: avl.NewTree(),
274 collectedInternalReward: 0,
275 collectedExternalRewards: avl.NewTree(),
276 externalIncentiveIds: avl.NewTree(),
277 lastExternalIncentiveUpdatedAt: 0,
278 }
279}
280
281type Warmup struct {
282 Index int
283 TimeDuration int64
284 NextWarmupTime int64 // time when this warmup period ends
285 WarmupRatio uint64
286}
287
288func (w *Warmup) SetNextWarmupTime(nextWarmupTime int64) {
289 w.NextWarmupTime = nextWarmupTime
290}
291
292func (w *Warmup) SetWarmupRatio(warmupRatio uint64) {
293 w.WarmupRatio = warmupRatio
294}
295
296func (w *Warmup) SetTimeDuration(timeDuration int64) {
297 w.TimeDuration = timeDuration
298}
299
300func DefaultWarmupTemplate() []Warmup {
301 secondsInDay := int64(86400)
302 secondsIn5Days := int64(5 * secondsInDay)
303 secondsIn10Days := int64(10 * secondsInDay)
304 secondsIn30Days := int64(30 * secondsInDay)
305
306 // NextWarmupTime is set to 0 for template.
307 // They will be set by InstantiateWarmup()
308 return []Warmup{
309 {
310 Index: 0,
311 TimeDuration: secondsIn5Days,
312 // NextWarmupTime will be set based on currentTime
313 // NextWarmupTime: currentTime + secondsIn5Days,
314 WarmupRatio: 30,
315 },
316 {
317 Index: 1,
318 TimeDuration: secondsIn10Days,
319 // NextWarmupTime will be set based on currentTime
320 // NextWarmupTime: currentTime + secondsIn10Days,
321 WarmupRatio: 50,
322 },
323 {
324 Index: 2,
325 TimeDuration: secondsIn30Days,
326 // NextWarmupTime will be set based on currentTime
327 // NextWarmupTime: currentTime + secondsIn30Days,
328 WarmupRatio: 70,
329 },
330 {
331 Index: 3,
332 TimeDuration: math.MaxInt64,
333 // NextWarmupTime will be set to math.MaxInt64
334 // NextWarmupTime: math.MaxInt64,
335 WarmupRatio: 100,
336 },
337 }
338}