Search Apps Documentation Source Content File Folder Download Copy Actions Download 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}