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}