accessor.gno
17.66 Kb · 452 lines
1package staker
2
3import (
4 "errors"
5
6 "gno.land/p/nt/grc721/v0"
7 "gno.land/r/gnoswap/access/v1"
8 "gno.land/r/gnoswap/emission"
9 "gno.land/r/gnoswap/gnft"
10 "gno.land/r/gnoswap/pool"
11)
12
13type PoolAccessor interface {
14 // ExistsPoolPath reports whether a pool is registered at poolPath.
15 //
16 // Parameters:
17 // - poolPath: Pool path whose registration is checked.
18 //
19 // Returns:
20 // - bool: true when a pool is registered at poolPath; false otherwise.
21 ExistsPoolPath(poolPath string) bool
22 // GetSlot0Tick returns the current slot-0 tick for a registered pool.
23 //
24 // Parameters:
25 // - poolPath: Pool path whose current tick is queried.
26 //
27 // Returns:
28 // - int32: Current signed slot-0 tick; the accessor panics if the underlying pool query fails.
29 GetSlot0Tick(poolPath string) int32
30 // GetSlot0SqrtPriceX96 returns a pool's current Q96-scaled square-root price.
31 //
32 // Parameters:
33 // - poolPath: Pool path whose current square-root price is queried.
34 //
35 // Returns:
36 // - string: Decimal representation of the Q96-scaled square-root price; the accessor panics if the underlying query fails.
37 GetSlot0SqrtPriceX96(poolPath string) string
38
39 // SetTickCrossHook registers a callback for pool tick-crossing events.
40 //
41 // Parameters:
42 // - _: Internal call discriminator; callers pass 0.
43 // - rlm: Propagated realm context; it must be current before the hook is registered.
44 // - hook: Callback invoked with the internal discriminator, current pool realm, pool path, crossed tick ID, swap direction (zeroForOne), and the event timestamp in Unix seconds.
45 SetTickCrossHook(_ int, rlm realm, hook func(_ int, rlm realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64))
46 // SetSwapStartHook registers a callback invoked when a pool swap starts.
47 //
48 // Parameters:
49 // - _: Internal call discriminator; callers pass 0.
50 // - rlm: Propagated realm context; it must be current before the hook is registered.
51 // - hook: Callback invoked with the internal discriminator, current pool realm, pool path, and swap-start timestamp in Unix seconds.
52 SetSwapStartHook(_ int, rlm realm, hook func(_ int, rlm realm, poolPath string, timestamp int64))
53 // SetSwapEndHook registers a callback invoked when a pool swap ends.
54 //
55 // Parameters:
56 // - _: Internal call discriminator; callers pass 0.
57 // - rlm: Propagated realm context; it must be current before the hook is registered.
58 // - hook: Callback invoked with the internal discriminator, current pool realm, and pool path; its error is propagated by the pool hook.
59 SetSwapEndHook(_ int, rlm realm, hook func(_ int, rlm realm, poolPath string) error)
60}
61
62type poolAccessor struct{}
63
64// ExistsPoolPath reports whether a pool is registered at poolPath.
65//
66// Parameters:
67// - poolPath: Pool path whose registration is checked.
68//
69// Returns:
70// - bool: true when a pool is registered at poolPath; false otherwise.
71func (p *poolAccessor) ExistsPoolPath(poolPath string) bool {
72 return pool.ExistsPoolPath(poolPath)
73}
74
75// GetSlot0Tick returns the current slot-0 tick for a registered pool.
76//
77// Parameters:
78// - poolPath: Pool path whose current tick is queried.
79//
80// Returns:
81// - int32: Current signed slot-0 tick; the accessor panics if the underlying pool query fails.
82func (p *poolAccessor) GetSlot0Tick(poolPath string) int32 {
83 tick, err := pool.GetSlot0Tick(poolPath)
84 if err != nil {
85 panic(err)
86 }
87 return tick
88}
89
90// GetSlot0SqrtPriceX96 returns a pool's current Q96-scaled square-root price.
91//
92// Parameters:
93// - poolPath: Pool path whose current square-root price is queried.
94//
95// Returns:
96// - string: Decimal representation of the Q96-scaled square-root price; the accessor panics if the underlying query fails.
97func (p *poolAccessor) GetSlot0SqrtPriceX96(poolPath string) string {
98 sqrtPriceX96, err := pool.GetSlot0SqrtPriceX96(poolPath)
99 if err != nil {
100 panic(err)
101 }
102 return sqrtPriceX96
103}
104
105// SetTickCrossHook registers a callback for pool tick-crossing events.
106//
107// Parameters:
108// - _: Internal call discriminator; callers pass 0.
109// - rlm: Propagated realm context; it must be current before the hook is registered.
110// - hook: Callback invoked with the internal discriminator, current pool realm, pool path, crossed tick ID, swap direction (zeroForOne), and the event timestamp in Unix seconds.
111func (p *poolAccessor) SetTickCrossHook(_ int, rlm realm, hook func(_ int, rlm realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64)) {
112 access.AssertIsRlmCurrent(0, rlm)
113
114 pool.SetTickCrossHook(cross(rlm), func(cur realm, poolPath string, tickId int32, zeroForOne bool, timestamp int64) {
115 hook(0, cur, poolPath, tickId, zeroForOne, timestamp)
116 })
117}
118
119// SetSwapStartHook registers a callback invoked when a pool swap starts.
120//
121// Parameters:
122// - _: Internal call discriminator; callers pass 0.
123// - rlm: Propagated realm context; it must be current before the hook is registered.
124// - hook: Callback invoked with the internal discriminator, current pool realm, pool path, and swap-start timestamp in Unix seconds.
125func (p *poolAccessor) SetSwapStartHook(_ int, rlm realm, hook func(_ int, rlm realm, poolPath string, timestamp int64)) {
126 access.AssertIsRlmCurrent(0, rlm)
127
128 pool.SetSwapStartHook(cross(rlm), func(cur realm, poolPath string, timestamp int64) {
129 hook(0, cur, poolPath, timestamp)
130 })
131}
132
133// SetSwapEndHook registers a callback invoked when a pool swap ends.
134//
135// Parameters:
136// - _: Internal call discriminator; callers pass 0.
137// - rlm: Propagated realm context; it must be current before the hook is registered.
138// - hook: Callback invoked with the internal discriminator, current pool realm, and pool path; its error is propagated by the pool hook.
139func (p *poolAccessor) SetSwapEndHook(_ int, rlm realm, hook func(_ int, rlm realm, poolPath string) error) {
140 access.AssertIsRlmCurrent(0, rlm)
141
142 pool.SetSwapEndHook(cross(rlm), func(cur realm, poolPath string) error {
143 return hook(0, cur, poolPath)
144 })
145}
146
147func newPoolAccessor() PoolAccessor {
148 return &poolAccessor{}
149}
150
151type EmissionAccessor interface {
152 // MintAndDistributeGns mints and distributes scheduled GNS emission through the emission realm.
153 //
154 // Parameters:
155 // - _: Internal call discriminator; callers pass 0.
156 // - rlm: Propagated realm context; it must be current before crossing into the emission realm.
157 //
158 // Returns:
159 // - int64: GNS amount distributed during this call, including any carried-forward amount.
160 // - bool: false only when emission is halted; true when processing completes, including a no-op call.
161 MintAndDistributeGns(_ int, rlm realm) (int64, bool)
162
163 // GetStakerEmissionAmountPerSecond returns the current GNS emission rate allocated to liquidity stakers.
164 //
165 // Returns:
166 // - int64: Current staker allocation in GNS units per second.
167 // - error: Non-nil when the emission distribution configuration cannot provide a staker rate; nil otherwise.
168 GetStakerEmissionAmountPerSecond() (int64, error)
169
170 // GetStakerEmissionAmountPerSecondInRange returns staker emission-rate change points over an inclusive time range.
171 //
172 // Parameters:
173 // - start: Inclusive lower bound as a Unix timestamp.
174 // - end: Inclusive upper bound as a Unix timestamp.
175 //
176 // Returns:
177 // - []int64: Unix timestamps at which the underlying GNS emission rate changes.
178 // - []int64: Staker emission amounts in GNS units per second at the corresponding timestamps.
179 // - error: Non-nil when the emission distribution configuration is invalid; nil when both slices are produced.
180 GetStakerEmissionAmountPerSecondInRange(start, end int64) ([]int64, []int64, error)
181
182 // SetOnDistributionPctChangeCallback registers a callback for staker distribution-percentage changes.
183 //
184 // Parameters:
185 // - _: Internal call discriminator; callers pass 0.
186 // - rlm: Propagated realm context; it must be current before the callback is registered.
187 // - callback: Callback invoked with the internal discriminator, current emission realm, and the new staker emission amount per second.
188 SetOnDistributionPctChangeCallback(_ int, rlm realm, callback func(_ int, rlm realm, emissionAmountPerSecond int64))
189}
190
191type emissionAccessor struct{}
192
193// MintAndDistributeGns mints and distributes scheduled GNS emission through the emission realm.
194//
195// Parameters:
196// - _: Internal call discriminator; callers pass 0.
197// - rlm: Propagated realm context; it must be current before crossing into the emission realm.
198//
199// Returns:
200// - int64: GNS amount distributed during this call, including any carried-forward amount.
201// - bool: false only when emission is halted; true when processing completes, including a no-op call.
202func (e *emissionAccessor) MintAndDistributeGns(_ int, rlm realm) (int64, bool) {
203 access.AssertIsRlmCurrent(0, rlm)
204
205 return emission.MintAndDistributeGns(cross(rlm))
206}
207
208// GetStakerEmissionAmountPerSecond returns the current GNS emission rate allocated to liquidity stakers.
209//
210// Returns:
211// - int64: Current staker allocation in GNS units per second.
212// - error: Non-nil when the emission distribution configuration cannot provide a staker rate; nil otherwise.
213func (e *emissionAccessor) GetStakerEmissionAmountPerSecond() (int64, error) {
214 return emission.GetStakerEmissionAmountPerSecond()
215}
216
217// GetStakerEmissionAmountPerSecondInRange returns staker emission-rate change points over an inclusive time range.
218//
219// Parameters:
220// - start: Inclusive lower bound as a Unix timestamp.
221// - end: Inclusive upper bound as a Unix timestamp.
222//
223// Returns:
224// - []int64: Unix timestamps at which the underlying GNS emission rate changes.
225// - []int64: Staker emission amounts in GNS units per second at the corresponding timestamps.
226// - error: Non-nil when the emission distribution configuration is invalid; nil when both slices are produced.
227func (e *emissionAccessor) GetStakerEmissionAmountPerSecondInRange(start, end int64) ([]int64, []int64, error) {
228 return emission.GetStakerEmissionAmountPerSecondInRange(start, end)
229}
230
231// SetOnDistributionPctChangeCallback registers a callback for staker distribution-percentage changes.
232//
233// Parameters:
234// - _: Internal call discriminator; callers pass 0.
235// - rlm: Propagated realm context; it must be current before the callback is registered.
236// - callback: Callback invoked with the internal discriminator, current emission realm, and the new staker emission amount per second.
237func (e *emissionAccessor) SetOnDistributionPctChangeCallback(_ int, rlm realm, callback func(_ int, rlm realm, emissionAmountPerSecond int64)) {
238 access.AssertIsRlmCurrent(0, rlm)
239
240 // Wrap the caller-provided callback in an adapter constructed HERE, inside
241 // the /r/gnoswap/staker domain package. By borrow rule #3 the wrapper
242 // closure is owned by /r/gnoswap/staker (its construction realm), not by the
243 // v1 implementation that passed `callback` in. This mirrors the swap/tick
244 // hook accessors above and lets emission persist the callback into its
245 // package-level var without hitting "cannot persist realm value" (which
246 // fired when a v1-constructed closure was stored there directly).
247 emission.SetOnDistributionPctChangeCallback(cross(rlm), func(cur realm, emissionAmountPerSecond int64) {
248 callback(0, cur, emissionAmountPerSecond)
249 })
250}
251
252func newEmissionAccessor() EmissionAccessor {
253 return &emissionAccessor{}
254}
255
256type NFTAccessor interface {
257 // Approve grants an address permission to transfer a specific NFT.
258 //
259 // Parameters:
260 // - _: Internal call discriminator; callers pass 0.
261 // - rlm: Propagated realm context; it must be current before crossing into the NFT realm.
262 // - approved: Address receiving permission for tid.
263 // - tid: NFT token ID whose approval is changed.
264 //
265 // Returns:
266 // - error: Non-nil when the NFT realm rejects the approval or the realm context is spoofed; nil on success.
267 Approve(_ int, rlm realm, approved address, tid grc721.TokenID) error
268
269 // Mint creates an NFT with tid and transfers it to to.
270 //
271 // Parameters:
272 // - _: Internal call discriminator; callers pass 0.
273 // - rlm: Propagated realm context; it must be current before crossing into the NFT realm.
274 // - to: Address receiving the newly minted NFT.
275 // - tid: Token ID to mint.
276 //
277 // Returns:
278 // - grc721.TokenID: The minted token ID, equal to tid.
279 Mint(_ int, rlm realm, to address, tid grc721.TokenID) grc721.TokenID
280
281 // Burn destroys an NFT.
282 //
283 // Parameters:
284 // - _: Internal call discriminator; callers pass 0.
285 // - rlm: Propagated realm context; it must be current before crossing into the NFT realm.
286 // - tid: NFT token ID to burn.
287 Burn(_ int, rlm realm, tid grc721.TokenID)
288
289 // TransferFrom moves an NFT from its current owner to another address.
290 //
291 // Parameters:
292 // - _: Internal call discriminator; callers pass 0.
293 // - rlm: Propagated realm context; it must be current before crossing into the NFT realm.
294 // - from: Current owner address of tid.
295 // - to: Recipient address for tid.
296 // - tid: NFT token ID to transfer.
297 //
298 // Returns:
299 // - error: Non-nil when the NFT realm rejects the transfer or the realm context is spoofed; nil on success.
300 TransferFrom(_ int, rlm realm, from, to address, tid grc721.TokenID) error
301
302 // TotalSupply returns the number of NFTs currently minted and not burned.
303 //
304 // Returns:
305 // - int64: Current NFT collection supply.
306 TotalSupply() int64
307
308 // Exists reports whether an NFT token ID is currently minted.
309 //
310 // Parameters:
311 // - tid: NFT token ID to look up.
312 //
313 // Returns:
314 // - bool: true when tid has an owner in the NFT ledger; false when it does not exist.
315 Exists(tid grc721.TokenID) bool
316
317 // MustOwnerOf returns the owner of an NFT and panics when tid is invalid.
318 //
319 // Parameters:
320 // - tid: NFT token ID whose owner is required.
321 //
322 // Returns:
323 // - address: Current owner address of tid; the accessor panics if tid does not exist.
324 MustOwnerOf(tid grc721.TokenID) address
325
326 // OwnerOf returns the owner of an NFT without panicking on lookup failure.
327 //
328 // Parameters:
329 // - tid: NFT token ID whose owner is queried.
330 //
331 // Returns:
332 // - address: Current owner address, or the zero address when lookup fails.
333 // - error: Non-nil when tid does not exist or the NFT realm cannot resolve its owner.
334 OwnerOf(tid grc721.TokenID) (address, error)
335}
336
337type gnftAccessor struct{}
338
339// Approve grants an address permission to transfer a specific NFT.
340//
341// Parameters:
342// - _: Internal call discriminator; callers pass 0.
343// - rlm: Propagated realm context; it must be current before crossing into the NFT realm.
344// - approved: Address receiving permission for tid.
345// - tid: NFT token ID whose approval is changed.
346//
347// Returns:
348// - error: Non-nil when the NFT realm rejects the approval or the realm context is spoofed; nil on success.
349func (n *gnftAccessor) Approve(_ int, rlm realm, approved address, tid grc721.TokenID) error {
350 if !rlm.IsCurrent() {
351 return errors.New(ErrSpoofedRealm)
352 }
353
354 return gnft.Approve(cross(rlm), approved, tid)
355}
356
357// Mint creates an NFT with tid and transfers it to to.
358//
359// Parameters:
360// - _: Internal call discriminator; callers pass 0.
361// - rlm: Propagated realm context; it must be current before crossing into the NFT realm.
362// - to: Address receiving the newly minted NFT.
363// - tid: Token ID to mint.
364//
365// Returns:
366// - grc721.TokenID: The minted token ID, equal to tid.
367func (n *gnftAccessor) Mint(_ int, rlm realm, to address, tid grc721.TokenID) grc721.TokenID {
368 access.AssertIsRlmCurrent(0, rlm)
369
370 return gnft.Mint(cross(rlm), to, tid)
371}
372
373// Burn destroys an NFT.
374//
375// Parameters:
376// - _: Internal call discriminator; callers pass 0.
377// - rlm: Propagated realm context; it must be current before crossing into the NFT realm.
378// - tid: NFT token ID to burn.
379func (n *gnftAccessor) Burn(_ int, rlm realm, tid grc721.TokenID) {
380 access.AssertIsRlmCurrent(0, rlm)
381
382 gnft.Burn(cross(rlm), tid)
383}
384
385// TransferFrom moves an NFT from its current owner to another address.
386//
387// Parameters:
388// - _: Internal call discriminator; callers pass 0.
389// - rlm: Propagated realm context; it must be current before crossing into the NFT realm.
390// - from: Current owner address of tid.
391// - to: Recipient address for tid.
392// - tid: NFT token ID to transfer.
393//
394// Returns:
395// - error: Non-nil when the NFT realm rejects the transfer or the realm context is spoofed; nil on success.
396func (n *gnftAccessor) TransferFrom(_ int, rlm realm, from, to address, tid grc721.TokenID) error {
397 if !rlm.IsCurrent() {
398 return errors.New(ErrSpoofedRealm)
399 }
400
401 return gnft.TransferFrom(cross(rlm), from, to, tid)
402}
403
404// TotalSupply returns the number of NFTs currently minted and not burned.
405//
406// Returns:
407// - int64: Current NFT collection supply.
408func (n *gnftAccessor) TotalSupply() int64 {
409 return gnft.TotalSupply()
410}
411
412// Exists reports whether an NFT token ID is currently minted.
413//
414// Parameters:
415// - tid: NFT token ID to look up.
416//
417// Returns:
418// - bool: true when tid has an owner in the NFT ledger; false when it does not exist.
419func (n *gnftAccessor) Exists(tid grc721.TokenID) bool {
420 return gnft.Exists(tid)
421}
422
423// MustOwnerOf returns the owner of an NFT and panics when tid is invalid.
424//
425// Parameters:
426// - tid: NFT token ID whose owner is required.
427//
428// Returns:
429// - address: Current owner address of tid; the accessor panics if tid does not exist.
430func (n *gnftAccessor) MustOwnerOf(tid grc721.TokenID) address {
431 owner, err := gnft.OwnerOf(tid)
432 if err != nil {
433 panic(err.Error())
434 }
435 return owner
436}
437
438// OwnerOf returns the owner of an NFT without panicking on lookup failure.
439//
440// Parameters:
441// - tid: NFT token ID whose owner is queried.
442//
443// Returns:
444// - address: Current owner address, or the zero address when lookup fails.
445// - error: Non-nil when tid does not exist or the NFT realm cannot resolve its owner.
446func (n *gnftAccessor) OwnerOf(tid grc721.TokenID) (address, error) {
447 return gnft.OwnerOf(tid)
448}
449
450func newNFTAccessor() NFTAccessor {
451 return &gnftAccessor{}
452}