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 }