github.com/InjectiveLabs/sdk-go@v1.53.0/chain/exchange/types/common_utils.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "math/big" 6 "reflect" 7 "regexp" 8 "strconv" 9 "strings" 10 11 "cosmossdk.io/errors" 12 "cosmossdk.io/math" 13 sdk "github.com/cosmos/cosmos-sdk/types" 14 "github.com/ethereum/go-ethereum/common" 15 ) 16 17 func IsEqualDenoms(denoms1, denoms2 []string) bool { 18 denom1Map := make(map[string]struct{}) 19 denom2Map := make(map[string]struct{}) 20 21 for _, denom := range denoms1 { 22 denom1Map[denom] = struct{}{} 23 } 24 for _, denom := range denoms2 { 25 denom2Map[denom] = struct{}{} 26 } 27 28 return reflect.DeepEqual(denom1Map, denom2Map) 29 } 30 31 func IsPeggyToken(denom string) bool { 32 return strings.HasPrefix(denom, "peggy0x") 33 } 34 35 func IsIBCDenom(denom string) bool { 36 return strings.HasPrefix(denom, "ibc/") 37 } 38 39 type SpotLimitOrderDelta struct { 40 Order *SpotLimitOrder 41 FillQuantity math.LegacyDec 42 } 43 44 type DerivativeLimitOrderDelta struct { 45 Order *DerivativeLimitOrder 46 FillQuantity math.LegacyDec 47 CancelQuantity math.LegacyDec 48 } 49 50 type DerivativeMarketOrderDelta struct { 51 Order *DerivativeMarketOrder 52 FillQuantity math.LegacyDec 53 } 54 55 func (d *DerivativeMarketOrderDelta) UnfilledQuantity() math.LegacyDec { 56 return d.Order.OrderInfo.Quantity.Sub(d.FillQuantity) 57 } 58 59 func (d *DerivativeLimitOrderDelta) IsBuy() bool { 60 return d.Order.IsBuy() 61 } 62 63 func (d *DerivativeLimitOrderDelta) SubaccountID() common.Hash { 64 return d.Order.SubaccountID() 65 } 66 67 func (d *DerivativeLimitOrderDelta) Price() math.LegacyDec { 68 return d.Order.Price() 69 } 70 71 func (d *DerivativeLimitOrderDelta) FillableQuantity() math.LegacyDec { 72 return d.Order.Fillable.Sub(d.CancelQuantity) 73 } 74 75 func (d *DerivativeLimitOrderDelta) OrderHash() common.Hash { 76 return d.Order.Hash() 77 } 78 79 func (d *DerivativeLimitOrderDelta) Cid() string { 80 return d.Order.Cid() 81 } 82 83 var AuctionSubaccountID = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") 84 var ZeroSubaccountID = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") 85 86 // inj1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqe2hm49 87 var TempRewardsSenderAddress = sdk.AccAddress(common.HexToAddress(ZeroSubaccountID.Hex()).Bytes()) 88 89 // inj1qqq3zyg3zyg3zyg3zyg3zyg3zyg3zyg3c9gg96 90 var AuctionFeesAddress = sdk.AccAddress(common.HexToAddress(AuctionSubaccountID.Hex()).Bytes()) 91 92 var hexRegex = regexp.MustCompile("^(0x)?[0-9a-fA-F]+$") 93 94 func StringInSlice(a string, list *[]string) bool { 95 for _, b := range *list { 96 if b == a { 97 return true 98 } 99 } 100 return false 101 } 102 103 func IsDefaultSubaccountID(subaccountID common.Hash) bool { 104 // empty 12 bytes 105 emptyBytes := make([]byte, common.HashLength-common.AddressLength) 106 return bytes.Equal(subaccountID[common.AddressLength:], emptyBytes) 107 } 108 109 func IsNonceDerivedSubaccountID(subaccountID string) bool { 110 return len(subaccountID) <= MaxSubaccountNonceLength 111 } 112 113 // CheckValidSubaccountIDOrNonce checks that either 1) the subaccountId is well-formatted subaccount nonce or 114 // 2) the normal subaccountId is a valid subaccount ID and the sender is the owner of the subaccount 115 func CheckValidSubaccountIDOrNonce(sender sdk.AccAddress, subaccountId string) error { 116 if IsNonceDerivedSubaccountID(subaccountId) { 117 if _, err := GetNonceDerivedSubaccountID(sender, subaccountId); err != nil { 118 return errors.Wrap(ErrBadSubaccountID, subaccountId) 119 } 120 return nil 121 } 122 123 subaccountAddress, ok := IsValidSubaccountID(subaccountId) 124 if !ok { 125 return errors.Wrap(ErrBadSubaccountID, subaccountId) 126 } 127 128 if !bytes.Equal(subaccountAddress.Bytes(), sender.Bytes()) { 129 return errors.Wrap(ErrBadSubaccountID, subaccountId) 130 } 131 return nil 132 } 133 134 func IsValidSubaccountID(subaccountID string) (*common.Address, bool) { 135 if !IsHexHash(subaccountID) { 136 return nil, false 137 } 138 subaccountIdBytes := common.FromHex(subaccountID) 139 addressBytes := subaccountIdBytes[:common.AddressLength] 140 address := common.BytesToAddress(addressBytes) 141 return &address, true 142 } 143 144 func IsValidOrderHash(orderHash string) bool { 145 return IsHexHash(orderHash) 146 } 147 148 func IsValidCid(cid string) bool { 149 // Arbitrarily setting max length of cid to uuid length 150 return len(cid) <= 36 151 } 152 153 // IsHexHash verifies whether a string can represent a valid hex-encoded hash or not. 154 func IsHexHash(s string) bool { 155 if !isHexString(s) { 156 return false 157 } 158 159 if strings.HasPrefix(s, "0x") { 160 return len(s) == 2*common.HashLength+2 161 } 162 163 return len(s) == 2*common.HashLength 164 } 165 166 func isHexString(str string) bool { 167 return hexRegex.MatchString(str) 168 } 169 170 func BreachesMinimumTickSize(value, minTickSize math.LegacyDec) bool { 171 // obviously breached if the value less than the minTickSize 172 if value.LT(minTickSize) { 173 return true 174 } 175 176 // prevent mod by 0 177 if minTickSize.IsZero() { 178 return true 179 } 180 181 // is breaching when value % minTickSize != 0 182 residue := new(big.Int).Mod(value.BigInt(), minTickSize.BigInt()) 183 return !bytes.Equal(residue.Bytes(), big.NewInt(0).Bytes()) 184 } 185 186 func (s *Subaccount) GetSubaccountID() (*common.Hash, error) { 187 trader, err := sdk.AccAddressFromBech32(s.Trader) 188 if err != nil { 189 return nil, err 190 } 191 return SdkAddressWithNonceToSubaccountID(trader, s.SubaccountNonce) 192 } 193 194 type Account [20]byte 195 196 func SdkAccAddressToAccount(account sdk.AccAddress) Account { 197 var accAddr Account 198 copy(accAddr[:], account.Bytes()) 199 return accAddr 200 } 201 202 func SubaccountIDToAccount(subaccountID common.Hash) Account { 203 var accAddr Account 204 copy(accAddr[:], subaccountID.Bytes()[:20]) 205 return accAddr 206 } 207 208 func GetSubaccountNonce(subaccountIdStr string) (uint32, error) { 209 // maximum of 10^3 = 1000 numeric subaccounts allowed 210 isValidLength := len(subaccountIdStr) <= MaxSubaccountNonceLength 211 212 if !isValidLength { 213 return 0, ErrBadSubaccountNonce 214 } 215 216 if subaccountIdStr == "" || subaccountIdStr == "0" { 217 return 0, nil 218 } 219 220 num, err := strconv.Atoi(subaccountIdStr) 221 if err != nil { 222 return 0, err 223 } 224 225 if num < 0 || num > 999 { 226 return 0, ErrBadSubaccountNonce 227 } 228 229 return uint32(num), nil 230 } 231 232 func MustGetSubaccountIDOrDeriveFromNonce(sender sdk.AccAddress, subaccountId string) common.Hash { 233 subaccountID, err := GetSubaccountIDOrDeriveFromNonce(sender, subaccountId) 234 if err != nil { 235 panic(err) 236 } 237 238 return subaccountID 239 } 240 241 func GetNonceDerivedSubaccountID(sender sdk.AccAddress, subaccountId string) (common.Hash, error) { 242 nonce, err := GetSubaccountNonce(subaccountId) 243 if err != nil { 244 return common.Hash{}, err 245 } 246 247 subaccountID, err := SdkAddressWithNonceToSubaccountID(sender, nonce) 248 if err != nil { 249 return common.Hash{}, err 250 } 251 252 return *subaccountID, nil 253 } 254 255 func GetSubaccountIDOrDeriveFromNonce(sender sdk.AccAddress, subaccountId string) (common.Hash, error) { 256 if IsNonceDerivedSubaccountID(subaccountId) { 257 return GetNonceDerivedSubaccountID(sender, subaccountId) 258 } 259 260 if !IsHexHash(subaccountId) { 261 return common.Hash{}, errors.Wrap(ErrBadSubaccountID, subaccountId) 262 } 263 264 return common.HexToHash(subaccountId), nil 265 } 266 267 func SdkAddressWithNonceToSubaccountID(addr sdk.AccAddress, nonce uint32) (*common.Hash, error) { 268 if len(addr.Bytes()) > common.AddressLength { 269 return &AuctionSubaccountID, ErrBadSubaccountID 270 } 271 subaccountID := common.BytesToHash(append(addr.Bytes(), common.LeftPadBytes(big.NewInt(int64(nonce)).Bytes(), 12)...)) 272 273 return &subaccountID, nil 274 } 275 276 func MustSdkAddressWithNonceToSubaccountID(addr sdk.AccAddress, nonce uint32) common.Hash { 277 if len(addr.Bytes()) > common.AddressLength { 278 panic(ErrBadSubaccountID) 279 } 280 subaccountID := common.BytesToHash(append(addr.Bytes(), common.LeftPadBytes(big.NewInt(int64(nonce)).Bytes(), 12)...)) 281 282 return subaccountID 283 } 284 285 func SdkAddressToSubaccountID(addr sdk.AccAddress) common.Hash { 286 return common.BytesToHash(common.RightPadBytes(addr.Bytes(), 32)) 287 } 288 289 func SdkAddressToEthAddress(addr sdk.AccAddress) common.Address { 290 return common.BytesToAddress(addr.Bytes()) 291 } 292 293 func SubaccountIDToSdkAddress(subaccountID common.Hash) sdk.AccAddress { 294 return sdk.AccAddress(subaccountID[:common.AddressLength]) 295 } 296 297 func SubaccountIDToEthAddress(subaccountID common.Hash) common.Address { 298 return common.BytesToAddress(subaccountID[:common.AddressLength]) 299 } 300 301 func EthAddressToSubaccountID(addr common.Address) common.Hash { 302 return common.BytesToHash(common.RightPadBytes(addr.Bytes(), 32)) 303 } 304 305 func DecToDecBytes(dec math.LegacyDec) []byte { 306 return dec.BigInt().Bytes() 307 } 308 309 func DecBytesToDec(bz []byte) math.LegacyDec { 310 dec := math.LegacyNewDecFromBigIntWithPrec(new(big.Int).SetBytes(bz), math.LegacyPrecision) 311 if dec.IsNil() { 312 return math.LegacyZeroDec() 313 } 314 return dec 315 } 316 317 func IntToIntBytes(i math.Int) []byte { 318 return i.BigInt().Bytes() 319 } 320 321 func IntBytesToInt(bz []byte) math.Int { 322 return math.NewIntFromBigInt(new(big.Int).SetBytes(bz)) 323 } 324 325 func HasDuplicates(slice []string) bool { 326 seen := make(map[string]struct{}) 327 for _, item := range slice { 328 if _, ok := seen[item]; ok { 329 return true 330 } 331 seen[item] = struct{}{} 332 } 333 return false 334 } 335 336 func HasDuplicatesHexHash(slice []string) bool { 337 seen := make(map[common.Hash]struct{}) 338 for _, item := range slice { 339 if _, ok := seen[common.HexToHash(item)]; ok { 340 return true 341 } 342 seen[common.HexToHash(item)] = struct{}{} 343 } 344 return false 345 } 346 347 func HasDuplicatesCoin(slice []sdk.Coin) bool { 348 seen := make(map[string]struct{}) 349 for _, item := range slice { 350 if _, ok := seen[item.Denom]; ok { 351 return true 352 } 353 seen[item.Denom] = struct{}{} 354 } 355 return false 356 } 357 358 func HasDuplicatesOrder(slice []*OrderData) bool { 359 seenHashes := make(map[string]struct{}) 360 seenCids := make(map[string]struct{}) 361 for _, item := range slice { 362 hash, cid := item.GetOrderHash(), item.GetCid() 363 _, hashExists := seenHashes[hash] 364 _, cidExists := seenCids[cid] 365 366 if (hash != "" && hashExists) || (cid != "" && cidExists) { 367 return true 368 } 369 seenHashes[hash] = struct{}{} 370 seenCids[cid] = struct{}{} 371 } 372 return false 373 }