Search Apps Documentation Source Content File Folder Download Copy Actions Download

utils.gno

5.97 Kb ยท 210 lines
  1package v1
  2
  3import (
  4	"strconv"
  5	"strings"
  6
  7	"gno.land/p/demo/tokens/grc721"
  8	prabc "gno.land/p/gnoswap/rbac"
  9	u256 "gno.land/p/gnoswap/uint256"
 10	"gno.land/p/nt/ufmt"
 11	"gno.land/r/gnoswap/access"
 12)
 13
 14const MAX_UINT256 string = "115792089237316195423570985008687907853269984665640564039457584007913129639935"
 15
 16func mustGetPositionAddress() address {
 17	return access.MustGetAddress(prabc.ROLE_POSITION.String())
 18}
 19
 20func mustGetStakerAddress() address {
 21	return access.MustGetAddress(prabc.ROLE_STAKER.String())
 22}
 23
 24// positionIdFrom converts positionId to grc721.TokenID type
 25// NOTE: input parameter positionId can be string, int, uint64, or grc721.TokenID
 26// if positionId is nil or not supported, it will panic
 27// if positionId is not found, it will panic
 28// input: positionId any
 29// output: grc721.TokenID
 30func positionIdFrom(positionId any) grc721.TokenID {
 31	if positionId == nil {
 32		panic(newErrorWithDetail(errInvalidInput, "positionId is nil"))
 33	}
 34
 35	switch positionId.(type) {
 36	case string:
 37		return grc721.TokenID(positionId.(string))
 38	case int:
 39		return grc721.TokenID(strconv.Itoa(positionId.(int)))
 40	case uint64:
 41		return grc721.TokenID(strconv.Itoa(int(positionId.(uint64))))
 42	case grc721.TokenID:
 43		return positionId.(grc721.TokenID)
 44	default:
 45		panic(newErrorWithDetail(errInvalidInput, "unsupported positionId type"))
 46	}
 47}
 48
 49// exists checks whether positionId exists
 50// If positionId doesn't exist, return false, otherwise return true
 51// input: positionId uint64
 52// output: bool
 53func (p *positionV1) exists(positionId uint64) bool {
 54	return p.nftAccessor.Exists(positionIdFrom(positionId))
 55}
 56
 57// isOwner checks whether the caller is the owner of the positionId
 58// If the caller is the owner of the positionId, return true, otherwise return false
 59// input: positionId uint64, addr std.Address
 60// output: bool
 61func (p *positionV1) isOwner(positionId uint64, addr address) bool {
 62	owner, err := p.nftAccessor.OwnerOf(positionIdFrom(positionId))
 63	if err != nil {
 64		return false
 65	}
 66	return owner == addr
 67}
 68
 69// isOperator checks whether the caller is the approved operator of the positionId
 70// If the caller is the approved operator of the positionId, return true, otherwise return false
 71// input: positionId uint64, addr std.Address
 72// output: bool
 73func (p *positionV1) isOperator(positionId uint64, addr address) bool {
 74	return p.GetPositionOperator(positionId) == addr
 75}
 76
 77// isStaked checks whether positionId is staked
 78// If positionId is staked, owner of positionId is staker contract
 79// If positionId is staked, return true, otherwise return false
 80// input: positionId grc721.TokenID
 81// output: bool
 82func (p *positionV1) isStaked(positionId grc721.TokenID) bool {
 83	exist := p.nftAccessor.Exists(positionId)
 84	if !exist {
 85		return false
 86	}
 87	owner, err := p.nftAccessor.OwnerOf(positionId)
 88	if err == nil && owner == mustGetStakerAddress() {
 89		return true
 90	}
 91	return false
 92}
 93
 94// isOwnerOrOperator checks whether the caller is the owner or approved operator of the positionId
 95// If the caller is the owner or approved operator of the positionId, return true, otherwise return false
 96// input: addr std.Address, positionId uint64
 97// output: bool
 98func (p *positionV1) isOwnerOrOperator(positionId uint64, addr address) bool {
 99	if !addr.IsValid() || !p.exists(positionId) {
100		return false
101	}
102
103	if p.isStaked(positionIdFrom(positionId)) {
104		return p.isOperator(positionId, addr)
105	}
106
107	return p.isOwner(positionId, addr)
108}
109
110// splitOf divides poolKey into pToken0, pToken1, and pFee
111// If poolKey is invalid, it will panic
112//
113// input: poolKey string
114// output:
115// - token0Path string
116// - token1Path string
117// - fee uint32
118func splitOf(poolKey string) (string, string, uint32) {
119	res := strings.Split(poolKey, ":")
120	if len(res) != 3 {
121		panic(newErrorWithDetail(errInvalidInput, ufmt.Sprintf("invalid poolKey(%s)", poolKey)))
122	}
123
124	pToken0, pToken1, pFeeStr := res[0], res[1], res[2]
125
126	pFee, err := strconv.Atoi(pFeeStr)
127	if err != nil {
128		panic(newErrorWithDetail(errInvalidInput, ufmt.Sprintf("invalid fee(%s)", pFeeStr)))
129	}
130
131	return pToken0, pToken1, uint32(pFee)
132}
133
134func formatUint(v any) string {
135	switch v := v.(type) {
136	case uint8:
137		return strconv.FormatUint(uint64(v), 10)
138	case uint32:
139		return strconv.FormatUint(uint64(v), 10)
140	case uint64:
141		return strconv.FormatUint(v, 10)
142	default:
143		panic(ufmt.Sprintf("invalid type: %T", v))
144	}
145}
146
147func formatInt(v any) string {
148	switch v := v.(type) {
149	case int32:
150		return strconv.FormatInt(int64(v), 10)
151	case int64:
152		return strconv.FormatInt(v, 10)
153	case int:
154		return strconv.Itoa(v)
155	default:
156		panic(ufmt.Sprintf("invalid type: %T", v))
157	}
158}
159
160func formatBool(v bool) string {
161	return strconv.FormatBool(v)
162}
163
164func mustParseInt64(v string) int64 {
165	amountInt, err := strconv.ParseInt(v, 10, 64)
166	if err != nil {
167		panic(err)
168	}
169
170	return amountInt
171}
172
173func isSlippageExceeded(amount0, amount1, amount0Min, amount1Min *u256.Uint) bool {
174	return !(amount0.Gte(amount0Min) && amount1.Gte(amount1Min))
175}
176
177func subUint256(x, y *u256.Uint) *u256.Uint {
178	if x.Cmp(y) < 0 {
179		diff := u256.Zero().Sub(u256.MustFromDecimal(MAX_UINT256), y)
180		result := u256.Zero().Add(diff, x)
181		return result.Add(result, u256.One())
182	}
183
184	return u256.Zero().Sub(x, y)
185}
186
187// safeConvertToInt64 safely converts a *u256.Uint value to an int64, ensuring no overflow.
188//
189// This function attempts to convert the given *u256.Uint value to an int64. If the value exceeds
190// the maximum allowable range for int64 (`2^63 - 1`), it triggers a panic with a descriptive error message.
191//
192// Parameters:
193// - value (*u256.Uint): The unsigned 256-bit integer to be converted.
194//
195// Returns:
196// - int64: The converted value if it falls within the int64 range.
197//
198// Panics:
199//   - If the `value` exceeds the range of int64, the function will panic with an error indicating
200//     the overflow and the original value.
201func safeConvertToInt64(value *u256.Uint) int64 {
202	res, overflow := value.Uint64WithOverflow()
203	if overflow || res > 9223372036854775807 {
204		panic(ufmt.Sprintf(
205			"amount(%s) overflows int64 range (max: 9223372036854775807)",
206			value.ToString(),
207		))
208	}
209	return int64(res)
210}