Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}