Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}