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  }