store.gno
8.30 Kb ยท 336 lines
1package governance
2
3import (
4 "errors"
5 "strconv"
6
7 "gno.land/p/gnoswap/store"
8 "gno.land/p/nt/avl"
9 "gno.land/p/nt/ufmt"
10)
11
12type StoreKey string
13
14func (s StoreKey) String() string {
15 return string(s)
16}
17
18const (
19 StoreKeyConfigCounter StoreKey = "configCounter" // Config version counter
20 StoreKeyProposalCounter StoreKey = "proposalCounter" // Proposal ID counter
21
22 StoreKeyConfigs StoreKey = "configs" // Configurations AVL tree
23
24 StoreKeyProposals StoreKey = "proposals" // Proposals AVL tree
25
26 StoreKeyProposalUserVotingInfos StoreKey = "proposalUserVotingInfos" // Proposal voting infos AVL tree
27
28 StoreKeyUserProposals StoreKey = "userProposals" // User proposals mapping AVL tree
29)
30
31type governanceStore struct {
32 kvStore store.KVStore
33}
34
35// Counter methods
36func (s *governanceStore) HasConfigCounterStoreKey() bool {
37 return s.kvStore.Has(StoreKeyConfigCounter.String())
38}
39
40func (s *governanceStore) GetConfigCounter() *Counter {
41 result, err := s.kvStore.Get(StoreKeyConfigCounter.String())
42 if err != nil {
43 panic(err)
44 }
45
46 counter, ok := result.(*Counter)
47 if !ok {
48 panic(ufmt.Sprintf("failed to cast result to *Counter: %T", result))
49 }
50
51 return counter
52}
53
54func (s *governanceStore) SetConfigCounter(counter *Counter) error {
55 return s.kvStore.Set(StoreKeyConfigCounter.String(), counter)
56}
57
58func (s *governanceStore) HasProposalCounterStoreKey() bool {
59 return s.kvStore.Has(StoreKeyProposalCounter.String())
60}
61
62func (s *governanceStore) GetProposalCounter() *Counter {
63 result, err := s.kvStore.Get(StoreKeyProposalCounter.String())
64 if err != nil {
65 panic(err)
66 }
67
68 counter, ok := result.(*Counter)
69 if !ok {
70 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
71 }
72
73 return counter
74}
75
76func (s *governanceStore) SetProposalCounter(counter *Counter) error {
77 return s.kvStore.Set(StoreKeyProposalCounter.String(), counter)
78}
79
80// Configs methods
81func (s *governanceStore) HasConfigsStoreKey() bool {
82 return s.kvStore.Has(StoreKeyConfigs.String())
83}
84
85func (s *governanceStore) GetConfigs() *avl.Tree {
86 result, err := s.kvStore.Get(StoreKeyConfigs.String())
87 if err != nil {
88 panic(err)
89 }
90
91 configs, ok := result.(*avl.Tree)
92 if !ok {
93 panic(ufmt.Sprintf("failed to cast result to *avl.Tree: %T", result))
94 }
95
96 return configs
97}
98
99func (s *governanceStore) SetConfigs(configs *avl.Tree) error {
100 return s.kvStore.Set(StoreKeyConfigs.String(), configs)
101}
102
103func (s *governanceStore) GetConfig(version int64) (Config, bool) {
104 configs := s.GetConfigs()
105 result, ok := configs.Get(formatInt64Key(version))
106 if !ok {
107 return Config{}, false
108 }
109
110 config, ok := result.(Config)
111 if !ok {
112 panic(ufmt.Sprintf("failed to cast result to Config: %T", result))
113 }
114
115 return config, true
116}
117
118func (s *governanceStore) SetConfig(version int64, config Config) error {
119 if !s.HasConfigsStoreKey() {
120 return errors.New("configs store key not found")
121 }
122
123 configs := s.GetConfigs()
124 configs.Set(formatInt64Key(version), config)
125
126 return s.kvStore.Set(StoreKeyConfigs.String(), configs)
127}
128
129// Proposals methods
130func (s *governanceStore) HasProposalsStoreKey() bool {
131 return s.kvStore.Has(StoreKeyProposals.String())
132}
133
134func (s *governanceStore) GetProposals() *avl.Tree {
135 result, err := s.kvStore.Get(StoreKeyProposals.String())
136 if err != nil {
137 panic(err)
138 }
139
140 proposals, ok := result.(*avl.Tree)
141 if !ok {
142 panic(ufmt.Sprintf("failed to cast result to *avl.Tree: %T", result))
143 }
144
145 return proposals
146}
147
148func (s *governanceStore) SetProposals(proposals *avl.Tree) error {
149 return s.kvStore.Set(StoreKeyProposals.String(), proposals)
150}
151
152func (s *governanceStore) GetProposal(proposalID int64) (*Proposal, bool) {
153 proposals := s.GetProposals()
154 result, ok := proposals.Get(formatInt64Key(proposalID))
155 if !ok {
156 return nil, false
157 }
158
159 proposal, ok := result.(*Proposal)
160 if !ok {
161 return nil, false
162 }
163 return proposal, true
164}
165
166func (s *governanceStore) SetProposal(proposalID int64, proposal *Proposal) error {
167 if !s.HasProposalsStoreKey() {
168 return errors.New("proposals store key not found")
169 }
170
171 proposals := s.GetProposals()
172 proposals.Set(formatInt64Key(proposalID), proposal)
173
174 return s.kvStore.Set(StoreKeyProposals.String(), proposals)
175}
176
177// Proposal User Voting Infos methods
178func (s *governanceStore) HasProposalUserVotingInfosStoreKey() bool {
179 return s.kvStore.Has(StoreKeyProposalUserVotingInfos.String())
180}
181
182func (s *governanceStore) GetProposalUserVotingInfos() *avl.Tree {
183 result, err := s.kvStore.Get(StoreKeyProposalUserVotingInfos.String())
184 if err != nil {
185 panic(err)
186 }
187
188 votingInfos, ok := result.(*avl.Tree)
189 if !ok {
190 panic(ufmt.Sprintf("failed to cast result to *avl.Tree: %T", result))
191 }
192
193 return votingInfos
194}
195
196func (s *governanceStore) SetProposalUserVotingInfos(votingInfos *avl.Tree) error {
197 return s.kvStore.Set(StoreKeyProposalUserVotingInfos.String(), votingInfos)
198}
199
200func (s *governanceStore) GetProposalVotingInfos(proposalID int64) (*avl.Tree, bool) {
201 votingInfos := s.GetProposalUserVotingInfos()
202 votingInfo, ok := votingInfos.Get(formatInt64Key(proposalID))
203 if !ok {
204 return nil, false
205 }
206
207 votingInfoTree, ok := votingInfo.(*avl.Tree)
208 if !ok {
209 return nil, false
210 }
211
212 return votingInfoTree, true
213}
214
215func (s *governanceStore) SetProposalVotingInfos(proposalID int64, votingInfos *avl.Tree) error {
216 if !s.HasProposalUserVotingInfosStoreKey() {
217 return errors.New("proposal user voting infos store key not found")
218 }
219
220 allVotingInfos := s.GetProposalUserVotingInfos()
221 allVotingInfos.Set(formatInt64Key(proposalID), votingInfos)
222
223 return s.kvStore.Set(StoreKeyProposalUserVotingInfos.String(), allVotingInfos)
224}
225
226// User Proposals methods
227func (s *governanceStore) HasUserProposalsStoreKey() bool {
228 return s.kvStore.Has(StoreKeyUserProposals.String())
229}
230
231func (s *governanceStore) GetUserProposals() *avl.Tree {
232 result, err := s.kvStore.Get(StoreKeyUserProposals.String())
233 if err != nil {
234 panic(err)
235 }
236
237 userProposals, ok := result.(*avl.Tree)
238 if !ok {
239 panic(ufmt.Sprintf("failed to cast result to *avl.Tree: %T", result))
240 }
241
242 return userProposals
243}
244
245func (s *governanceStore) SetUserProposals(userProposals *avl.Tree) error {
246 return s.kvStore.Set(StoreKeyUserProposals.String(), userProposals)
247}
248
249func (s *governanceStore) GetUserProposalsTree() *avl.Tree {
250 return s.GetUserProposals()
251}
252
253func (s *governanceStore) GetUserProposalIDs(user string) ([]int64, bool) {
254 userProposals := s.GetUserProposals()
255 result, ok := userProposals.Get(user)
256 if !ok {
257 return nil, false
258 }
259
260 proposalIDs, ok := result.([]int64)
261 if !ok {
262 panic(ufmt.Sprintf("failed to cast result to []int64: %T", result))
263 }
264
265 return proposalIDs, true
266}
267
268func (s *governanceStore) AddUserProposal(user string, proposalID int64) error {
269 if !s.HasUserProposalsStoreKey() {
270 return errors.New("user proposals store key not found")
271 }
272
273 userProposals := s.GetUserProposals()
274
275 // Get existing proposals for user
276 var proposalIDs []int64
277 if existing, ok := userProposals.Get(user); ok {
278 proposalIDs, ok = existing.([]int64)
279 if !ok {
280 panic(ufmt.Sprintf("failed to cast result to []int64: %T", existing))
281 }
282 }
283
284 // Add new proposal ID
285 proposalIDs = append(proposalIDs, proposalID)
286 userProposals.Set(user, proposalIDs)
287
288 return s.kvStore.Set(StoreKeyUserProposals.String(), userProposals)
289}
290
291func (s *governanceStore) RemoveUserProposal(user string, proposalID int64) error {
292 if !s.HasUserProposalsStoreKey() {
293 return errors.New("user proposals store key not found")
294 }
295
296 userProposals := s.GetUserProposals()
297 proposalIDsRaw, ok := userProposals.Get(user)
298 // proposal already removed
299 if !ok {
300 return nil
301 }
302
303 proposalIDs, ok := proposalIDsRaw.([]int64)
304 if !ok {
305 panic(ufmt.Sprintf("failed to cast result to []int64: %T", proposalIDs))
306 }
307
308 newProposalIDs := make([]int64, 0)
309
310 for _, id := range proposalIDs {
311 if id != proposalID {
312 newProposalIDs = append(newProposalIDs, id)
313 }
314 }
315
316 if len(newProposalIDs) == 0 {
317 userProposals.Remove(user)
318 } else {
319 userProposals.Set(user, newProposalIDs)
320 }
321
322 return s.kvStore.Set(StoreKeyUserProposals.String(), userProposals)
323}
324
325// NewGovernanceStore creates a new governance store instance with the provided KV store.
326// This function is used by the upgrade system to create storage instances for each implementation.
327func NewGovernanceStore(kvStore store.KVStore) IGovernanceStore {
328 return &governanceStore{
329 kvStore: kvStore,
330 }
331}
332
333// formatInt64Key formats int64 identifiers for storage keys.
334func formatInt64Key(id int64) string {
335 return strconv.FormatInt(id, 10)
336}