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

getter.gno

6.36 Kb · 184 lines
  1package position
  2
  3import (
  4	"strconv"
  5
  6	"gno.land/p/gnoswap/consts"
  7	u256 "gno.land/p/gnoswap/uint256"
  8	ufmt "gno.land/p/nt/ufmt/v0"
  9
 10	pl "gno.land/r/gnoswap/pool"
 11	"gno.land/r/gnoswap/position"
 12)
 13
 14// MustGetPosition returns a position for a given position ID.
 15// panics if position doesn't exist
 16func (p *positionV1) mustGetPosition(positionId uint64) *position.Position {
 17	pos, exist := p.GetPosition(positionId)
 18	if !exist {
 19		panic(newErrorWithDetail(
 20			errPositionDoesNotExist,
 21			ufmt.Sprintf("position with position ID(%d) doesn't exist", positionId),
 22		))
 23	}
 24
 25	return &pos
 26}
 27
 28// GetPositionCount returns the total number of positions.
 29func (p *positionV1) GetPositionCount() int {
 30	return p.store.GetPositions().Size()
 31}
 32
 33// GetPositionIDs returns a paginated list of position IDs.
 34func (p *positionV1) GetPositionIDs(offset, count int) []uint64 {
 35	positions := p.store.GetPositions()
 36	positionIDs := make([]uint64, 0)
 37
 38	positions.IterateByOffset(offset, count, func(key string, _ any) bool {
 39		id, err := strconv.ParseUint(key, 10, 64)
 40		if err != nil {
 41			return false
 42		}
 43
 44		positionIDs = append(positionIDs, id)
 45
 46		return false
 47	})
 48
 49	return positionIDs
 50}
 51
 52// GetPosition returns a position for a given position ID.
 53// Returns false if position doesn't exist
 54func (p *positionV1) GetPosition(id uint64) (position.Position, bool) {
 55	return p.store.GetPosition(id)
 56}
 57
 58// ExistPosition checks if a position exists for a given position ID
 59func (p *positionV1) ExistPosition(positionId uint64) bool {
 60	return p.store.HasPosition(positionId)
 61}
 62
 63func (p *positionV1) IsBurned(positionId uint64) bool {
 64	return p.mustGetPosition(positionId).Burned()
 65}
 66
 67func (p *positionV1) IsInRange(positionId uint64) bool {
 68	position := p.mustGetPosition(positionId)
 69	poolPath := position.PoolKey()
 70	poolCurrentTick := pl.GetSlot0Tick(poolPath)
 71
 72	return position.TickLower() <= poolCurrentTick && poolCurrentTick < position.TickUpper()
 73}
 74
 75func (p *positionV1) GetPositionOperator(positionId uint64) address {
 76	return p.mustGetPosition(positionId).Operator()
 77}
 78
 79func (p *positionV1) GetPositionPoolKey(positionId uint64) string {
 80	return p.mustGetPosition(positionId).PoolKey()
 81}
 82
 83func (p *positionV1) GetPositionTickLower(positionId uint64) int32 {
 84	return p.mustGetPosition(positionId).TickLower()
 85}
 86
 87func (p *positionV1) GetPositionTickUpper(positionId uint64) int32 {
 88	return p.mustGetPosition(positionId).TickUpper()
 89}
 90
 91func (p *positionV1) GetPositionLiquidity(positionId uint64) string {
 92	return p.mustGetPosition(positionId).Liquidity()
 93}
 94
 95func (p *positionV1) GetPositionTokenBalances(positionId uint64) (int64, int64) {
 96	position := p.mustGetPosition(positionId)
 97
 98	return calculatePositionBalances(position)
 99}
