Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}