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

utils.gno

4.31 Kb · 138 lines
  1package position
  2
  3import (
  4	"strconv"
  5	"strings"
  6
  7	prabc "gno.land/p/gnoswap/rbac/v1"
  8	u256 "gno.land/p/gnoswap/uint256/v1"
  9	"gno.land/p/nt/grc721/v0"
 10	ufmt "gno.land/p/nt/ufmt/v0"
 11	"gno.land/r/gnoswap/access/v1"
 12	pl "gno.land/r/gnoswap/pool"
 13)
 14
 15const MAX_UINT256 string = "115792089237316195423570985008687907853269984665640564039457584007913129639935"
 16
 17func mustGetStakerAddress() address {
 18	return access.MustGetAddress(prabc.ROLE_STAKER.String())
 19}
 20
 21// mustGetPool returns the read-only snapshot for poolPath.
 22// It panics when poolPath does not identify a pool.
 23func mustGetPool(poolPath string) *pl.Pool {
 24	pool, ok := pl.GetPools().Get(poolPath).(*pl.Pool)
 25	if !ok || pool == nil {
 26		panic(ufmt.Sprintf("expected poolPath(%s) to exist", poolPath))
 27	}
 28	return pool
 29}
 30
 31// positionIdFrom converts positionId to grc721.TokenID type
 32// input: positionId uint64
 33// output: grc721.TokenID
 34func positionIdFrom(positionId uint64) grc721.TokenID {
 35	return grc721.TokenID(strconv.FormatUint(positionId, 10))
 36}
 37
 38// exists checks whether positionId exists
 39// If positionId doesn't exist, return false, otherwise return true
 40// input: positionId uint64
 41// output: bool
 42func (p *positionV1) exists(positionId uint64) bool {
 43	return p.nftAccessor.Exists(positionIdFrom(positionId))
 44}
 45
 46// isOwner checks whether the caller is the owner of the positionId
 47// If the caller is the owner of the positionId, return true, otherwise return false
 48// input: positionId uint64, addr std.Address
 49// output: bool
 50func (p *positionV1) isOwner(positionId uint64, addr address) bool {
 51	owner, err := p.nftAccessor.OwnerOf(positionIdFrom(positionId))
 52	if err != nil {
 53		return false
 54	}
 55	return owner == addr
 56}
 57
 58// isOperator checks whether the caller is the approved operator of the positionId
 59// If the caller is the approved operator of the positionId, return true, otherwise return false
 60// input: positionId uint64, addr std.Address
 61// output: bool
 62func (p *positionV1) isOperator(positionId uint64, addr address) bool {
 63	operator, err := p.GetPositionOperator(positionId)
 64	return err == nil && operator == addr
 65}
 66
 67// isStaked checks whether positionId is staked
 68// If positionId is staked, owner of positionId is staker contract
 69// If positionId is staked, return true, otherwise return false
 70// input: positionId grc721.TokenID
 71// output: bool
 72func (p *positionV1) isStaked(positionId grc721.TokenID) bool {
 73	exist := p.nftAccessor.Exists(positionId)
 74	if !exist {
 75		return false
 76	}
 77	owner, err := p.nftAccessor.OwnerOf(positionId)
 78	if err == nil && owner == mustGetStakerAddress() {
 79		return true
 80	}
 81	return false
 82}
 83
 84// isOwnerOrOperator checks whether the caller is the owner or approved operator of the positionId
 85// If the caller is the owner or approved operator of the positionId, return true, otherwise return false
 86// input: addr std.Address, positionId uint64
 87// output: bool
 88func (p *positionV1) isOwnerOrOperator(positionId uint64, addr address) bool {
 89	if !addr.IsValid() || !p.exists(positionId) {
 90		return false
 91	}
 92
 93	if p.isStaked(positionIdFrom(positionId)) {
 94		return p.isOperator(positionId, addr)
 95	}
 96
 97	return p.isOwner(positionId, addr)
 98}
 99
100// splitOf divides poolKey into pToken0, pToken1, and pFee
101// If poolKey is invalid, it will panic
102//
103// input: poolKey string
104// output:
105// - token0Path string
106// - token1Path string
107// - fee uint32
108func splitOf(poolKey string) (string, string, uint32) {
109	res := strings.Split(poolKey, ":")
110	if len(res) != 3 {
111		panic(newErrorWithDetail(errInvalidInput, ufmt.Sprintf("invalid poolKey(%s)", poolKey)))
112	}
113
114	pToken0, pToken1, pFeeStr := res[0], res[1], res[2]
115
116	pFee, err := strconv.Atoi(pFeeStr)
117	if err != nil {
118		panic(newErrorWithDetail(errInvalidInput, ufmt.Sprintf("invalid fee(%s)", pFeeStr)))
119	}
120
121	return pToken0, pToken1, uint32(pFee)
122}
123
124func isSlippageExceeded(amount0, amount1, amount0Min, amount1Min *u256.Uint) bool {
125	return !(amount0.Gte(amount0Min) && amount1.Gte(amount1Min))
126}
127
128// currentPoolObservation derives the latest stored observation from the
129// Uniswap-V3-aligned Slot0 and observations surfaces.
130func currentPoolObservation(poolPath string) (int64, string, int64, error) {
131	slot0 := pl.GetSlot0(poolPath)
132	observation, err := pl.GetObservationAt(poolPath, slot0.ObservationIndex())
133	if err != nil {
134		return 0, "", 0, err
135	}
136
137	return observation.TickCumulative(), observation.SecondsPerLiquidityCumulativeX128(), observation.BlockTimestamp(), nil
138}