delegation.gno
3.87 Kb ยท 148 lines
1package v1
2
3import (
4 "errors"
5
6 "gno.land/r/gnoswap/gov/staker"
7)
8
9var (
10 errCollectAmountExceedsCollectable = errors.New("amount to collect is greater than collectable amount")
11)
12
13type DelegationResolver struct {
14 delegation *staker.Delegation
15}
16
17func NewDelegationResolver(delegation *staker.Delegation) *DelegationResolver {
18 return &DelegationResolver{delegation}
19}
20
21func (r *DelegationResolver) Get() *staker.Delegation {
22 return r.delegation
23}
24
25func (r *DelegationResolver) DelegatedAmount() int64 {
26 return safeSubInt64(r.delegation.TotalDelegatedAmount(), r.delegation.UnDelegatedAmount())
27}
28
29func (r *DelegationResolver) LockedAmount() int64 {
30 return safeSubInt64(r.delegation.TotalDelegatedAmount(), r.delegation.CollectedAmount())
31}
32
33func (r *DelegationResolver) IsEmpty() bool {
34 return r.LockedAmount() == 0
35}
36
37// CollectableAmount calculates the total amount that can be collected at the given time
38func (r *DelegationResolver) CollectableAmount(currentTime int64) (total int64) {
39 for _, withdraw := range r.delegation.Withdraws() {
40 total = safeAddInt64(total, NewDelegationWithdrawResolver(withdraw).CollectableAmount(currentTime))
41 }
42 return total
43}
44
45// UnDelegate processes an undelegation with lockup period
46func (r *DelegationResolver) UnDelegate(
47 amount, currentHeight, currentTimestamp, unDelegationLockupPeriod int64,
48) {
49 r.delegation.SetUnDelegateAmount(safeAddInt64(r.delegation.UnDelegatedAmount(), amount))
50
51 withdraw := NewDelegationWithdraw(
52 r.delegation.ID(),
53 amount,
54 currentHeight,
55 currentTimestamp,
56 unDelegationLockupPeriod,
57 )
58 r.delegation.AddWithdraw(withdraw)
59}
60
61// UnDelegateWithoutLockup processes an immediate undelegation without lockup
62func (r *DelegationResolver) UnDelegateWithoutLockup(
63 amount, currentHeight, currentTime int64,
64) {
65 r.delegation.SetUnDelegateAmount(safeAddInt64(r.delegation.UnDelegatedAmount(), amount))
66 r.delegation.SetCollectedAmount(safeAddInt64(r.delegation.CollectedAmount(), amount))
67}
68
69// processCollection handles the actual collection logic
70func (r *DelegationResolver) processCollection(currentTime int64) (int64, error) {
71 collectedAmount := int64(0)
72 withdraws := r.delegation.Withdraws()
73
74 for _, withdraw := range withdraws {
75 resolver := NewDelegationWithdrawResolver(withdraw)
76
77 collectableAmount := resolver.CollectableAmount(currentTime)
78 if collectableAmount <= 0 {
79 continue
80 }
81
82 err := resolver.Collect(collectableAmount, currentTime)
83 if err != nil {
84 return 0, err
85 }
86
87 updatedAmount, err := addToCollectedAmount(r.delegation.CollectedAmount(), collectableAmount)
88 if err != nil {
89 return 0, err
90 }
91
92 r.delegation.SetCollectedAmount(updatedAmount)
93 collectedAmount = safeAddInt64(collectedAmount, collectableAmount)
94 }
95
96 // Skip filtering if nothing was collected
97 if collectedAmount == 0 {
98 return collectedAmount, nil
99 }
100
101 currentIndex := 0
102
103 for _, withdraw := range withdraws {
104 if !withdraw.IsCollected() {
105 withdraws[currentIndex] = withdraw
106 currentIndex++
107 }
108 }
109
110 r.delegation.SetWithdraws(withdraws[:currentIndex])
111
112 return collectedAmount, nil
113}
114
115func addToCollectedAmount(collectedAmount, amount int64) (int64, error) {
116 if amount < 0 {
117 return 0, errors.New("amount must be non-negative")
118 }
119 return safeAddInt64(collectedAmount, amount), nil
120}
121
122// NewDelegation creates a new delegation.
123// This is a convenience wrapper around staker.NewDelegation.
124//
125// Parameters:
126// - id: delegation ID
127// - delegateFrom: delegator's address
128// - delegateTo: delegatee's address
129// - delegateAmount: amount to delegate
130// - createdHeight: creation block height
131// - createdAt: creation timestamp
132//
133// Returns:
134// - *staker.Delegation: new delegation instance
135func NewDelegation(
136 id int64,
137 delegateFrom, delegateTo address,
138 delegateAmount, createdHeight, createdAt int64,
139) *staker.Delegation {
140 return staker.NewDelegation(
141 id,
142 delegateFrom,
143 delegateTo,
144 delegateAmount,
145 createdHeight,
146 createdAt,
147 )
148}