github.com/KiraCore/sekai@v0.3.43/x/gov/keeper/poll.go (about) 1 package keeper 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "github.com/KiraCore/sekai/x/gov/types" 7 sdk "github.com/cosmos/cosmos-sdk/types" 8 "time" 9 ) 10 11 func (k Keeper) GetNextPollIDAndIncrement(ctx sdk.Context) uint64 { 12 pollID := k.GetNextPollID(ctx) 13 k.SetNextPollID(ctx, pollID+1) 14 return pollID 15 } 16 17 func (k Keeper) GetNextPollID(ctx sdk.Context) uint64 { 18 store := ctx.KVStore(k.storeKey) 19 20 bz := store.Get(NextPollIDPrefix) 21 if bz == nil { 22 return 1 23 } 24 25 pollID := sdk.BigEndianToUint64(bz) 26 return pollID 27 } 28 29 func (k Keeper) SetNextPollID(ctx sdk.Context, pollID uint64) { 30 store := ctx.KVStore(k.storeKey) 31 store.Set(NextPollIDPrefix, sdk.Uint64ToBigEndian(pollID)) 32 } 33 34 func (k Keeper) PollCreate(ctx sdk.Context, msg *types.MsgPollCreate) (uint64, error) { 35 var roles []uint64 36 pollID := k.GetNextPollIDAndIncrement(ctx) 37 options := new(types.PollOptions) 38 39 options.Type = msg.ValueType 40 options.Count = msg.ValueCount 41 options.Choices = msg.PossibleChoices 42 43 duration, err := time.ParseDuration(msg.Duration) 44 if err != nil { 45 return pollID, fmt.Errorf("invalid duration: %w", err) 46 } 47 48 for _, v := range msg.PollValues { 49 options.Values = append(options.Values, v) 50 } 51 52 for _, sid := range msg.Roles { 53 role, _ := k.GetRoleBySid(ctx, sid) 54 roles = append(roles, uint64(role.Id)) 55 } 56 57 poll, err := types.NewPoll( 58 pollID, 59 msg.Creator, 60 msg.Title, 61 msg.Description, 62 msg.Reference, 63 msg.Checksum, 64 roles, 65 options, 66 time.Now().Add(duration), 67 ) 68 69 if err != nil { 70 return pollID, err 71 } 72 73 k.SavePoll(ctx, poll) 74 k.AddAddressPoll(ctx, poll) 75 k.AddToActivePolls(ctx, poll) 76 77 return pollID, nil 78 } 79 80 func (k Keeper) SavePoll(ctx sdk.Context, poll types.Poll) { 81 store := ctx.KVStore(k.storeKey) 82 key := append(PollPrefix, sdk.Uint64ToBigEndian(poll.PollId)...) 83 store.Set(key, k.cdc.MustMarshal(&poll)) 84 } 85 86 func (k Keeper) AddAddressPoll(ctx sdk.Context, poll types.Poll) { 87 store := ctx.KVStore(k.storeKey) 88 addressKey := append(PollPrefix, poll.Creator.Bytes()...) 89 key := append(addressKey, sdk.Uint64ToBigEndian(poll.PollId)...) 90 store.Set(key, sdk.Uint64ToBigEndian(poll.PollId)) 91 } 92 93 func (k Keeper) AddToActivePolls(ctx sdk.Context, poll types.Poll) { 94 store := ctx.KVStore(k.storeKey) 95 key := append(PollsByTimeKey(poll.VotingEndTime), sdk.Uint64ToBigEndian(poll.PollId)...) 96 store.Set(key, sdk.Uint64ToBigEndian(poll.PollId)) 97 } 98 99 func (k Keeper) RemoveActivePoll(ctx sdk.Context, poll types.Poll) { 100 store := ctx.KVStore(k.storeKey) 101 key := append(PollsByTimeKey(poll.VotingEndTime), sdk.Uint64ToBigEndian(poll.PollId)...) 102 store.Delete(key) 103 } 104 105 func (k Keeper) PollVote(ctx sdk.Context, msg *types.MsgPollVote) error { 106 vote := types.PollVote{ 107 Voter: msg.Voter, 108 PollId: msg.PollId, 109 Option: msg.Option, 110 CustomValue: msg.Value, 111 } 112 113 store := ctx.KVStore(k.storeKey) 114 bz := k.cdc.MustMarshal(&vote) 115 store.Set(PollVoteKey(vote.PollId, vote.Voter), bz) 116 117 return nil 118 } 119 120 func (k Keeper) GetPoll(ctx sdk.Context, pollID uint64) (types.Poll, error) { 121 store := ctx.KVStore(k.storeKey) 122 bz := store.Get(append(PollPrefix, sdk.Uint64ToBigEndian(pollID)...)) 123 124 if bz == nil { 125 return types.Poll{}, types.ErrPollsNotFount 126 } 127 128 var poll types.Poll 129 k.cdc.MustUnmarshal(bz, &poll) 130 131 return poll, nil 132 } 133 134 func (k Keeper) GetPollsIdsByAddress(ctx sdk.Context, address sdk.AccAddress) []uint64 { 135 var ids []uint64 136 store := ctx.KVStore(k.storeKey) 137 addressKey := append(PollPrefix, address.Bytes()...) 138 iterator := sdk.KVStorePrefixIterator(store, addressKey) 139 defer iterator.Close() 140 141 for ; iterator.Valid(); iterator.Next() { 142 id := binary.BigEndian.Uint64(iterator.Value()) 143 ids = append(ids, id) 144 } 145 146 return ids 147 } 148 149 func (k Keeper) GetPollsByAddress(ctx sdk.Context, address sdk.AccAddress) ([]types.Poll, error) { 150 ids := k.GetPollsIdsByAddress(ctx, address) 151 var polls []types.Poll 152 153 for _, v := range ids { 154 poll, err := k.GetPoll(ctx, v) 155 if err != nil { 156 return nil, err 157 } 158 polls = append(polls, poll) 159 } 160 161 return polls, nil 162 } 163 164 func (k Keeper) GetPollVotes(ctx sdk.Context, pollID uint64) types.PollVotes { 165 var votes types.PollVotes 166 167 iterator := k.GetPollVotesIterator(ctx, pollID) 168 defer iterator.Close() 169 for ; iterator.Valid(); iterator.Next() { 170 var vote types.PollVote 171 k.cdc.MustUnmarshal(iterator.Value(), &vote) 172 votes = append(votes, vote) 173 } 174 175 return votes 176 } 177 178 func (k Keeper) GetPollVotesIterator(ctx sdk.Context, pollID uint64) sdk.Iterator { 179 store := ctx.KVStore(k.storeKey) 180 return sdk.KVStorePrefixIterator(store, PollVotesKey(pollID)) 181 } 182 183 func (k Keeper) GetPollsWithFinishedVotingEndTimeIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator { 184 store := ctx.KVStore(k.storeKey) 185 return store.Iterator(ActivePollPrefix, sdk.PrefixEndBytes(PollsByTimeKey(endTime))) 186 } 187 188 func PollsByTimeKey(endTime time.Time) []byte { 189 return append(ActivePollPrefix, sdk.FormatTimeBytes(endTime)...) 190 } 191 192 func PollVotesKey(pollId uint64) []byte { 193 return append(PollVotesPrefix, sdk.Uint64ToBigEndian(pollId)...) 194 } 195 196 func PollVoteKey(pollId uint64, address sdk.AccAddress) []byte { 197 return append(PollVotesKey(pollId), address.Bytes()...) 198 }