github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/order/endblocker_test.go (about) 1 //go:build ignore 2 3 package order 4 5 import ( 6 "math/rand" 7 "strconv" 8 "testing" 9 "time" 10 11 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 12 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 13 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply" 14 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 15 "github.com/stretchr/testify/require" 16 17 "github.com/fibonacci-chain/fbc/x/common" 18 "github.com/fibonacci-chain/fbc/x/dex" 19 "github.com/fibonacci-chain/fbc/x/order/keeper" 20 "github.com/fibonacci-chain/fbc/x/order/types" 21 token "github.com/fibonacci-chain/fbc/x/token/types" 22 ) 23 24 func TestEndBlockerPeriodicMatch(t *testing.T) { 25 common.InitConfig() 26 mapp, addrKeysSlice := getMockApp(t, 2) 27 k := mapp.orderKeeper 28 mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 29 30 var startHeight int64 = 10 31 ctx := mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(startHeight) 32 mapp.supplyKeeper.SetSupply(ctx, supply.NewSupply(mapp.TotalCoinsSupply)) 33 34 feeParams := types.DefaultTestParams() 35 mapp.orderKeeper.SetParams(ctx, &feeParams) 36 37 tokenPair := dex.GetBuiltInTokenPair() 38 err := mapp.dexKeeper.SaveTokenPair(ctx, tokenPair) 39 require.Nil(t, err) 40 mapp.dexKeeper.SetOperator(ctx, dex.DEXOperator{ 41 Address: tokenPair.Owner, 42 HandlingFeeAddress: tokenPair.Owner, 43 }) 44 45 // mock orders 46 orders := []*types.Order{ 47 types.MockOrder(types.FormatOrderID(startHeight, 1), types.TestTokenPair, types.BuyOrder, "10.0", "1.0"), 48 types.MockOrder(types.FormatOrderID(startHeight, 2), types.TestTokenPair, types.SellOrder, "10.0", "0.5"), 49 types.MockOrder(types.FormatOrderID(startHeight, 3), types.TestTokenPair, types.SellOrder, "10.0", "2.5"), 50 } 51 orders[0].Sender = addrKeysSlice[0].Address 52 orders[1].Sender = addrKeysSlice[1].Address 53 orders[2].Sender = addrKeysSlice[1].Address 54 for i := 0; i < 3; i++ { 55 err := k.PlaceOrder(ctx, orders[i]) 56 require.NoError(t, err) 57 } 58 // subtract all okb of addr0 59 // 100 - 10 - 0.2592 60 err = k.LockCoins(ctx, addrKeysSlice[0].Address, sdk.SysCoins{{Denom: common.NativeToken, 61 Amount: sdk.MustNewDecFromStr("89.7408")}}, token.LockCoinsTypeQuantity) 62 require.NoError(t, err) 63 64 // call EndBlocker to execute periodic match 65 EndBlocker(ctx, k) 66 67 // check order status 68 order0 := k.GetOrder(ctx, orders[0].OrderID) 69 order1 := k.GetOrder(ctx, orders[1].OrderID) 70 order2 := k.GetOrder(ctx, orders[2].OrderID) 71 require.EqualValues(t, types.OrderStatusFilled, order0.Status) 72 require.EqualValues(t, types.OrderStatusFilled, order1.Status) 73 require.EqualValues(t, types.OrderStatusOpen, order2.Status) 74 require.EqualValues(t, sdk.MustNewDecFromStr("2"), order2.RemainQuantity) 75 76 // check depth book 77 depthBook := k.GetDepthBookCopy(types.TestTokenPair) 78 require.EqualValues(t, 1, len(depthBook.Items)) 79 require.EqualValues(t, sdk.MustNewDecFromStr("10.0"), depthBook.Items[0].Price) 80 require.True(sdk.DecEq(t, sdk.ZeroDec(), depthBook.Items[0].BuyQuantity)) 81 require.EqualValues(t, sdk.MustNewDecFromStr("2"), depthBook.Items[0].SellQuantity) 82 83 depthBookDB := k.GetDepthBookFromDB(ctx, types.TestTokenPair) 84 require.EqualValues(t, 1, len(depthBookDB.Items)) 85 require.EqualValues(t, sdk.MustNewDecFromStr("10.0"), depthBookDB.Items[0].Price) 86 require.True(sdk.DecEq(t, sdk.ZeroDec(), depthBookDB.Items[0].BuyQuantity)) 87 require.EqualValues(t, sdk.MustNewDecFromStr("2"), depthBookDB.Items[0].SellQuantity) 88 89 // check product price - order ids 90 key := types.FormatOrderIDsKey(types.TestTokenPair, sdk.MustNewDecFromStr("10.0"), types.SellOrder) 91 orderIDs := k.GetProductPriceOrderIDs(key) 92 require.EqualValues(t, 1, len(orderIDs)) 93 require.EqualValues(t, order2.OrderID, orderIDs[0]) 94 key = types.FormatOrderIDsKey(types.TestTokenPair, sdk.MustNewDecFromStr("10.0"), types.BuyOrder) 95 orderIDs = k.GetProductPriceOrderIDs(key) 96 require.EqualValues(t, 0, len(orderIDs)) 97 98 // check block match result 99 result := k.GetBlockMatchResult() 100 require.EqualValues(t, sdk.MustNewDecFromStr("10.0"), result.ResultMap[types.TestTokenPair].Price) 101 require.EqualValues(t, sdk.MustNewDecFromStr("1.0"), result.ResultMap[types.TestTokenPair].Quantity) 102 require.EqualValues(t, 3, len(result.ResultMap[types.TestTokenPair].Deals)) 103 require.EqualValues(t, order0.OrderID, result.ResultMap[types.TestTokenPair].Deals[0].OrderID) 104 require.EqualValues(t, order1.OrderID, result.ResultMap[types.TestTokenPair].Deals[1].OrderID) 105 require.EqualValues(t, order2.OrderID, result.ResultMap[types.TestTokenPair].Deals[2].OrderID) 106 // check closed order id 107 closedOrderIDs := k.GetLastClosedOrderIDs(ctx) 108 require.Equal(t, 2, len(closedOrderIDs)) 109 require.Equal(t, orders[0].OrderID, closedOrderIDs[0]) 110 require.Equal(t, orders[1].OrderID, closedOrderIDs[1]) 111 112 // check account balance 113 acc0 := mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[0].Address) 114 acc1 := mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[1].Address) 115 expectCoins0 := sdk.SysCoins{ 116 sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("0.2592")), 117 sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("100.999")), // 100 + 1 * (1 - 0.001) 118 } 119 expectCoins1 := sdk.SysCoins{ 120 sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("109.7308")), // 100 + 10 * (1-0.001) - 0.2592 121 sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("97")), // 100 - 0.5 - 2.5 122 } 123 require.EqualValues(t, expectCoins0.String(), acc0.GetCoins().String()) 124 require.EqualValues(t, expectCoins1.String(), acc1.GetCoins().String()) 125 126 // check fee pool 127 feeCollector := mapp.supplyKeeper.GetModuleAccount(ctx, auth.FeeCollectorName) 128 collectedFees := feeCollector.GetCoins() 129 require.EqualValues(t, "", collectedFees.String()) 130 } 131 132 func TestEndBlockerPeriodicMatchBusyProduct(t *testing.T) { 133 mapp, addrKeysSlice := getMockApp(t, 2) 134 k := mapp.orderKeeper 135 mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 136 ctx := mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(10) 137 mapp.supplyKeeper.SetSupply(ctx, supply.NewSupply(mapp.TotalCoinsSupply)) 138 feeParams := types.DefaultTestParams() 139 feeParams.MaxDealsPerBlock = 2 140 k.SetParams(ctx, &feeParams) 141 142 tokenPair := dex.GetBuiltInTokenPair() 143 err := mapp.dexKeeper.SaveTokenPair(ctx, tokenPair) 144 require.Nil(t, err) 145 mapp.dexKeeper.SetOperator(ctx, dex.DEXOperator{ 146 Address: tokenPair.Owner, 147 HandlingFeeAddress: tokenPair.Owner, 148 }) 149 150 // mock orders 151 orders := []*types.Order{ 152 types.MockOrder("", types.TestTokenPair, types.BuyOrder, "10.0", "1.0"), 153 types.MockOrder("", types.TestTokenPair, types.SellOrder, "10.0", "0.5"), 154 types.MockOrder("", types.TestTokenPair, types.SellOrder, "10.0", "2.5"), 155 } 156 orders[0].Sender = addrKeysSlice[0].Address 157 orders[1].Sender = addrKeysSlice[1].Address 158 orders[2].Sender = addrKeysSlice[1].Address 159 for i := 0; i < 3; i++ { 160 err := k.PlaceOrder(ctx, orders[i]) 161 require.NoError(t, err) 162 } 163 164 // ------- call EndBlocker at height 10 -------// 165 EndBlocker(ctx, k) 166 167 // check product lock 168 lock := k.GetDexKeeper().GetLockedProductsCopy(ctx).Data[types.TestTokenPair] 169 require.NotNil(t, lock) 170 require.EqualValues(t, 10, lock.BlockHeight) 171 require.EqualValues(t, sdk.MustNewDecFromStr("10.0"), lock.Price) 172 require.EqualValues(t, sdk.MustNewDecFromStr("1.0"), lock.Quantity) 173 require.EqualValues(t, sdk.MustNewDecFromStr("1.0"), lock.BuyExecuted) 174 require.EqualValues(t, sdk.MustNewDecFromStr("0.5"), lock.SellExecuted) 175 176 // check order status 177 order0 := k.GetOrder(ctx, orders[0].OrderID) 178 order1 := k.GetOrder(ctx, orders[1].OrderID) 179 order2 := k.GetOrder(ctx, orders[2].OrderID) 180 require.EqualValues(t, types.OrderStatusFilled, order0.Status) 181 require.EqualValues(t, types.OrderStatusFilled, order1.Status) 182 require.EqualValues(t, types.OrderStatusOpen, order2.Status) 183 require.EqualValues(t, sdk.MustNewDecFromStr("2.5"), order2.RemainQuantity) 184 185 // check depth book 186 depthBook := k.GetDepthBookCopy(types.TestTokenPair) 187 require.EqualValues(t, 1, len(depthBook.Items)) 188 require.EqualValues(t, sdk.MustNewDecFromStr("10.0"), depthBook.Items[0].Price) 189 require.True(sdk.DecEq(t, sdk.ZeroDec(), depthBook.Items[0].BuyQuantity)) 190 require.EqualValues(t, sdk.MustNewDecFromStr("2.5"), depthBook.Items[0].SellQuantity) 191 192 // check product price - order ids 193 key := types.FormatOrderIDsKey(types.TestTokenPair, sdk.MustNewDecFromStr("10.0"), types.SellOrder) 194 orderIDs := k.GetProductPriceOrderIDs(key) 195 require.EqualValues(t, 1, len(orderIDs)) 196 require.EqualValues(t, order2.OrderID, orderIDs[0]) 197 key = types.FormatOrderIDsKey(types.TestTokenPair, sdk.MustNewDecFromStr("10.0"), types.BuyOrder) 198 orderIDs = k.GetProductPriceOrderIDs(key) 199 require.EqualValues(t, 0, len(orderIDs)) 200 201 // check block match result 202 result := k.GetBlockMatchResult() 203 require.EqualValues(t, 10, result.ResultMap[types.TestTokenPair].BlockHeight) 204 require.EqualValues(t, sdk.MustNewDecFromStr("10.0"), result.ResultMap[types.TestTokenPair].Price) 205 require.EqualValues(t, sdk.MustNewDecFromStr("1.0"), result.ResultMap[types.TestTokenPair].Quantity) 206 require.EqualValues(t, 2, len(result.ResultMap[types.TestTokenPair].Deals)) 207 require.EqualValues(t, order0.OrderID, result.ResultMap[types.TestTokenPair].Deals[0].OrderID) 208 require.EqualValues(t, order1.OrderID, result.ResultMap[types.TestTokenPair].Deals[1].OrderID) 209 210 // check account balance 211 acc0 := mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[0].Address) 212 acc1 := mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[1].Address) 213 expectCoins0 := sdk.SysCoins{ 214 sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("90")), // 100 - 10 215 sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("100.999")), // 100 + 1 * (1 - 0.001) 216 } 217 expectCoins1 := sdk.SysCoins{ 218 sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("104.7358")), // 100 + 5 * (1 - 0.001) - 0.2592 219 sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("97")), // 100 - 0.5 - 2.5 220 } 221 222 require.EqualValues(t, expectCoins0.String(), acc0.GetCoins().String()) 223 require.EqualValues(t, expectCoins1.String(), acc1.GetCoins().String()) 224 225 // ------- call EndBlock at height 11, continue filling ------- // 226 ctx = mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(11) 227 BeginBlocker(ctx, k) 228 EndBlocker(ctx, k) 229 230 // check product lock 231 lock = k.GetDexKeeper().GetLockedProductsCopy(ctx).Data[types.TestTokenPair] 232 require.Nil(t, lock) 233 234 // check order status 235 order2 = k.GetOrder(ctx, orders[2].OrderID) 236 require.EqualValues(t, types.OrderStatusOpen, order2.Status) 237 require.EqualValues(t, sdk.MustNewDecFromStr("2.0"), order2.RemainQuantity) 238 239 // check depth book 240 depthBook = k.GetDepthBookCopy(types.TestTokenPair) 241 require.EqualValues(t, sdk.MustNewDecFromStr("2.0"), depthBook.Items[0].SellQuantity) 242 243 // check block match result 244 result = k.GetBlockMatchResult() 245 require.EqualValues(t, 10, result.ResultMap[types.TestTokenPair].BlockHeight) 246 require.EqualValues(t, sdk.MustNewDecFromStr("10.0"), result.ResultMap[types.TestTokenPair].Price) 247 require.EqualValues(t, sdk.MustNewDecFromStr("1.0"), result.ResultMap[types.TestTokenPair].Quantity) 248 require.EqualValues(t, 1, len(result.ResultMap[types.TestTokenPair].Deals)) 249 require.EqualValues(t, order2.OrderID, result.ResultMap[types.TestTokenPair].Deals[0].OrderID) 250 251 // check account balance 252 acc0 = mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[0].Address) 253 acc1 = mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[1].Address) 254 expectCoins0 = sdk.SysCoins{ 255 sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("90")), // 100 - 10 256 sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("100.999")), // 100 + 1 * (1 - 0.001) 257 } 258 expectCoins1 = sdk.SysCoins{ 259 sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("109.7308")), // 100 + 10 * (1 - 0.001) - 0.2592 260 sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("97")), // 100 - 0.5 - 2.5 261 } 262 require.EqualValues(t, expectCoins0.String(), acc0.GetCoins().String()) 263 require.EqualValues(t, expectCoins1.String(), acc1.GetCoins().String()) 264 } 265 266 func TestEndBlockerDropExpireData(t *testing.T) { 267 mapp, addrKeysSlice := getMockApp(t, 2) 268 k := mapp.orderKeeper 269 mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 270 ctx := mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(10) 271 mapp.supplyKeeper.SetSupply(ctx, supply.NewSupply(mapp.TotalCoinsSupply)) 272 feeParams := types.DefaultTestParams() 273 mapp.orderKeeper.SetParams(ctx, &feeParams) 274 275 tokenPair := dex.GetBuiltInTokenPair() 276 err := mapp.dexKeeper.SaveTokenPair(ctx, tokenPair) 277 require.Nil(t, err) 278 279 // mock orders 280 orders := []*types.Order{ 281 types.MockOrder("", types.TestTokenPair, types.BuyOrder, "9.8", "1.0"), 282 types.MockOrder("", types.TestTokenPair, types.SellOrder, "10.0", "1.5"), 283 types.MockOrder("", types.TestTokenPair, types.BuyOrder, "10.0", "1.0"), 284 } 285 orders[0].Sender = addrKeysSlice[0].Address 286 orders[1].Sender = addrKeysSlice[1].Address 287 orders[2].Sender = addrKeysSlice[0].Address 288 for i := 0; i < 3; i++ { 289 err := k.PlaceOrder(ctx, orders[i]) 290 require.NoError(t, err) 291 } 292 293 EndBlocker(ctx, k) // update blockMatchResult, updatedOrderIds 294 295 // check before expire: order, blockOrderNum, blockMatchResult, updatedOrderIDs 296 require.NotNil(t, k.GetOrder(ctx, orders[1].OrderID)) 297 require.EqualValues(t, 3, k.GetBlockOrderNum(ctx, 10)) 298 blockMatchResult := k.GetBlockMatchResult() 299 require.NotNil(t, blockMatchResult) 300 updatedOrderIDs := k.GetUpdatedOrderIDs() 301 require.EqualValues(t, []string{orders[2].OrderID, orders[1].OrderID}, updatedOrderIDs) 302 303 ctx = mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(11) 304 EndBlocker(ctx, k) 305 // call EndBlocker to expire orders 306 ctx = mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(10 + feeParams.OrderExpireBlocks) 307 param := types.DefaultTestParams() 308 mapp.orderKeeper.SetParams(ctx, ¶m) 309 EndBlocker(ctx, k) 310 311 order0 := k.GetOrder(ctx, orders[0].OrderID) 312 order1 := k.GetOrder(ctx, orders[1].OrderID) 313 order2 := k.GetOrder(ctx, orders[2].OrderID) 314 315 require.EqualValues(t, types.OrderStatusExpired, order0.Status) 316 require.EqualValues(t, types.OrderStatusPartialFilledExpired, order1.Status) 317 require.Nil(t, order2) 318 319 // call EndBlocker to drop expire orders 320 ctx = mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(11 + feeParams.OrderExpireBlocks) 321 EndBlocker(ctx, k) 322 323 // check after expire: order, blockOrderNum, blockMatchResult, updatedOrderIDs 324 require.Nil(t, k.GetOrder(ctx, orders[0].OrderID)) 325 require.Nil(t, k.GetOrder(ctx, orders[1].OrderID)) 326 require.EqualValues(t, 0, k.GetBlockOrderNum(ctx, 10)) 327 } 328 329 // test order expire when product is busy 330 func TestEndBlockerExpireOrdersBusyProduct(t *testing.T) { 331 mapp, addrKeysSlice := getMockApp(t, 1) 332 k := mapp.orderKeeper 333 mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 334 ctx := mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(10) 335 mapp.supplyKeeper.SetSupply(ctx, supply.NewSupply(mapp.TotalCoinsSupply)) 336 feeParams := types.DefaultTestParams() 337 338 tokenPair := dex.GetBuiltInTokenPair() 339 err := mapp.dexKeeper.SaveTokenPair(ctx, tokenPair) 340 require.Nil(t, err) 341 mapp.orderKeeper.SetParams(ctx, &feeParams) 342 343 // mock orders 344 orders := []*types.Order{ 345 types.MockOrder("", types.TestTokenPair, types.SellOrder, "10.0", "2.0"), 346 } 347 orders[0].Sender = addrKeysSlice[0].Address 348 err = k.PlaceOrder(ctx, orders[0]) 349 require.NoError(t, err) 350 EndBlocker(ctx, k) 351 // call EndBlocker at 86400 + 9 352 ctx = mapp.BaseApp.NewContext(false, abci.Header{}). 353 WithBlockHeight(9 + feeParams.OrderExpireBlocks) 354 EndBlocker(ctx, k) 355 356 // call EndBlocker at 86400 + 10, lock product 357 ctx = mapp.BaseApp.NewContext(false, abci.Header{}). 358 WithBlockHeight(10 + feeParams.OrderExpireBlocks) 359 lock := &types.ProductLock{ 360 Price: sdk.MustNewDecFromStr("10.0"), 361 Quantity: sdk.MustNewDecFromStr("1.0"), 362 BuyExecuted: sdk.MustNewDecFromStr("1.0"), 363 SellExecuted: sdk.MustNewDecFromStr("1.0"), 364 } 365 k.SetProductLock(ctx, types.TestTokenPair, lock) 366 EndBlocker(ctx, k) 367 368 // check order 369 order := k.GetOrder(ctx, orders[0].OrderID) 370 require.EqualValues(t, types.OrderStatusOpen, order.Status) 371 require.EqualValues(t, 9+feeParams.OrderExpireBlocks, k.GetLastExpiredBlockHeight(ctx)) 372 373 // call EndBlocker at 86400 + 11, unlock product 374 ctx = mapp.BaseApp.NewContext(false, abci.Header{}). 375 WithBlockHeight(11 + feeParams.OrderExpireBlocks) 376 k.UnlockProduct(ctx, types.TestTokenPair) 377 EndBlocker(ctx, k) 378 379 // check order 380 order = k.GetOrder(ctx, orders[0].OrderID) 381 require.EqualValues(t, types.OrderStatusExpired, order.Status) 382 require.EqualValues(t, 11+feeParams.OrderExpireBlocks, k.GetLastExpiredBlockHeight(ctx)) 383 } 384 385 //func TestEndBlockerExpireOrders(t *testing.T) { 386 // mapp, addrKeysSlice := getMockApp(t, 3) 387 // k := mapp.orderKeeper 388 // mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 389 // 390 // var startHeight int64 = 10 391 // ctx := mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(startHeight) 392 // mapp.supplyKeeper.SetSupply(ctx, supply.NewSupply(mapp.TotalCoinsSupply)) 393 // 394 // feeParams := types.DefaultTestParams() 395 // 396 // tokenPair := dex.GetBuiltInTokenPair() 397 // err := mapp.dexKeeper.SaveTokenPair(ctx, tokenPair) 398 // require.Nil(t, err) 399 // 400 // tokenPairDex := dex.GetBuiltInTokenPair() 401 // err = mapp.dexKeeper.SaveTokenPair(ctx, tokenPairDex) 402 // require.Nil(t, err) 403 // mapp.dexKeeper.SetOperator(ctx, dex.DEXOperator{ 404 // Address: tokenPair.Owner, 405 // HandlingFeeAddress: tokenPair.Owner, 406 // }) 407 // 408 // mapp.orderKeeper.SetParams(ctx, &feeParams) 409 // EndBlocker(ctx, k) 410 // 411 // // mock orders 412 // orders := []*types.Order{ 413 // types.MockOrder(types.FormatOrderID(startHeight, 1), types.TestTokenPair, types.BuyOrder, "9.8", "1.0"), 414 // types.MockOrder(types.FormatOrderID(startHeight, 2), types.TestTokenPair, types.SellOrder, "10.0", "1.0"), 415 // types.MockOrder(types.FormatOrderID(startHeight, 3), types.TestTokenPair, types.BuyOrder, "10.0", "0.5"), 416 // } 417 // orders[0].Sender = addrKeysSlice[0].Address 418 // orders[1].Sender = addrKeysSlice[1].Address 419 // orders[2].Sender = addrKeysSlice[2].Address 420 // for i := 0; i < 3; i++ { 421 // err := k.PlaceOrder(ctx, orders[i]) 422 // require.NoError(t, err) 423 // } 424 // EndBlocker(ctx, k) 425 // 426 // // check account balance 427 // acc0 := mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[0].Address) 428 // acc1 := mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[1].Address) 429 // expectCoins0 := sdk.SysCoins{ 430 // // 100 - 9.8 - 0.2592 = 89.9408 431 // sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("89.9408")), 432 // sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("100")), 433 // } 434 // expectCoins1 := sdk.SysCoins{ 435 // // 100 + 10 * 0.5 * (1 - 0.001) - 0.2592 = 104.7408 436 // sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("104.7358")), 437 // sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("99")), 438 // } 439 // require.EqualValues(t, expectCoins0.String(), acc0.GetCoins().String()) 440 // require.EqualValues(t, expectCoins1.String(), acc1.GetCoins().String()) 441 // 442 // // check depth book 443 // depthBook := k.GetDepthBookCopy(types.TestTokenPair) 444 // require.EqualValues(t, 2, len(depthBook.Items)) 445 // 446 // // call EndBlocker to expire orders 447 // mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 448 // ctx = mapp.BaseApp.NewContext(false, abci.Header{}). 449 // WithBlockHeight(startHeight + feeParams.OrderExpireBlocks) 450 // 451 // EndBlocker(ctx, k) 452 // 453 // // check order status 454 // order0 := k.GetOrder(ctx, orders[0].OrderID) 455 // order1 := k.GetOrder(ctx, orders[1].OrderID) 456 // require.EqualValues(t, types.OrderStatusExpired, order0.Status) 457 // require.EqualValues(t, types.OrderStatusPartialFilledExpired, order1.Status) 458 // 459 // // check depth book 460 // depthBook = k.GetDepthBookCopy(types.TestTokenPair) 461 // require.EqualValues(t, 0, len(depthBook.Items)) 462 // // check order ids 463 // key := types.FormatOrderIDsKey(types.TestTokenPair, sdk.MustNewDecFromStr("9.8"), types.BuyOrder) 464 // orderIDs := k.GetProductPriceOrderIDs(key) 465 // require.EqualValues(t, 0, len(orderIDs)) 466 // // check updated order ids 467 // updatedOrderIDs := k.GetUpdatedOrderIDs() 468 // require.EqualValues(t, 2, len(updatedOrderIDs)) 469 // require.EqualValues(t, orders[0].OrderID, updatedOrderIDs[0]) 470 // // check closed order id 471 // closedOrderIDs := k.GetDiskCache().GetClosedOrderIDs() 472 // require.Equal(t, 2, len(closedOrderIDs)) 473 // require.Equal(t, orders[0].OrderID, closedOrderIDs[0]) 474 // 475 // // check account balance 476 // acc0 = mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[0].Address) 477 // acc1 = mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[1].Address) 478 // expectCoins0 = sdk.SysCoins{ 479 // sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("99.7408")), // 100 - 0.2592 480 // sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("100")), 481 // } 482 // expectCoins1 = sdk.SysCoins{ 483 // // 100 + 10 * 0.5 * (1 - 0.001) - 0.2592 484 // sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("104.7358")), 485 // sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("99.5")), 486 // } 487 // require.EqualValues(t, expectCoins0.String(), acc0.GetCoins().String()) 488 // require.EqualValues(t, expectCoins1.String(), acc1.GetCoins().String()) 489 // 490 // // check fee pool 491 // feeCollector := mapp.supplyKeeper.GetModuleAccount(ctx, auth.FeeCollectorName) 492 // collectedFees := feeCollector.GetCoins() 493 // // 0.2592 + 0.2592 494 // require.EqualValues(t, "0.518400000000000000"+common.NativeToken, collectedFees.String()) 495 //} 496 497 func TestEndBlockerCleanupOrdersWhoseTokenPairHaveBeenDelisted(t *testing.T) { 498 mapp, addrKeysSlice := getMockApp(t, 2) 499 k := mapp.orderKeeper 500 mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 501 502 var startHeight int64 = 10 503 ctx := mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(startHeight) 504 mapp.supplyKeeper.SetSupply(ctx, supply.NewSupply(mapp.TotalCoinsSupply)) 505 506 feeParams := types.DefaultTestParams() 507 mapp.orderKeeper.SetParams(ctx, &feeParams) 508 509 // mock orders 510 orders := []*types.Order{ 511 types.MockOrder(types.FormatOrderID(startHeight, 1), types.TestTokenPair, types.BuyOrder, "10.0", "1.0"), 512 types.MockOrder(types.FormatOrderID(startHeight, 2), types.TestTokenPair, types.SellOrder, "10.0", "0.5"), 513 types.MockOrder(types.FormatOrderID(startHeight, 3), types.TestTokenPair, types.SellOrder, "10.0", "2.5"), 514 } 515 orders[0].Sender = addrKeysSlice[0].Address 516 orders[1].Sender = addrKeysSlice[1].Address 517 orders[2].Sender = addrKeysSlice[1].Address 518 for i := 0; i < 3; i++ { 519 err := k.PlaceOrder(ctx, orders[i]) 520 require.NoError(t, err) 521 } 522 523 // call EndBlocker to execute periodic match 524 EndBlocker(ctx, k) 525 526 // check depth book 527 depthBook := k.GetDepthBookCopy(types.TestTokenPair) 528 require.EqualValues(t, 0, len(depthBook.Items)) 529 530 depthBookDB := k.GetDepthBookFromDB(ctx, types.TestTokenPair) 531 require.EqualValues(t, 0, len(depthBookDB.Items)) 532 533 // check product price - order ids 534 key := types.FormatOrderIDsKey(types.TestTokenPair, sdk.MustNewDecFromStr("10.0"), types.SellOrder) 535 orderIDs := k.GetProductPriceOrderIDs(key) 536 require.EqualValues(t, 0, len(orderIDs)) 537 538 key = types.FormatOrderIDsKey(types.TestTokenPair, sdk.MustNewDecFromStr("10.0"), types.BuyOrder) 539 orderIDs = k.GetProductPriceOrderIDs(key) 540 require.EqualValues(t, 0, len(orderIDs)) 541 542 // check closed order id 543 closedOrderIDs := k.GetLastClosedOrderIDs(ctx) 544 require.Equal(t, 3, len(closedOrderIDs)) 545 require.Equal(t, orders[0].OrderID, closedOrderIDs[0]) 546 require.Equal(t, orders[1].OrderID, closedOrderIDs[1]) 547 require.Equal(t, orders[2].OrderID, closedOrderIDs[2]) 548 549 // check account balance 550 acc0 := mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[0].Address) 551 acc1 := mapp.AccountKeeper.GetAccount(ctx, addrKeysSlice[1].Address) 552 expectCoins0 := sdk.SysCoins{ 553 sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("100")), 554 sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("100")), 555 } 556 expectCoins1 := sdk.SysCoins{ 557 sdk.NewDecCoinFromDec(common.NativeToken, sdk.MustNewDecFromStr("100")), 558 sdk.NewDecCoinFromDec(common.TestToken, sdk.MustNewDecFromStr("100")), 559 } 560 require.EqualValues(t, expectCoins0.String(), acc0.GetCoins().String()) 561 require.EqualValues(t, expectCoins1.String(), acc1.GetCoins().String()) 562 563 // check fee pool 564 feeCollector := mapp.supplyKeeper.GetModuleAccount(ctx, auth.FeeCollectorName) 565 collectedFees := feeCollector.GetCoins() 566 require.EqualValues(t, "", collectedFees.String()) 567 } 568 569 func TestFillPrecision(t *testing.T) { 570 mapp, addrKeysSlice := getMockApp(t, 2) 571 k := mapp.orderKeeper 572 mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 573 574 var startHeight int64 = 10 575 ctx := mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(startHeight) 576 BeginBlocker(ctx, k) 577 578 mapp.supplyKeeper.SetSupply(ctx, supply.NewSupply(mapp.TotalCoinsSupply)) 579 feeParams := types.DefaultParams() 580 mapp.orderKeeper.SetParams(ctx, &feeParams) 581 582 tokenPair := dex.GetBuiltInTokenPair() 583 err := mapp.dexKeeper.SaveTokenPair(ctx, tokenPair) 584 require.Nil(t, err) 585 586 // mock orders 587 orderIdx := 0 588 roundN := 1 // Need more balance to make a large round 589 orderNums := 20 590 var orders []*types.Order 591 592 for j := 0; j < roundN; j++ { 593 rand.Seed(time.Now().Unix()) 594 price := float64(25000+rand.Intn(5000)) / 10000 595 596 for i := 0; i < orderNums; i++ { 597 var buyPrice string 598 var sellPrice string 599 var quantity string 600 601 rand.Seed(time.Now().Unix() + int64(orderIdx)) 602 603 // Test Same precision of price and quantity 604 quantity = strconv.FormatFloat(float64(rand.Intn(99999))/100000, 'f', 4, 64) 605 buyPrice = strconv.FormatFloat(price+0.0001, 'f', 4, 64) 606 sellPrice = strconv.FormatFloat(price, 'f', 4, 64) 607 608 tmp, err := strconv.ParseFloat(quantity, 64) 609 if tmp == 0.0 { 610 continue 611 } 612 613 orderIdx += 1 614 buyOrder := types.MockOrder(types.FormatOrderID(startHeight, int64(orderIdx)), types.TestTokenPair, types.BuyOrder, buyPrice, quantity) 615 orderIdx += 1 616 sellOrder := types.MockOrder(types.FormatOrderID(startHeight, int64(orderIdx)), types.TestTokenPair, types.SellOrder, sellPrice, quantity) 617 618 buyOrder.Sender = addrKeysSlice[0].Address 619 sellOrder.Sender = addrKeysSlice[1].Address 620 621 orders = append(orders, buyOrder, sellOrder) 622 err = k.PlaceOrder(ctx, buyOrder) 623 require.NoError(t, err) 624 625 orders = append(orders, sellOrder) 626 err = k.PlaceOrder(ctx, sellOrder) 627 } 628 } 629 // call EndBlocker to execute periodic match 630 EndBlocker(ctx, k) 631 632 N := len(orders) / 1000 633 for i := 0; i < N; i++ { 634 ctx = mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(startHeight + int64(1+i)) 635 BeginBlocker(ctx, k) 636 EndBlocker(ctx, k) 637 } 638 639 invaFunc := keeper.ModuleAccountInvariant(mapp.orderKeeper) 640 _, isInval := invaFunc(ctx) 641 require.EqualValues(t, false, isInval) 642 } 643 644 func buildRandomOrderMsg(addr sdk.AccAddress) MsgNewOrders { 645 price := strconv.Itoa(rand.Intn(10) + 100) 646 orderItems := []types.OrderItem{ 647 types.NewOrderItem(types.TestTokenPair, types.BuyOrder, price, "1.0"), 648 } 649 msg := types.NewMsgNewOrders(addr, orderItems) 650 return msg 651 652 } 653 654 //func TestEndBlocker(t *testing.T) { 655 // mapp, addrKeysSlice := getMockAppWithBalance(t, 2, 100000000) 656 // k := mapp.orderKeeper 657 // mapp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 658 // 659 // var startHeight int64 = 10 660 // ctx := mapp.BaseApp.NewContext(false, abci.Header{}).WithBlockHeight(startHeight) 661 // mapp.supplyKeeper.SetSupply(ctx, supply.NewSupply(mapp.TotalCoinsSupply)) 662 // 663 // feeParams := types.DefaultTestParams() 664 // mapp.orderKeeper.SetParams(ctx, &feeParams) 665 // 666 // tokenPair := dex.GetBuiltInTokenPair() 667 // err := mapp.dexKeeper.SaveTokenPair(ctx, tokenPair) 668 // require.Nil(t, err) 669 // 670 // handler := NewOrderHandler(k) 671 // 672 // blockHeight := startHeight 673 // for i := 0; i < 100000; i++ { 674 // msg := buildRandomOrderMsg(addrKeysSlice[0].Address) 675 // result, err := handler(ctx, msg) 676 // if (i+1)%1000 == 0 { 677 // blockHeight = blockHeight + 1 678 // ctx.SetBlockHeight(blockHeight) 679 // } 680 // require.Nil(t, err) 681 // require.EqualValues(t, "", result.Log) 682 // } 683 // // call EndBlocker to execute periodic match 684 // EndBlocker(ctx, k) 685 // 686 // quantityList := [3]string{"200", "500", "1000"} 687 // for _, quantity := range quantityList { 688 // startTime := time.Now() 689 // blockHeight = blockHeight + 1 690 // ctx.SetBlockHeight(blockHeight) 691 // orderItems := []types.OrderItem{ 692 // types.NewOrderItem(types.TestTokenPair, types.SellOrder, "100", quantity), 693 // } 694 // msg := types.NewMsgNewOrders(addrKeysSlice[1].Address, orderItems) 695 // handler(ctx, msg) 696 // EndBlocker(ctx, k) 697 // fmt.Println(time.Since(startTime)) 698 // fmt.Println(k.GetOrder(ctx, types.FormatOrderID(blockHeight, 1))) 699 // } 700 //}