github.com/cosmos/cosmos-sdk@v0.50.10/x/gov/types/v1/vote.go (about)

     1  package v1
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"cosmossdk.io/math"
     9  
    10  	sdk "github.com/cosmos/cosmos-sdk/types"
    11  )
    12  
    13  const (
    14  	OptionEmpty      = VoteOption_VOTE_OPTION_UNSPECIFIED
    15  	OptionYes        = VoteOption_VOTE_OPTION_YES
    16  	OptionNo         = VoteOption_VOTE_OPTION_NO
    17  	OptionNoWithVeto = VoteOption_VOTE_OPTION_NO_WITH_VETO
    18  	OptionAbstain    = VoteOption_VOTE_OPTION_ABSTAIN
    19  )
    20  
    21  // NewVote creates a new Vote instance
    22  func NewVote(proposalID uint64, voter sdk.AccAddress, options WeightedVoteOptions, metadata string) Vote {
    23  	return Vote{ProposalId: proposalID, Voter: voter.String(), Options: options, Metadata: metadata}
    24  }
    25  
    26  // Empty returns whether a vote is empty.
    27  func (v Vote) Empty() bool {
    28  	return v.ProposalId == 0 || v.Voter == "" || len(v.Options) == 0
    29  }
    30  
    31  // Votes is a collection of Vote objects
    32  type Votes []*Vote
    33  
    34  // Equal returns true if two slices (order-dependant) of votes are equal.
    35  func (v Votes) Equal(other Votes) bool {
    36  	if len(v) != len(other) {
    37  		return false
    38  	}
    39  
    40  	for i, vote := range v {
    41  		if vote.String() != other[i].String() {
    42  			return false
    43  		}
    44  	}
    45  
    46  	return true
    47  }
    48  
    49  // String implements stringer interface
    50  func (v Votes) String() string {
    51  	if len(v) == 0 {
    52  		return "[]"
    53  	}
    54  	out := fmt.Sprintf("Votes for Proposal %d:", v[0].ProposalId)
    55  	for _, vot := range v {
    56  		out += fmt.Sprintf("\n  %s: %s", vot.Voter, vot.Options)
    57  	}
    58  	return out
    59  }
    60  
    61  func NewWeightedVoteOption(option VoteOption, weight math.LegacyDec) *WeightedVoteOption {
    62  	return &WeightedVoteOption{Option: option, Weight: weight.String()}
    63  }
    64  
    65  // IsValid returns true if the sub vote is valid and false otherwise.
    66  func (w *WeightedVoteOption) IsValid() bool {
    67  	weight, err := math.LegacyNewDecFromStr(w.Weight)
    68  	if err != nil {
    69  		return false
    70  	}
    71  
    72  	if !weight.IsPositive() || weight.GT(math.LegacyNewDec(1)) {
    73  		return false
    74  	}
    75  
    76  	return ValidVoteOption(w.Option)
    77  }
    78  
    79  // NewNonSplitVoteOption creates a single option vote with weight 1
    80  func NewNonSplitVoteOption(option VoteOption) WeightedVoteOptions {
    81  	return WeightedVoteOptions{{option, math.LegacyNewDec(1).String()}}
    82  }
    83  
    84  // ValidWeightedVoteOption returns true if the sub vote is valid and false otherwise.
    85  func ValidWeightedVoteOption(option WeightedVoteOption) bool {
    86  	weight, err := math.LegacyNewDecFromStr(option.Weight)
    87  	if err != nil || !weight.IsPositive() || weight.GT(math.LegacyNewDec(1)) {
    88  		return false
    89  	}
    90  	return ValidVoteOption(option.Option)
    91  }
    92  
    93  // WeightedVoteOptions describes array of WeightedVoteOptions
    94  type WeightedVoteOptions []*WeightedVoteOption
    95  
    96  func (v WeightedVoteOptions) String() string {
    97  	out, _ := json.Marshal(v)
    98  	return string(out)
    99  }
   100  
   101  // VoteOptionFromString returns a VoteOption from a string. It returns an error
   102  // if the string is invalid.
   103  func VoteOptionFromString(str string) (VoteOption, error) {
   104  	option, ok := VoteOption_value[str]
   105  	if !ok {
   106  		return OptionEmpty, fmt.Errorf("'%s' is not a valid vote option, available options: yes/no/no_with_veto/abstain", str)
   107  	}
   108  	return VoteOption(option), nil
   109  }
   110  
   111  // WeightedVoteOptionsFromString returns weighted vote options from string. It returns an error
   112  // if the string is invalid.
   113  func WeightedVoteOptionsFromString(str string) (WeightedVoteOptions, error) {
   114  	options := WeightedVoteOptions{}
   115  	for _, option := range strings.Split(str, ",") {
   116  		fields := strings.Split(option, "=")
   117  		option, err := VoteOptionFromString(fields[0])
   118  		if err != nil {
   119  			return options, err
   120  		}
   121  		if len(fields) < 2 {
   122  			return options, fmt.Errorf("weight field does not exist for %s option", fields[0])
   123  		}
   124  		weight, err := math.LegacyNewDecFromStr(fields[1])
   125  		if err != nil {
   126  			return options, err
   127  		}
   128  		options = append(options, NewWeightedVoteOption(option, weight))
   129  	}
   130  	return options, nil
   131  }
   132  
   133  // ValidVoteOption returns true if the vote option is valid and false otherwise.
   134  func ValidVoteOption(option VoteOption) bool {
   135  	if option == OptionYes ||
   136  		option == OptionAbstain ||
   137  		option == OptionNo ||
   138  		option == OptionNoWithVeto {
   139  		return true
   140  	}
   141  	return false
   142  }
   143  
   144  // Format implements the fmt.Formatter interface.
   145  func (vo VoteOption) Format(s fmt.State, verb rune) {
   146  	switch verb {
   147  	case 's':
   148  		s.Write([]byte(vo.String()))
   149  	default:
   150  		s.Write([]byte(fmt.Sprintf("%v", byte(vo))))
   151  	}
   152  }