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  }