-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
vote.go
150 lines (127 loc) · 3.71 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
142
143
144
145
146
147
148
149
150
package types
import (
"encoding/json"
"fmt"
"strings"
yaml "gopkg.in/yaml.v2"
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}
}
func (v Vote) String() string {
out, _ := yaml.Marshal(v)
return string(out)
}
// Votes is a collection of Vote objects
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
}
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
}
// Empty returns whether a vote is empty.
func (v Vote) Empty() bool {
return v.String() == Vote{}.String()
}
// NewNonSplitVoteOption creates a single option vote with weight 1
func NewNonSplitVoteOption(option VoteOption) WeightedVoteOptions {
return WeightedVoteOptions{{option, sdk.NewDec(1)}}
}
func (v WeightedVoteOption) String() string {
out, _ := json.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(sdk.NewDec(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
}
// Marshal needed for protobuf compatibility.
func (vo VoteOption) Marshal() ([]byte, error) {
return []byte{byte(vo)}, nil
}
// Unmarshal needed for protobuf compatibility.
func (vo *VoteOption) Unmarshal(data []byte) error {
*vo = VoteOption(data[0])
return nil
}
// 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))))
}
}