Search Apps Documentation Source Content File Folder Download Copy Actions Download

getter.gno

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