100
101func (p *positionV1) GetPositionFeeGrowthInside0LastX128(positionId uint64) string {
102	return p.mustGetPosition(positionId).FeeGrowthInside0LastX128()
103}
104
105func (p *positionV1) GetPositionFeeGrowthInside1LastX128(positionId uint64) string {
106	return p.mustGetPosition(positionId).FeeGrowthInside1LastX128()
107}
108
109func (p *positionV1) GetPositionTokensOwed0(positionId uint64) int64 {
110	return p.mustGetPosition(positionId).TokensOwed0()
111}
112
113func (p *positionV1) GetPositionTokensOwed1(positionId uint64) int64 {
114	return p.mustGetPosition(positionId).TokensOwed1()
115}
116
117func (p *positionV1) GetPositionOwner(positionId uint64) address {
118	owner, err := p.nftAccessor.OwnerOf(positionIdFrom(positionId))
119	if err != nil {
120		panic(newErrorWithDetail(
121			errDataNotFound, err.Error()))
122	}
123
124	return owner
125}
126
127func (p *positionV1) GetUnclaimedFee(positionId uint64) (*u256.Uint, *u256.Uint) {
128	// ref: https://blog.uniswap.org/uniswap-v3-math-primer-2#calculating-uncollected-fees
129	position := p.mustGetPosition(positionId)
130
131	liquidity := u256.MustFromDecimal(position.Liquidity())
132	tickLower := position.TickLower()
133	tickUpper := position.TickUpper()
134
135	poolKey := position.PoolKey()
136
137	currentTick := pl.GetSlot0Tick(poolKey)
138
139	feeGrowthGlobal0X128Str, feeGrowthGlobal1X128Str := pl.GetFeeGrowthGlobalX128(poolKey)
140	feeGrowthGlobal0X128 := u256.MustFromDecimal(feeGrowthGlobal0X128Str)
141	feeGrowthGlobal1X128 := u256.MustFromDecimal(feeGrowthGlobal1X128Str)
142
143	tickUpperFeeGrowthOutside0X128Str, tickUpperFeeGrowthOutside1X128Str := pl.GetTickFeeGrowthOutsideX128(poolKey, tickUpper)
144	tickUpperFeeGrowthOutside0X128 := u256.MustFromDecimal(tickUpperFeeGrowthOutside0X128Str)
145	tickUpperFeeGrowthOutside1X128 := u256.MustFromDecimal(tickUpperFeeGrowthOutside1X128Str)
146
147	tickLowerFeeGrowthOutside0X128Str, tickLowerFeeGrowthOutside1X128Str := pl.GetTickFeeGrowthOutsideX128(poolKey, tickLower)
148	tickLowerFeeGrowthOutside0X128 := u256.MustFromDecimal(tickLowerFeeGrowthOutside0X128Str)
149	tickLowerFeeGrowthOutside1X128 := u256.MustFromDecimal(tickLowerFeeGrowthOutside1X128Str)
150
151	feeGrowthInside0LastX128 := u256.MustFromDecimal(position.FeeGrowthInside0LastX128())
152	feeGrowthInside1LastX128 := u256.MustFromDecimal(position.FeeGrowthInside1LastX128())
153
154	var tickLowerFeeGrowthBelow0, tickLowerFeeGrowthBelow1, tickUpperFeeGrowthAbove0, tickUpperFeeGrowthAbove1 *u256.Uint
155
156	if currentTick >= tickUpper {
157		tickUpperFeeGrowthAbove0 = u256.Zero().Sub(feeGrowthGlobal0X128, tickUpperFeeGrowthOutside0X128)
158		tickUpperFeeGrowthAbove1 = u256.Zero().Sub(feeGrowthGlobal1X128, tickUpperFeeGrowthOutside1X128)
159	} else {
160		tickUpperFeeGrowthAbove0 = tickUpperFeeGrowthOutside0X128
161		tickUpperFeeGrowthAbove1 = tickUpperFeeGrowthOutside1X128
162	}
163
164	if currentTick >= tickLower {
165		tickLowerFeeGrowthBelow0 = tickLowerFeeGrowthOutside0X128
166		tickLowerFeeGrowthBelow1 = tickLowerFeeGrowthOutside1X128
167	} else {
168		tickLowerFeeGrowthBelow0 = u256.Zero().Sub(feeGrowthGlobal0X128, tickLowerFeeGrowthOutside0X128)
169		tickLowerFeeGrowthBelow1 = u256.Zero().Sub(feeGrowthGlobal1X128, tickLowerFeeGrowthOutside1X128)
170	}
171
172	feeGrowthInside0X128 := u256.Zero().Sub(feeGrowthGlobal0X128, tickLowerFeeGrowthBelow0)
173	feeGrowthInside0X128 = u256.Zero().Sub(feeGrowthInside0X128, tickUpperFeeGrowthAbove0)
174
175	feeGrowthInside1X128 := u256.Zero().Sub(feeGrowthGlobal1X128, tickLowerFeeGrowthBelow1)
176	feeGrowthInside1X128 = u256.Zero().Sub(feeGrowthInside1X128, tickUpperFeeGrowthAbove1)
177
178	diffGrowthInside0X128 := u256.Zero().Sub(feeGrowthInside0X128, feeGrowthInside0LastX128)
179	unclaimedFee0 := u256.MulDiv(diffGrowthInside0X128, liquidity, consts.Q128())
180
181	diffGrowthInside1X128 := u256.Zero().Sub(feeGrowthInside1X128, feeGrowthInside1LastX128)
182	unclaimedFee1 := u256.MulDiv(diffGrowthInside1X128, liquidity, consts.Q128())
183	return unclaimedFee0, unclaimedFee1
184}