/
vote.go
141 lines (120 loc) · 3.54 KB
/
vote.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
140
141
package v1beta1
import (
"fmt"
"strings"
"cosmossdk.io/math"
"sigs.k8s.io/yaml"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// NewVote creates a new Vote instance
//
//nolint:interfacer
func NewVote(proposalID uint64, voter sdk.AccAddress, options WeightedVoteOptions) Vote {
return Vote{ProposalId: proposalID, Voter: voter.String(), Options: options}
}
// String returns the string representation of the vote
func (v Vote) String() string {
out, _ := yaml.Marshal(v)
return string(out)
}
// Empty returns whether a vote is empty.
func (v Vote) Empty() bool {
return v.String() == Vote{}.String()
}
// Votes is an array of vote
type Votes []Vote
// Equal returns true if two slices (order-dependant) of votes are equal.
func (v Votes) Equal(other Votes) bool {
if len(v) != len(other) {
return false
}
for i, vote := range v {
if vote.String() != other[i].String() {
return false
}
}
return true
}
// String implements stringer interface
func (v Votes) String() string {
if len(v) == 0 {
return "[]"
}
out := fmt.Sprintf("Votes for Proposal %d:", v[0].ProposalId)
for _, vot := range v {
out += fmt.Sprintf("\n %s: %s", vot.Voter, vot.Options)
}
return out
}
// NewNonSplitVoteOption creates a single option vote with weight 1
func NewNonSplitVoteOption(option VoteOption) WeightedVoteOptions {
return WeightedVoteOptions{{option, math.LegacyNewDec(1)}}
}
func (v WeightedVoteOption) String() string {
out, _ := yaml.Marshal(v)
return string(out)
}
// WeightedVoteOptions describes array of WeightedVoteOptions
type WeightedVoteOptions []WeightedVoteOption
func (v WeightedVoteOptions) String() (out string) {
for _, opt := range v {
out += opt.String() + "\n"
}
return strings.TrimSpace(out)
}
// ValidWeightedVoteOption returns true if the sub vote is valid and false otherwise.
func ValidWeightedVoteOption(option WeightedVoteOption) bool {
if !option.Weight.IsPositive() || option.Weight.GT(math.LegacyNewDec(1)) {
return false
}
return ValidVoteOption(option.Option)
}
// VoteOptionFromString returns a VoteOption from a string. It returns an error
// if the string is invalid.
func VoteOptionFromString(str string) (VoteOption, error) {
option, ok := VoteOption_value[str]
if !ok {
return OptionEmpty, fmt.Errorf("'%s' is not a valid vote option, available options: yes/no/no_with_veto/abstain", str)
}
return VoteOption(option), nil
}
// WeightedVoteOptionsFromString returns weighted vote options from string. It returns an error
// if the string is invalid.
func WeightedVoteOptionsFromString(str string) (WeightedVoteOptions, error) {
options := WeightedVoteOptions{}
for _, option := range strings.Split(str, ",") {
fields := strings.Split(option, "=")
option, err := VoteOptionFromString(fields[0])
if err != nil {
return options, err
}
if len(fields) < 2 {
return options, fmt.Errorf("weight field does not exist for %s option", fields[0])
}
weight, err := sdk.NewDecFromStr(fields[1])
if err != nil {
return options, err
}
options = append(options, WeightedVoteOption{option, weight})
}
return options, nil
}
// ValidVoteOption returns true if the vote option is valid and false otherwise.
func ValidVoteOption(option VoteOption) bool {
if option == OptionYes ||
option == OptionAbstain ||
option == OptionNo ||
option == OptionNoWithVeto {
return true
}
return false
}
// Format implements the fmt.Formatter interface.
func (vo VoteOption) Format(s fmt.State, verb rune) {
switch verb {
case 's':
s.Write([]byte(vo.String()))
default:
s.Write([]byte(fmt.Sprintf("%v", byte(vo))))
}
}