-
Notifications
You must be signed in to change notification settings - Fork 367
/
multipliers.go
139 lines (122 loc) · 3.6 KB
/
multipliers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package types
import (
"fmt"
"sort"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// NewMultiplier returns a new Multiplier
func NewMultiplier(name string, lockup int64, factor sdk.Dec) Multiplier {
return Multiplier{
Name: name,
MonthsLockup: lockup,
Factor: factor,
}
}
// Validate multiplier param
func (m Multiplier) Validate() error {
if m.Name == "" {
return fmt.Errorf("expected non empty name")
}
if m.MonthsLockup < 0 {
return fmt.Errorf("expected non-negative lockup, got %d", m.MonthsLockup)
}
if m.Factor.IsNegative() {
return fmt.Errorf("expected non-negative factor, got %s", m.Factor.String())
}
return nil
}
// Multipliers is a slice of Multiplier
type Multipliers []Multiplier
// Validate validates each multiplier
func (ms Multipliers) Validate() error {
for _, m := range ms {
if err := m.Validate(); err != nil {
return err
}
}
return nil
}
// Get returns a multiplier with a matching name
func (ms Multipliers) Get(name string) (Multiplier, bool) {
for _, m := range ms {
if m.Name == name {
return m, true
}
}
return Multiplier{}, false
}
// MultipliersPerDenoms is a slice of MultipliersPerDenom
type MultipliersPerDenoms []MultipliersPerDenom
// Validate checks each denom and multipliers for invalid values.
func (mpd MultipliersPerDenoms) Validate() error {
foundDenoms := map[string]bool{}
for _, item := range mpd {
if err := sdk.ValidateDenom(item.Denom); err != nil {
return err
}
if err := item.Multipliers.Validate(); err != nil {
return err
}
if foundDenoms[item.Denom] {
return fmt.Errorf("duplicate denom %s", item.Denom)
}
foundDenoms[item.Denom] = true
}
return nil
}
// NewSelection returns a new Selection
func NewSelection(denom, multiplierName string) Selection {
return Selection{
Denom: denom,
MultiplierName: multiplierName,
}
}
// Validate performs basic validation checks
func (s Selection) Validate() error {
if err := sdk.ValidateDenom(s.Denom); err != nil {
return sdkerrors.Wrap(ErrInvalidClaimDenoms, err.Error())
}
if s.MultiplierName == "" {
return sdkerrors.Wrap(ErrInvalidMultiplier, "multiplier name cannot be empty")
}
return nil
}
// Selections are a list of denom - multiplier pairs that specify what rewards to claim and with what lockups.
type Selections []Selection
// NewSelectionsFromMap creates a new set of selections from a string to string map.
// It sorts the output before returning.
func NewSelectionsFromMap(selectionMap map[string]string) Selections {
var selections Selections
for k, v := range selectionMap {
selections = append(selections, NewSelection(k, v))
}
// deterministically sort the slice to protect against the random range order causing consensus failures
sort.Slice(selections, func(i, j int) bool {
if selections[i].Denom != selections[j].Denom {
return selections[i].Denom < selections[j].Denom
}
return selections[i].MultiplierName < selections[j].MultiplierName
})
return selections
}
// Valdate performs basic validaton checks
func (ss Selections) Validate() error {
if len(ss) == 0 {
return sdkerrors.Wrap(ErrInvalidClaimDenoms, "cannot claim 0 denoms")
}
if len(ss) >= MaxDenomsToClaim {
return sdkerrors.Wrapf(ErrInvalidClaimDenoms, "cannot claim more than %d denoms", MaxDenomsToClaim)
}
foundDenoms := map[string]bool{}
for _, s := range ss {
if err := s.Validate(); err != nil {
return err
}
if foundDenoms[s.Denom] {
return sdkerrors.Wrapf(ErrInvalidClaimDenoms, "cannot claim denom '%s' more than once", s.Denom)
}
foundDenoms[s.Denom] = true
}
return nil
}