code.vegaprotocol.io/vega@v0.79.0/core/types/vesting.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package types 17 18 import ( 19 "fmt" 20 21 "code.vegaprotocol.io/vega/libs/num" 22 vgreflect "code.vegaprotocol.io/vega/libs/reflect" 23 proto "code.vegaprotocol.io/vega/protos/vega" 24 ) 25 26 type VestingBenefitTiers struct { 27 Tiers []*VestingBenefitTier 28 } 29 30 type VestingBenefitTier struct { 31 MinimumQuantumBalance *num.Uint 32 RewardMultiplier num.Decimal 33 } 34 35 func (a *VestingBenefitTiers) Clone() *VestingBenefitTiers { 36 out := &VestingBenefitTiers{} 37 38 for _, v := range a.Tiers { 39 out.Tiers = append(out.Tiers, &VestingBenefitTier{ 40 MinimumQuantumBalance: v.MinimumQuantumBalance.Clone(), 41 RewardMultiplier: v.RewardMultiplier, 42 }) 43 } 44 45 return out 46 } 47 48 func VestingBenefitTiersFromUntypedProto(v interface{}) (*VestingBenefitTiers, error) { 49 ptiers, err := toVestingBenefitTier(v) 50 if err != nil { 51 return nil, fmt.Errorf("couldn't convert untyped proto to VestingBenefitTiers proto: %w", err) 52 } 53 54 tiers, err := VestingBenefitTiersFromProto(ptiers) 55 if err != nil { 56 return nil, fmt.Errorf("couldn't build EthereumConfig: %w", err) 57 } 58 59 return tiers, nil 60 } 61 62 func VestingBenefitTiersFromProto(ptiers *proto.VestingBenefitTiers) (*VestingBenefitTiers, error) { 63 err := CheckVestingBenefitTiers(ptiers) 64 if err != nil { 65 return nil, err 66 } 67 68 tiers := &VestingBenefitTiers{} 69 for _, v := range ptiers.Tiers { 70 balance, _ := num.UintFromString(v.MinimumQuantumBalance, 10) 71 tiers.Tiers = append(tiers.Tiers, &VestingBenefitTier{ 72 MinimumQuantumBalance: balance, 73 RewardMultiplier: num.MustDecimalFromString(v.RewardMultiplier), 74 }) 75 } 76 77 return tiers, nil 78 } 79 80 func CheckUntypedVestingBenefitTier(v interface{}, _ interface{}) error { 81 tiers, err := toVestingBenefitTier(v) 82 if err != nil { 83 return err 84 } 85 86 return CheckVestingBenefitTiers(tiers) 87 } 88 89 // CheckEthereumConfig verifies the proto.EthereumConfig is valid. 90 func CheckVestingBenefitTiers(ptiers *proto.VestingBenefitTiers) error { 91 minQuantumVolumeSet := map[num.Uint]struct{}{} 92 93 for i, v := range ptiers.Tiers { 94 minQuantumBalance, underflow := num.UintFromString(v.MinimumQuantumBalance, 10) 95 if underflow { 96 return fmt.Errorf("invalid %d.minimum_quantum_balance", i) 97 } 98 if _, ok := minQuantumVolumeSet[*minQuantumBalance]; ok { 99 return fmt.Errorf("duplicate minimum_activity_streak entry for: %s", v.MinimumQuantumBalance) 100 } 101 minQuantumVolumeSet[*minQuantumBalance] = struct{}{} 102 103 if _, err := num.DecimalFromString(v.RewardMultiplier); err != nil { 104 return fmt.Errorf("%d.reward_multiplier, invalid decimal: %w", i, err) 105 } 106 } 107 108 return nil 109 } 110 111 func toVestingBenefitTier(v interface{}) (*proto.VestingBenefitTiers, error) { 112 cfg, ok := v.(*proto.VestingBenefitTiers) 113 if !ok { 114 return nil, fmt.Errorf("type \"%s\" is not a *VestingBenefitTiers proto", vgreflect.TypeName(v)) 115 } 116 117 return cfg, nil 118 }