store.gno
10.04 Kb · 340 lines
1package pool
2
3import (
4 "errors"
5 "gno.land/p/gnoswap/store"
6 bptree "gno.land/p/nt/bptree/v0"
7 ufmt "gno.land/p/nt/ufmt/v0"
8)
9
10// StoreKey defines the keys used for storing pool data in the KV store.
11// These keys are prefixed with the domain address to ensure namespace isolation.
12type StoreKey string
13
14func (s StoreKey) String() string {
15 return string(s)
16}
17
18const (
19 // Pool data storage keys
20 StoreKeyPools StoreKey = "pools" // Map containing all pools
21 StoreKeyFeeAmountTickSpacing StoreKey = "feeAmountTickSpacing" // Fee tier to tick spacing mapping
22 StoreKeySlot0FeeProtocol StoreKey = "slot0FeeProtocol" // Protocol fee percentage
23
24 // Protocol fee storage keys
25 StoreKeyPoolCreationFee StoreKey = "poolCreationFee" // Pool creation fee amount
26 StoreKeyPendingProtocolFees StoreKey = "pendingProtocolFees" // tokenPath -> amount held locally for protocol_fee
27 StoreKeyWithdrawalFeeBPS StoreKey = "withdrawalFeeBPS" // Withdrawal fee in basis points
28 StoreKeyUnlocked StoreKey = "unlocked" // Global pool reentrancy lock
29
30 // Swap hook storage keys
31 StoreKeySwapStartHook StoreKey = "swapStartHook" // Swap start hook function
32 StoreKeySwapEndHook StoreKey = "swapEndHook" // Swap end hook function
33 StoreKeyTickCrossHook StoreKey = "tickCrossHook" // Tick cross hook function
34)
35
36// poolStore implements the IPoolStore interface for pool domain storage.
37// It provides type-safe access to pool data stored in the underlying KV store.
38type poolStore struct {
39 kvStore store.KVStore
40}
41
42func (s *poolStore) HasPools() bool {
43 return s.kvStore.Has(StoreKeyPools.String())
44}
45
46// GetPools retrieves the map containing all pool data.
47// This is the main data structure that stores all pool instances.
48func (s *poolStore) GetPools() *bptree.BPTree {
49 pools, err := s.kvStore.GetBPTree(StoreKeyPools.String())
50 if err != nil {
51 panic(err)
52 }
53
54 if pools == nil {
55 panic("pools is nil")
56 }
57
58 return pools
59}
60
61// SetPools stores the map containing all pool data.
62func (s *poolStore) SetPools(_ int, rlm realm, pools *bptree.BPTree) error {
63 if !rlm.IsCurrent() {
64 return errors.New(ErrSpoofedRealm)
65 }
66
67 if pools == nil {
68 panic("pools is nil")
69 }
70
71 return s.kvStore.Set(0, rlm, StoreKeyPools.String(), pools)
72}
73
74func (s *poolStore) HasFeeAmountTickSpacing() bool {
75 return s.kvStore.Has(StoreKeyFeeAmountTickSpacing.String())
76}
77
78// GetFeeAmountTickSpacing retrieves the mapping between fee amounts and tick spacing.
79// This mapping determines the tick spacing for each supported fee tier.
80func (s *poolStore) GetFeeAmountTickSpacing() map[uint32]int32 {
81 result, err := s.kvStore.Get(StoreKeyFeeAmountTickSpacing.String())
82 if err != nil {
83 panic(err)
84 }
85
86 feeAmountTickSpacing, ok := result.(map[uint32]int32)
87 if !ok {
88 panic(ufmt.Sprintf("failed to cast result to map[uint32]int32: %T", result))
89 }
90
91 if feeAmountTickSpacing == nil {
92 panic("feeAmountTickSpacing is nil")
93 }
94
95 return cloneFeeAmountTickSpacings(feeAmountTickSpacing)
96}
97
98// SetFeeAmountTickSpacing stores the mapping between fee amounts and tick spacing.
99func (s *poolStore) SetFeeAmountTickSpacing(_ int, rlm realm, feeAmountTickSpacing map[uint32]int32) error {
100 if !rlm.IsCurrent() {
101 return errors.New(ErrSpoofedRealm)
102 }
103
104 if feeAmountTickSpacing == nil {
105 panic("feeAmountTickSpacing is nil")
106 }
107
108 return s.kvStore.Set(0, rlm, StoreKeyFeeAmountTickSpacing.String(), feeAmountTickSpacing)
109}
110
111func (s *poolStore) HasSlot0FeeProtocol() bool {
112 return s.kvStore.Has(StoreKeySlot0FeeProtocol.String())
113}
114
115// GetSlot0FeeProtocol retrieves the protocol fee percentage for slot0.
116func (s *poolStore) GetSlot0FeeProtocol() uint8 {
117 result, err := s.kvStore.Get(StoreKeySlot0FeeProtocol.String())
118 if err != nil {
119 panic(err)
120 }
121
122 slot0FeeProtocol, ok := result.(uint8)
123 if !ok {
124 panic(ufmt.Sprintf("failed to cast result to uint8: %T", result))
125 }
126
127 return slot0FeeProtocol
128}
129
130// SetSlot0FeeProtocol stores the protocol fee percentage for slot0.
131func (s *poolStore) SetSlot0FeeProtocol(_ int, rlm realm, slot0FeeProtocol uint8) error {
132 if !rlm.IsCurrent() {
133 return errors.New(ErrSpoofedRealm)
134 }
135
136 return s.kvStore.Set(0, rlm, StoreKeySlot0FeeProtocol.String(), slot0FeeProtocol)
137}
138
139func (s *poolStore) HasPoolCreationFee() bool {
140 return s.kvStore.Has(StoreKeyPoolCreationFee.String())
141}
142
143// GetPoolCreationFee retrieves the pool creation fee amount.
144func (s *poolStore) GetPoolCreationFee() int64 {
145 result, err := s.kvStore.Get(StoreKeyPoolCreationFee.String())
146 if err != nil {
147 panic(err)
148 }
149
150 poolCreationFee, ok := result.(int64)
151 if !ok {
152 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
153 }
154
155 return poolCreationFee
156}
157
158// SetPoolCreationFee stores the pool creation fee amount.
159func (s *poolStore) SetPoolCreationFee(_ int, rlm realm, poolCreationFee int64) error {
160 if !rlm.IsCurrent() {
161 return errors.New(ErrSpoofedRealm)
162 }
163
164 return s.kvStore.Set(0, rlm, StoreKeyPoolCreationFee.String(), poolCreationFee)
165}
166
167func (s *poolStore) HasPendingProtocolFees() bool {
168 return s.kvStore.Has(StoreKeyPendingProtocolFees.String())
169}
170
171func (s *poolStore) GetPendingProtocolFees() map[string]int64 {
172 result, err := s.kvStore.Get(StoreKeyPendingProtocolFees.String())
173 if err != nil {
174 panic(err)
175 }
176
177 pendingProtocolFees, ok := result.(map[string]int64)
178 if !ok {
179 panic(ufmt.Sprintf("failed to cast result to map[string]int64: %T", result))
180 }
181
182 return cloneStringInt64Map(pendingProtocolFees)
183}
184
185func (s *poolStore) SetPendingProtocolFees(_ int, rlm realm, pendingProtocolFees map[string]int64) error {
186 if !rlm.IsCurrent() {
187 return errors.New(ErrSpoofedRealm)
188 }
189
190 return s.kvStore.Set(0, rlm, StoreKeyPendingProtocolFees.String(), pendingProtocolFees)
191}
192
193func (s *poolStore) HasWithdrawalFeeBPS() bool {
194 return s.kvStore.Has(StoreKeyWithdrawalFeeBPS.String())
195}
196
197// GetWithdrawalFeeBPS retrieves the withdrawal fee in basis points.
198func (s *poolStore) GetWithdrawalFeeBPS() uint64 {
199 result, err := s.kvStore.Get(StoreKeyWithdrawalFeeBPS.String())
200 if err != nil {
201 panic(err)
202 }
203
204 withdrawalFeeBPS, ok := result.(uint64)
205 if !ok {
206 panic(ufmt.Sprintf("failed to cast result to uint64: %T", result))
207 }
208
209 return withdrawalFeeBPS
210}
211
212// SetWithdrawalFeeBPS stores the withdrawal fee in basis points.
213func (s *poolStore) SetWithdrawalFeeBPS(_ int, rlm realm, withdrawalFeeBPS uint64) error {
214 if !rlm.IsCurrent() {
215 return errors.New(ErrSpoofedRealm)
216 }
217
218 return s.kvStore.Set(0, rlm, StoreKeyWithdrawalFeeBPS.String(), withdrawalFeeBPS)
219}
220
221func (s *poolStore) HasUnlocked() bool {
222 return s.kvStore.Has(StoreKeyUnlocked.String())
223}
224
225func (s *poolStore) GetUnlocked() bool {
226 result, err := s.kvStore.Get(StoreKeyUnlocked.String())
227 if err != nil {
228 panic(err)
229 }
230
231 unlocked, ok := result.(bool)
232 if !ok {
233 panic(ufmt.Sprintf("failed to cast result to bool: %T", result))
234 }
235
236 return unlocked
237}
238
239func (s *poolStore) SetUnlocked(_ int, rlm realm, unlocked bool) error {
240 if !rlm.IsCurrent() {
241 return errors.New(ErrSpoofedRealm)
242 }
243
244 return s.kvStore.Set(0, rlm, StoreKeyUnlocked.String(), unlocked)
245}
246
247// HasSwapStartHook checks if the swap start hook is set.
248func (s *poolStore) HasSwapStartHook() bool {
249 return s.kvStore.Has(StoreKeySwapStartHook.String())
250}
251
252// GetSwapStartHook retrieves the swap start hook function.
253func (s *poolStore) GetSwapStartHook() func(cur realm, poolPath string, timestamp int64) {
254 result, err := s.kvStore.Get(StoreKeySwapStartHook.String())
255 if err != nil {
256 panic(err)
257 }
258
259 swapStartHook, ok := result.(func(cur realm, poolPath string, timestamp int64))
260 if !ok {
261 panic(ufmt.Sprintf("failed to cast result to func(poolPath string, timestamp int64): %T", result))
262 }
263
264 return swapStartHook
265}
266
267// SetSwapStartHook stores the swap start hook function.
268func (s *poolStore) SetSwapStartHook(_ int, rlm realm, swapStartHook func(cur realm, poolPath string, timestamp int64)) error {
269 if !rlm.IsCurrent() {
270 return errors.New(ErrSpoofedRealm)
271 }
272
273 return s.kvStore.Set(0, rlm, StoreKeySwapStartHook.String(), swapStartHook)
274}
275
276// HasSwapEndHook checks if the swap end hook is set.
277func (s *poolStore) HasSwapEndHook() bool {
278 return s.kvStore.Has(StoreKeySwapEndHook.String())
279}
280
281// GetSwapEndHook retrieves the swap end hook function.
282func (s *poolStore) GetSwapEndHook() func(cur realm, poolPath string) error {
283 result, err := s.kvStore.Get(StoreKeySwapEndHook.String())
284 if err != nil {
285 panic(err)
286 }
287
288 swapEndHook, ok := result.(func(cur realm, poolPath string) error)
289 if !ok {
290 panic(ufmt.Sprintf("failed to cast result to func(poolPath string): %T", result))
291 }
292
293 return swapEndHook
294}
295
296// SetSwapEndHook stores the swap end hook function.
297func (s *poolStore) SetSwapEndHook(_ int, rlm realm, swapEndHook func(cur realm, poolPath string) error) error {
298 if !rlm.IsCurrent() {
299 return errors.New(ErrSpoofedRealm)
300 }
301
302 return s.kvStore.Set(0, rlm, StoreKeySwapEndHook.String(), swapEndHook)
303}
304
305// HasTickCrossHook checks if the tick cross hook is set.
306func (s *poolStore) HasTickCrossHook() bool {
307 return s.kvStore.Has(StoreKeyTickCrossHook.String())
308}
309
310// GetTickCrossHook retrieves the tick cross hook function.
311func (s *poolStore) GetTickCrossHook() func(cur realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64) {
312 result, err := s.kvStore.Get(StoreKeyTickCrossHook.String())
313 if err != nil {
314 panic(err)
315 }
316
317 tickCrossHook, ok := result.(func(cur realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64))
318 if !ok {
319 panic(ufmt.Sprintf("failed to cast result to func(poolPath string, tickId int32, zeroForOne bool, timestamp int64): %T", result))
320 }
321
322 return tickCrossHook
323}
324
325// SetTickCrossHook stores the tick cross hook function.
326func (s *poolStore) SetTickCrossHook(_ int, rlm realm, tickCrossHook func(cur realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64)) error {
327 if !rlm.IsCurrent() {
328 return errors.New(ErrSpoofedRealm)
329 }
330
331 return s.kvStore.Set(0, rlm, StoreKeyTickCrossHook.String(), tickCrossHook)
332}
333
334// NewPoolStore creates a new pool store instance with the provided KV store.
335// This function is used by the upgrade system to create storage instances for each implementation.
336func NewPoolStore(kvStore store.KVStore) IPoolStore {
337 return &poolStore{
338 kvStore: kvStore,
339 }
340}