store.gno
5.90 Kb · 194 lines
1package router
2
3import (
4 "errors"
5
6 "gno.land/p/gnoswap/store/v1"
7 ufmt "gno.land/p/nt/ufmt/v0"
8)
9
10const errSpoofedRealm = "rlm does not match the current crossing frame"
11
12type StoreKey string
13
14// String converts the typed store key to the string key used by KVStore.
15//
16// Returns:
17// - key: underlying string representation of the store key
18func (s StoreKey) String() string {
19 return string(s)
20}
21
22const (
23 StoreKeySwapFee StoreKey = "swapFee" // Swap fee in basis points
24 StoreKeyPendingProtocolFees StoreKey = "pendingProtocolFees" // tokenPath -> amount held locally for protocol_fee
25)
26
27type routerStore struct {
28 kvStore store.KVStore
29}
30
31// HasSwapFeeKey reports whether persistent storage contains the router swap-fee key.
32//
33// Returns:
34// - exists: true when the swap-fee key is present, otherwise false
35func (s *routerStore) HasSwapFeeKey() bool {
36 return s.kvStore.Has(StoreKeySwapFee.String())
37}
38
39// GetSwapFee retrieves the current swap fee from persistent storage.
40//
41// Returns:
42// - fee: configured router fee in basis points; panics if the key is missing or has the wrong type
43func (s *routerStore) GetSwapFee() uint64 {
44 result, err := s.kvStore.Get(StoreKeySwapFee.String())
45 if err != nil {
46 panic(err)
47 }
48
49 swapFee, ok := result.(uint64)
50 if !ok {
51 panic(ufmt.Sprintf("failed to cast result to uint64: %T", result))
52 }
53
54 return swapFee
55}
56
57// SetSwapFee stores the router fee in persistent storage.
58//
59// Parameters:
60// - _: leading call discriminator; callers pass 0
61// - rlm: current realm context; must be the current crossing frame
62// - fee: router fee rate in basis points
63//
64// Returns:
65// - err: nil when storage succeeds; an error when rlm is not current or KVStore rejects the write
66func (s *routerStore) SetSwapFee(_ int, rlm realm, fee uint64) error {
67 if !rlm.IsCurrent() {
68 return errors.New(errSpoofedRealm)
69 }
70
71 return s.kvStore.Set(0, rlm, StoreKeySwapFee.String(), fee)
72}
73
74// HasPendingProtocolFeesKey reports whether persistent storage contains the pending-fees map.
75//
76// Returns:
77// - exists: true when the pending protocol-fees key is present, otherwise false
78func (s *routerStore) HasPendingProtocolFeesKey() bool {
79 return s.kvStore.Has(StoreKeyPendingProtocolFees.String())
80}
81
82// GetPendingProtocolFees retrieves the token-path keyed pending protocol-fees map.
83//
84// Returns:
85// - fees: stored token-path to pending amount map; panics if storage is missing or has the wrong type
86func (s *routerStore) GetPendingProtocolFees() map[string]int64 {
87 result, err := s.kvStore.Get(StoreKeyPendingProtocolFees.String())
88 if err != nil {
89 panic(err)
90 }
91
92 pendingProtocolFees, ok := result.(map[string]int64)
93 if !ok {
94 panic(ufmt.Sprintf("failed to cast result to map[string]int64: %T", result))
95 }
96
97 return pendingProtocolFees
98}
99
100// SetPendingProtocolFees replaces the pending protocol-fees map in persistent storage.
101//
102// Parameters:
103// - _: leading call discriminator; callers pass 0
104// - rlm: current realm context; must be the current crossing frame
105// - fees: token-path keyed pending fee amounts to store; entries are copied into realm-owned storage
106//
107// Returns:
108// - err: nil when storage succeeds; an error when rlm is not current or KVStore rejects the write
109func (s *routerStore) SetPendingProtocolFees(_ int, rlm realm, fees map[string]int64) error {
110 if !rlm.IsCurrent() {
111 return errors.New(errSpoofedRealm)
112 }
113
114 // The map is copied here so it is allocated by, and therefore mutable from, this realm.
115 owned := make(map[string]int64, len(fees))
116 for tokenPath, amount := range fees {
117 owned[tokenPath] = amount
118 }
119
120 return s.kvStore.Set(0, rlm, StoreKeyPendingProtocolFees.String(), owned)
121}
122
123// GetPendingProtocolFee returns the pending amount recorded for one token path.
124//
125// Parameters:
126// - tokenPath: token contract path whose pending protocol fee is queried
127//
128// Returns:
129// - amount: pending fee amount for tokenPath, or zero when no entry exists
130func (s *routerStore) GetPendingProtocolFee(tokenPath string) int64 {
131 return s.GetPendingProtocolFees()[tokenPath]
132}
133
134// SetPendingProtocolFee updates one token path's pending protocol-fee amount.
135//
136// Parameters:
137// - _: leading call discriminator; callers pass 0
138// - rlm: current realm context; must be current and authorized to write storage
139// - tokenPath: token contract path whose pending amount is updated
140// - amount: pending protocol-fee amount to record
141//
142// Returns:
143// - err: nil when updated; an error when the realm is spoofed or lacks KVStore write permission
144func (s *routerStore) SetPendingProtocolFee(_ int, rlm realm, tokenPath string, amount int64) error {
145 if !rlm.IsCurrent() {
146 return errors.New(errSpoofedRealm)
147 }
148
149 if rlm.IsCode() && !s.kvStore.IsWriteAuthorized(rlm.Address()) {
150 return errors.New(store.ErrWritePermissionDenied)
151 }
152
153 s.GetPendingProtocolFees()[tokenPath] = amount
154
155 return nil
156}
157
158// RemovePendingProtocolFee deletes one token path's pending protocol-fee entry.
159//
160// Parameters:
161// - _: leading call discriminator; callers pass 0
162// - rlm: current realm context; must be current and authorized to write storage
163// - tokenPath: token contract path whose pending amount is removed
164//
165// Returns:
166// - err: nil when removed; an error when the realm is spoofed or lacks KVStore write permission
167func (s *routerStore) RemovePendingProtocolFee(_ int, rlm realm, tokenPath string) error {
168 if !rlm.IsCurrent() {
169 return errors.New(errSpoofedRealm)
170 }
171
172 if rlm.IsCode() && !s.kvStore.IsWriteAuthorized(rlm.Address()) {
173 return errors.New(store.ErrWritePermissionDenied)
174 }
175
176 delete(s.GetPendingProtocolFees(), tokenPath)
177
178 return nil
179}
180
181// NewRouterStore creates a router store backed by the provided KV store.
182//
183// Parameters:
184// - kvStore: persistent key-value store used for router fee and pending-fee data
185//
186// Returns:
187// - routerStore: router storage implementation using kvStore
188func NewRouterStore(kvStore store.KVStore) IRouterStore {
189 rs := &routerStore{
190 kvStore: kvStore,
191 }
192
193 return rs
194}