github.com/InjectiveLabs/sdk-go@v1.53.0/client/core/market_test.go (about)

     1  package core
     2  
     3  import (
     4  	"testing"
     5  
     6  	sdkmath "cosmossdk.io/math"
     7  
     8  	"github.com/huandu/go-assert"
     9  	"github.com/shopspring/decimal"
    10  )
    11  
    12  func createINJUSDTSpotMarket() SpotMarket {
    13  	injToken := createINJToken()
    14  	usdtToken := createUSDTToken()
    15  
    16  	makerFeeRate := decimal.RequireFromString("-0.0001")
    17  	takerFeeRate := decimal.RequireFromString("0.001")
    18  	serviceProviderFee := decimal.RequireFromString("0.4")
    19  	minPriceTickSize := decimal.RequireFromString("0.000000000000001")
    20  	minQuantityTickSize := decimal.RequireFromString("1000000000000000")
    21  	minNotional := decimal.RequireFromString("1000000")
    22  
    23  	market := SpotMarket{
    24  		Id:                  "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0",
    25  		Status:              "active",
    26  		Ticker:              "INJ/USDT",
    27  		BaseToken:           injToken,
    28  		QuoteToken:          usdtToken,
    29  		MakerFeeRate:        makerFeeRate,
    30  		TakerFeeRate:        takerFeeRate,
    31  		ServiceProviderFee:  serviceProviderFee,
    32  		MinPriceTickSize:    minPriceTickSize,
    33  		MinQuantityTickSize: minQuantityTickSize,
    34  		MinNotional:         minNotional,
    35  	}
    36  	return market
    37  }
    38  
    39  func createBTCUSDTPerpMarket() DerivativeMarket {
    40  	usdtToken := createUSDTToken()
    41  
    42  	initialMarginRatio := decimal.RequireFromString("0.095")
    43  	maintenanceMarginRatio := decimal.RequireFromString("0.025")
    44  	makerFeeRate := decimal.RequireFromString("-0.0001")
    45  	takerFeeRate := decimal.RequireFromString("0.001")
    46  	serviceProviderFee := decimal.RequireFromString("0.4")
    47  	minPriceTickSize := decimal.RequireFromString("1000000")
    48  	minQuantityTickSize := decimal.RequireFromString("0.0001")
    49  	minNotional := decimal.RequireFromString("1000000")
    50  
    51  	market := DerivativeMarket{
    52  		Id:                     "0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce",
    53  		Status:                 "active",
    54  		Ticker:                 "BTC/USDT PERP",
    55  		OracleBase:             "BTC",
    56  		OracleQuote:            usdtToken.Symbol,
    57  		OracleType:             "bandibc",
    58  		OracleScaleFactor:      6,
    59  		InitialMarginRatio:     initialMarginRatio,
    60  		MaintenanceMarginRatio: maintenanceMarginRatio,
    61  		QuoteToken:             usdtToken,
    62  		MakerFeeRate:           makerFeeRate,
    63  		TakerFeeRate:           takerFeeRate,
    64  		ServiceProviderFee:     serviceProviderFee,
    65  		MinPriceTickSize:       minPriceTickSize,
    66  		MinQuantityTickSize:    minQuantityTickSize,
    67  		MinNotional:            minNotional,
    68  	}
    69  	return market
    70  }
    71  
    72  // Spot market tests
    73  
    74  func TestConvertQuantityToChainFormatForSpotMarket(t *testing.T) {
    75  	spotMarket := createINJUSDTSpotMarket()
    76  	originalQuantity := decimal.RequireFromString("123.456789")
    77  
    78  	chainValue := spotMarket.QuantityToChainFormat(originalQuantity)
    79  	expectedValue := originalQuantity.Mul(decimal.New(1, spotMarket.BaseToken.Decimals))
    80  	quantizedValue := expectedValue.DivRound(spotMarket.MinQuantityTickSize, 0).Mul(spotMarket.MinQuantityTickSize)
    81  	quantizedChainFormatValue := sdkmath.LegacyMustNewDecFromStr(quantizedValue.String())
    82  
    83  	assert.Assert(t, quantizedChainFormatValue.Equal(chainValue))
    84  }
    85  
    86  func TestConvertPriceToChainFormatForSpotMarket(t *testing.T) {
    87  	spotMarket := createINJUSDTSpotMarket()
    88  	originalPrice := decimal.RequireFromString("123.456789")
    89  
    90  	chainValue := spotMarket.PriceToChainFormat(originalPrice)
    91  	priceDecimals := spotMarket.QuoteToken.Decimals - spotMarket.BaseToken.Decimals
    92  	expectedValue := originalPrice.Mul(decimal.New(1, priceDecimals))
    93  	quantizedValue := expectedValue.DivRound(spotMarket.MinPriceTickSize, 0).Mul(spotMarket.MinPriceTickSize)
    94  	quantizedChainFormatValue := sdkmath.LegacyMustNewDecFromStr(quantizedValue.String())
    95  
    96  	assert.Assert(t, quantizedChainFormatValue.Equal(chainValue))
    97  }
    98  
    99  func TestConvertNotionalToChainFormatForSpotMarket(t *testing.T) {
   100  	spotMarket := createINJUSDTSpotMarket()
   101  	originalNotional := decimal.RequireFromString("123.456789")
   102  
   103  	chainValue := spotMarket.NotionalToChainFormat(originalNotional)
   104  	notionalDecimals := spotMarket.QuoteToken.Decimals
   105  	expectedValue := originalNotional.Mul(decimal.New(1, notionalDecimals))
   106  	chainFormatValue := sdkmath.LegacyMustNewDecFromStr(expectedValue.String())
   107  
   108  	assert.Assert(t, chainFormatValue.Equal(chainValue))
   109  }
   110  
   111  func TestConvertQuantityFromChainFormatForSpotMarket(t *testing.T) {
   112  	spotMarket := createINJUSDTSpotMarket()
   113  	expectedQuantity := decimal.RequireFromString("123.456")
   114  
   115  	chainFormatQuantity := expectedQuantity.Mul(decimal.New(1, spotMarket.BaseToken.Decimals))
   116  	humanReadableQuantity := spotMarket.QuantityFromChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatQuantity.String()))
   117  
   118  	assert.Assert(t, expectedQuantity.Equal(humanReadableQuantity))
   119  }
   120  
   121  func TestConvertPriceFromChainFormatForSpotMarket(t *testing.T) {
   122  	spotMarket := createINJUSDTSpotMarket()
   123  	expectedPrice := decimal.RequireFromString("123.456")
   124  
   125  	priceDecimals := spotMarket.QuoteToken.Decimals - spotMarket.BaseToken.Decimals
   126  	chainFormatPrice := expectedPrice.Mul(decimal.New(1, priceDecimals))
   127  	humanReadablePrice := spotMarket.PriceFromChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatPrice.String()))
   128  
   129  	assert.Assert(t, expectedPrice.Equal(humanReadablePrice))
   130  }
   131  
   132  func TestConvertNotionalFromChainFormatForSpotMarket(t *testing.T) {
   133  	spotMarket := createINJUSDTSpotMarket()
   134  	expectedNotional := decimal.RequireFromString("123.456")
   135  
   136  	notionalDecimals := spotMarket.QuoteToken.Decimals
   137  	chainFormatPrice := expectedNotional.Mul(decimal.New(1, notionalDecimals))
   138  	humanReadableNotional := spotMarket.NotionalFromChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatPrice.String()))
   139  
   140  	assert.Assert(t, expectedNotional.Equal(humanReadableNotional))
   141  }
   142  
   143  func TestConvertQuantityFromExtendedChainFormatForSpotMarket(t *testing.T) {
   144  	spotMarket := createINJUSDTSpotMarket()
   145  	expectedQuantity := decimal.RequireFromString("123.456")
   146  
   147  	chainFormatQuantity := expectedQuantity.Mul(decimal.New(1, spotMarket.BaseToken.Decimals)).Mul(decimal.New(1, AdditionalChainFormatDecimals))
   148  	humanReadableQuantity := spotMarket.QuantityFromExtendedChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatQuantity.String()))
   149  
   150  	assert.Assert(t, expectedQuantity.Equal(humanReadableQuantity))
   151  }
   152  
   153  func TestConvertPriceFromExtendedChainFormatForSpotMarket(t *testing.T) {
   154  	spotMarket := createINJUSDTSpotMarket()
   155  	expectedPrice := decimal.RequireFromString("123.456")
   156  
   157  	priceDecimals := spotMarket.QuoteToken.Decimals - spotMarket.BaseToken.Decimals
   158  	chainFormatPrice := expectedPrice.Mul(decimal.New(1, priceDecimals)).Mul(decimal.New(1, AdditionalChainFormatDecimals))
   159  	humanReadablePrice := spotMarket.PriceFromExtendedChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatPrice.String()))
   160  
   161  	assert.Assert(t, expectedPrice.Equal(humanReadablePrice))
   162  }
   163  
   164  func TestConvertNotionalFromExtendedChainFormatForSpotMarket(t *testing.T) {
   165  	spotMarket := createINJUSDTSpotMarket()
   166  	expectedNotional := decimal.RequireFromString("123.456")
   167  
   168  	notionalDecimals := spotMarket.QuoteToken.Decimals
   169  	chainFormatNotional := expectedNotional.Mul(decimal.New(1, notionalDecimals)).Mul(decimal.New(1, AdditionalChainFormatDecimals))
   170  	humanReadableNotional := spotMarket.NotionalFromExtendedChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatNotional.String()))
   171  
   172  	assert.Assert(t, expectedNotional.Equal(humanReadableNotional))
   173  }
   174  
   175  // Derivative markets tests
   176  
   177  func TestConvertQuantityToChainFormatForDerivativeMarket(t *testing.T) {
   178  	derivativeMarket := createBTCUSDTPerpMarket()
   179  	originalQuantity := decimal.RequireFromString("123.456789")
   180  
   181  	chainValue := derivativeMarket.QuantityToChainFormat(originalQuantity)
   182  	quantizedValue := originalQuantity.DivRound(derivativeMarket.MinQuantityTickSize, 0).Mul(derivativeMarket.MinQuantityTickSize)
   183  	quantizedChainFormatValue := sdkmath.LegacyMustNewDecFromStr(quantizedValue.String())
   184  
   185  	assert.Assert(t, quantizedChainFormatValue.Equal(chainValue))
   186  }
   187  
   188  func TestConvertPriceToChainFormatForDerivativeMarket(t *testing.T) {
   189  	derivativeMarket := createBTCUSDTPerpMarket()
   190  	originalPrice := decimal.RequireFromString("123.456789")
   191  
   192  	chainValue := derivativeMarket.PriceToChainFormat(originalPrice)
   193  	priceDecimals := derivativeMarket.QuoteToken.Decimals
   194  	expectedValue := originalPrice.Mul(decimal.New(1, priceDecimals))
   195  	quantizedValue := expectedValue.DivRound(derivativeMarket.MinPriceTickSize, 0).Mul(derivativeMarket.MinPriceTickSize)
   196  	quantizedChainFormatValue := sdkmath.LegacyMustNewDecFromStr(quantizedValue.String())
   197  
   198  	assert.Assert(t, quantizedChainFormatValue.Equal(chainValue))
   199  }
   200  
   201  func TestConvertMarginToChainFormatForDerivativeMarket(t *testing.T) {
   202  	derivativeMarket := createBTCUSDTPerpMarket()
   203  	originalPrice := decimal.RequireFromString("123.456789")
   204  
   205  	chainValue := derivativeMarket.MarginToChainFormat(originalPrice)
   206  	marginDecimals := derivativeMarket.QuoteToken.Decimals
   207  	expectedValue := originalPrice.Mul(decimal.New(1, marginDecimals))
   208  	quantizedValue := expectedValue.DivRound(derivativeMarket.MinQuantityTickSize, 0).Mul(derivativeMarket.MinQuantityTickSize)
   209  	quantizedChainFormatValue := sdkmath.LegacyMustNewDecFromStr(quantizedValue.String())
   210  
   211  	assert.Assert(t, quantizedChainFormatValue.Equal(chainValue))
   212  }
   213  
   214  func TestCalculateMarginInChainFormatForDerivativeMarket(t *testing.T) {
   215  	derivativeMarket := createBTCUSDTPerpMarket()
   216  	originalQuantity := decimal.RequireFromString("10")
   217  	originalPrice := decimal.RequireFromString("123.456789")
   218  	originalLeverage := decimal.RequireFromString("2.5")
   219  
   220  	chainValue := derivativeMarket.CalculateMarginInChainFormat(originalQuantity, originalPrice, originalLeverage)
   221  	decimals := derivativeMarket.QuoteToken.Decimals
   222  	expectedValue := originalQuantity.Mul(originalPrice).Div(originalLeverage).Mul(decimal.New(1, decimals))
   223  	quantizedValue := expectedValue.DivRound(derivativeMarket.MinQuantityTickSize, 0).Mul(derivativeMarket.MinQuantityTickSize)
   224  	legacyDecimalQuantizedValue := sdkmath.LegacyMustNewDecFromStr(quantizedValue.String())
   225  
   226  	assert.Assert(t, chainValue.Equal(legacyDecimalQuantizedValue))
   227  }
   228  
   229  func TestConvertNotionalToChainFormatForDerivativeMarket(t *testing.T) {
   230  	derivativeMarket := createBTCUSDTPerpMarket()
   231  	originalNotional := decimal.RequireFromString("123.456789")
   232  
   233  	chainValue := derivativeMarket.NotionalToChainFormat(originalNotional)
   234  	notionalDecimals := derivativeMarket.QuoteToken.Decimals
   235  	expectedValue := originalNotional.Mul(decimal.New(1, notionalDecimals))
   236  	expectedChainFormatValue := sdkmath.LegacyMustNewDecFromStr(expectedValue.String())
   237  
   238  	assert.Assert(t, expectedChainFormatValue.Equal(chainValue))
   239  }
   240  
   241  func TestConvertQuantityFromChainFormatForDerivativeMarket(t *testing.T) {
   242  	derivativeMarket := createBTCUSDTPerpMarket()
   243  	expectedQuantity := decimal.RequireFromString("123.456")
   244  
   245  	chainFormatQuantity := expectedQuantity
   246  	humanReadableQuantity := derivativeMarket.QuantityFromChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatQuantity.String()))
   247  
   248  	assert.Assert(t, expectedQuantity.Equal(humanReadableQuantity))
   249  }
   250  
   251  func TestConvertPriceFromChainFormatForDerivativeMarket(t *testing.T) {
   252  	derivativeMarket := createBTCUSDTPerpMarket()
   253  	expectedPrice := decimal.RequireFromString("123.456")
   254  
   255  	priceDecimals := derivativeMarket.QuoteToken.Decimals
   256  	chainFormatPrice := expectedPrice.Mul(decimal.New(1, priceDecimals))
   257  	humanReadablePrice := derivativeMarket.PriceFromChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatPrice.String()))
   258  
   259  	assert.Assert(t, expectedPrice.Equal(humanReadablePrice))
   260  }
   261  
   262  func TestConvertMarginFromChainFormatForDerivativeMarket(t *testing.T) {
   263  	derivativeMarket := createBTCUSDTPerpMarket()
   264  	expectedMargin := decimal.RequireFromString("123.456")
   265  
   266  	marginDecimals := derivativeMarket.QuoteToken.Decimals
   267  	chainFormatMargin := expectedMargin.Mul(decimal.New(1, marginDecimals))
   268  	humanReadablePrice := derivativeMarket.MarginFromChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatMargin.String()))
   269  
   270  	assert.Assert(t, expectedMargin.Equal(humanReadablePrice))
   271  }
   272  
   273  func TestConvertNotionalFromChainFormatForDerivativeMarket(t *testing.T) {
   274  	derivativeMarket := createBTCUSDTPerpMarket()
   275  	expectedNotional := decimal.RequireFromString("123.456")
   276  
   277  	notionalDecimals := derivativeMarket.QuoteToken.Decimals
   278  	chainFormatPrice := expectedNotional.Mul(decimal.New(1, notionalDecimals))
   279  	humanReadableNotional := derivativeMarket.NotionalFromChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatPrice.String()))
   280  
   281  	assert.Assert(t, expectedNotional.Equal(humanReadableNotional))
   282  }
   283  
   284  func TestConvertQuantityFromExtendedChainFormatForDerivativeMarket(t *testing.T) {
   285  	derivativeMarket := createBTCUSDTPerpMarket()
   286  	expectedQuantity := decimal.RequireFromString("123.456")
   287  
   288  	chainFormatQuantity := expectedQuantity.Mul(decimal.New(1, AdditionalChainFormatDecimals))
   289  	humanReadableQuantity := derivativeMarket.QuantityFromExtendedChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatQuantity.String()))
   290  
   291  	assert.Assert(t, expectedQuantity.Equal(humanReadableQuantity))
   292  }
   293  
   294  func TestConvertPriceFromExtendedChainFormatForDerivativeMarket(t *testing.T) {
   295  	derivativeMarket := createBTCUSDTPerpMarket()
   296  	expectedPrice := decimal.RequireFromString("123.456")
   297  
   298  	priceDecimals := derivativeMarket.QuoteToken.Decimals
   299  	chainFormatPrice := expectedPrice.Mul(decimal.New(1, priceDecimals)).Mul(decimal.New(1, AdditionalChainFormatDecimals))
   300  	humanReadablePrice := derivativeMarket.PriceFromExtendedChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatPrice.String()))
   301  
   302  	assert.Assert(t, expectedPrice.Equal(humanReadablePrice))
   303  }
   304  
   305  func TestConvertMarginFromExtendedChainFormatForDerivativeMarket(t *testing.T) {
   306  	derivativeMarket := createBTCUSDTPerpMarket()
   307  	expectedMargin := decimal.RequireFromString("123.456")
   308  
   309  	marginDecimals := derivativeMarket.QuoteToken.Decimals
   310  	chainFormatMargin := expectedMargin.Mul(decimal.New(1, marginDecimals)).Mul(decimal.New(1, AdditionalChainFormatDecimals))
   311  	humanReadablePrice := derivativeMarket.MarginFromExtendedChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatMargin.String()))
   312  
   313  	assert.Assert(t, expectedMargin.Equal(humanReadablePrice))
   314  }
   315  
   316  func TestConvertNotionalFromExtendedChainFormatForDerivativeMarket(t *testing.T) {
   317  	derivativeMarket := createBTCUSDTPerpMarket()
   318  	expectedNotional := decimal.RequireFromString("123.456")
   319  
   320  	notionalDecimals := derivativeMarket.QuoteToken.Decimals
   321  	chainFormatNotional := expectedNotional.Mul(decimal.New(1, notionalDecimals)).Mul(decimal.New(1, AdditionalChainFormatDecimals))
   322  	humanReadableNotional := derivativeMarket.NotionalFromExtendedChainFormat(sdkmath.LegacyMustNewDecFromStr(chainFormatNotional.String()))
   323  
   324  	assert.Assert(t, expectedNotional.Equal(humanReadableNotional))
   325  }