delegation.gno
3.88 Kb · 149 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
43 return total
44}
45
46// UnDelegate processes an undelegation with lockup period
47func (r *DelegationResolver) UnDelegate(
48 amount, currentHeight, currentTimestamp, unDelegationLockupPeriod int64,
49) {
50 r.delegation.SetUnDelegateAmount(safeAddInt64(r.delegation.UnDelegatedAmount(), amount))
51
52 withdraw := NewDelegationWithdraw(
53 r.delegation.ID(),
54 amount,
55 currentHeight,
56 currentTimestamp,
57 unDelegationLockupPeriod,
58 )
59 r.delegation.AddWithdraw(withdraw)
60}
61
62// UnDelegateWithoutLockup processes an immediate undelegation without lockup
63func (r *DelegationResolver) UnDelegateWithoutLockup(
64 amount, currentHeight, currentTime int64,
65) {
66 r.delegation.SetUnDelegateAmount(safeAddInt64(r.delegation.UnDelegatedAmount(), amount))
67 r.delegation.SetCollectedAmount(safeAddInt64(r.delegation.CollectedAmount(), amount))
68}
69
70// processCollection handles the actual collection logic
71func (r *DelegationResolver) processCollection(currentTime int64) (int64, error) {
72 collectedAmount := int64(0)
73 withdraws := r.delegation.Withdraws()
74
75 for i := range withdraws {
76 resolver := NewDelegationWithdrawResolver(&withdraws[i])
77
78 collectableAmount := resolver.CollectableAmount(currentTime)
79 if collectableAmount <= 0 {
80 continue
81 }
82
83 err := resolver.Collect(collectableAmount, currentTime)
84 if err != nil {
85 return 0, err
86 }
87
88 updatedAmount, err := addToCollectedAmount(r.delegation.CollectedAmount(), collectableAmount)
89 if err != nil {
90 return 0, err
91 }
92
93 r.delegation.SetCollectedAmount(updatedAmount)
94 collectedAmount = safeAddInt64(collectedAmount, collectableAmount)
95 }
96
97 // Skip filtering if nothing was collected
98 if collectedAmount == 0 {
99 return collectedAmount, nil
100 }
101
102 currentIndex := 0
103
104 for i := range withdraws {
105 if !withdraws[i].IsCollected() {
106 r.delegation.SetWithdraw(currentIndex, withdraws[i])
107 currentIndex++
108 }
109 }
110
111 r.delegation.SetWithdraws(withdraws[:currentIndex])
112
113 return collectedAmount, nil
114}
115
116func addToCollectedAmount(collectedAmount, amount int64) (int64, error) {
117 if amount < 0 {
118 return 0, errors.New("amount must be non-negative")
119 }
120 return safeAddInt64(collectedAmount, amount), nil
121}
122
123// NewDelegation creates a new delegation.
124// This is a convenience wrapper around staker.NewDelegation.
125//
126// Parameters:
127// - id: delegation ID
128// - delegateFrom: delegator's address
129// - delegateTo: delegatee's address
130// - delegateAmount: amount to delegate
131// - createdHeight: creation block height
132// - createdAt: creation timestamp
133//
134// Returns:
135// - *staker.Delegation: new delegation instance
136func NewDelegation(
137 id int64,
138 delegateFrom, delegateTo address,
139 delegateAmount, createdHeight, createdAt int64,
140) *staker.Delegation {
141 return staker.NewDelegation(
142 id,
143 delegateFrom,
144 delegateTo,
145 delegateAmount,
146 createdHeight,
147 createdAt,
148 )
149}