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}