github.com/gravity-devs/liquidity@v1.5.3/x/liquidity/types/swap_test.go (about) 1 package types_test 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "testing" 7 8 sdk "github.com/cosmos/cosmos-sdk/types" 9 "github.com/stretchr/testify/require" 10 11 "github.com/gravity-devs/liquidity/app" 12 "github.com/gravity-devs/liquidity/x/liquidity" 13 "github.com/gravity-devs/liquidity/x/liquidity/types" 14 ) 15 16 func TestSwapScenario(t *testing.T) { 17 // init test app and context 18 simapp, ctx := app.CreateTestInput() 19 simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams()) 20 params := simapp.LiquidityKeeper.GetParams(ctx) 21 22 // define test denom X, Y for Liquidity Pool 23 denomX, denomY := types.AlphabeticalDenomPair(DenomX, DenomY) 24 X := params.MinInitDepositAmount 25 Y := params.MinInitDepositAmount 26 27 // init addresses for the test 28 addrs := app.AddTestAddrs(simapp, ctx, 20, params.PoolCreationFee) 29 30 // Create pool 31 // The create pool msg is not run in batch, but is processed immediately. 32 poolID := app.TestCreatePool(t, simapp, ctx, X, Y, denomX, denomY, addrs[0]) 33 34 // In case of deposit, withdraw, and swap msg, unlike other normal tx msgs, 35 // collect them in the batch and perform an execution at once at the endblock. 36 37 // add a deposit to pool and run batch execution on endblock 38 app.TestDepositPool(t, simapp, ctx, X, Y, addrs[1:2], poolID, true) 39 40 // next block, reinitialize batch and increase batchIndex at beginBlocker, 41 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 42 liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper) 43 44 // Create swap msg for test purposes and put it in the batch. 45 price, _ := sdk.NewDecFromStr("1.1") 46 priceY, _ := sdk.NewDecFromStr("1.2") 47 xOfferCoins := []sdk.Coin{sdk.NewCoin(denomX, sdk.NewInt(10000))} 48 yOfferCoins := []sdk.Coin{sdk.NewCoin(denomY, sdk.NewInt(5000))} 49 xOrderPrices := []sdk.Dec{price} 50 yOrderPrices := []sdk.Dec{priceY} 51 xOrderAddrs := addrs[1:2] 52 yOrderAddrs := addrs[2:3] 53 _, batch := app.TestSwapPool(t, simapp, ctx, xOfferCoins, xOrderPrices, xOrderAddrs, poolID, false) 54 _, batch = app.TestSwapPool(t, simapp, ctx, xOfferCoins, xOrderPrices, xOrderAddrs, poolID, false) 55 _, batch = app.TestSwapPool(t, simapp, ctx, xOfferCoins, xOrderPrices, xOrderAddrs, poolID, false) 56 _, batch = app.TestSwapPool(t, simapp, ctx, yOfferCoins, yOrderPrices, yOrderAddrs, poolID, false) 57 58 // Set the execution status flag of messages to true. 59 msgs := simapp.LiquidityKeeper.GetAllPoolBatchSwapMsgStatesAsPointer(ctx, batch) 60 for _, msg := range msgs { 61 msg.Executed = true 62 } 63 simapp.LiquidityKeeper.SetPoolBatchSwapMsgStatesByPointer(ctx, poolID, msgs) 64 65 // Generate an orderbook by arranging swap messages in order price 66 orderMap, xToY, yToX := types.MakeOrderMap(msgs, denomX, denomY, false) 67 orderBook := orderMap.SortOrderBook() 68 currentPrice := X.Quo(Y).ToDec() 69 require.Equal(t, orderMap[xOrderPrices[0].String()].BuyOfferAmt, xOfferCoins[0].Amount.MulRaw(3)) 70 require.Equal(t, orderMap[xOrderPrices[0].String()].Price, xOrderPrices[0]) 71 72 require.Equal(t, 3, len(xToY)) 73 require.Equal(t, 1, len(yToX)) 74 require.Equal(t, 3, len(orderMap[xOrderPrices[0].String()].SwapMsgStates)) 75 require.Equal(t, 1, len(orderMap[yOrderPrices[0].String()].SwapMsgStates)) 76 require.Equal(t, 3, len(orderBook[0].SwapMsgStates)) 77 require.Equal(t, 1, len(orderBook[1].SwapMsgStates)) 78 79 require.Equal(t, len(orderBook), orderBook.Len()) 80 81 fmt.Println(orderBook, currentPrice) 82 fmt.Println(xToY, yToX) 83 84 types.ValidateStateAndExpireOrders(xToY, ctx.BlockHeight(), false) 85 types.ValidateStateAndExpireOrders(yToX, ctx.BlockHeight(), false) 86 87 // The price and coins of swap messages in orderbook are calculated 88 // to derive match result with the price direction. 89 result, found := orderBook.Match(X.ToDec(), Y.ToDec()) 90 require.True(t, found) 91 require.NotEqual(t, types.NoMatch, result.MatchType) 92 93 matchResultXtoY, poolXDeltaXtoY, poolYDeltaXtoY := types.FindOrderMatch(types.DirectionXtoY, xToY, result.EX, 94 result.SwapPrice, ctx.BlockHeight()) 95 matchResultYtoX, poolXDeltaYtoX, poolYDeltaYtoX := types.FindOrderMatch(types.DirectionYtoX, yToX, result.EY, 96 result.SwapPrice, ctx.BlockHeight()) 97 98 xToY, yToX, XDec, YDec, poolXDelta2, poolYDelta2 := 99 types.UpdateSwapMsgStates(X.ToDec(), Y.ToDec(), xToY, yToX, matchResultXtoY, matchResultYtoX) 100 101 require.Equal(t, 0, types.CountNotMatchedMsgs(xToY)) 102 require.Equal(t, 0, types.CountFractionalMatchedMsgs(xToY)) 103 require.Equal(t, 1, types.CountNotMatchedMsgs(yToX)) 104 require.Equal(t, 0, types.CountFractionalMatchedMsgs(yToX)) 105 require.Equal(t, 3, len(xToY)) 106 require.Equal(t, 1, len(yToX)) 107 108 fmt.Println(matchResultXtoY) 109 fmt.Println(poolXDeltaXtoY) 110 fmt.Println(poolYDeltaXtoY) 111 112 fmt.Println(poolXDeltaYtoX, poolYDeltaYtoX) 113 fmt.Println(poolXDelta2, poolYDelta2) 114 fmt.Println(XDec, YDec) 115 116 // Verify swap result by creating an orderbook with remaining messages that have been matched and not transacted. 117 orderMapExecuted, _, _ := types.MakeOrderMap(append(xToY, yToX...), denomX, denomY, true) 118 orderBookExecuted := orderMapExecuted.SortOrderBook() 119 lastPrice := XDec.Quo(YDec) 120 fmt.Println("lastPrice", lastPrice) 121 fmt.Println("X", XDec) 122 fmt.Println("Y", YDec) 123 require.True(t, orderBookExecuted.Validate(lastPrice)) 124 125 require.Equal(t, 0, types.CountNotMatchedMsgs(orderMapExecuted[xOrderPrices[0].String()].SwapMsgStates)) 126 require.Equal(t, 1, types.CountNotMatchedMsgs(orderMapExecuted[yOrderPrices[0].String()].SwapMsgStates)) 127 require.Equal(t, 1, types.CountNotMatchedMsgs(orderBookExecuted[0].SwapMsgStates)) 128 129 types.ValidateStateAndExpireOrders(xToY, ctx.BlockHeight(), true) 130 types.ValidateStateAndExpireOrders(yToX, ctx.BlockHeight(), true) 131 132 orderMapCleared, _, _ := types.MakeOrderMap(append(xToY, yToX...), denomX, denomY, true) 133 orderBookCleared := orderMapCleared.SortOrderBook() 134 require.True(t, orderBookCleared.Validate(lastPrice)) 135 136 require.Equal(t, 0, types.CountNotMatchedMsgs(orderMapCleared[xOrderPrices[0].String()].SwapMsgStates)) 137 require.Equal(t, 0, types.CountNotMatchedMsgs(orderMapCleared[yOrderPrices[0].String()].SwapMsgStates)) 138 require.Equal(t, 0, len(orderBookCleared)) 139 140 // next block 141 liquidity.EndBlocker(ctx, simapp.LiquidityKeeper) 142 143 // test genesisState with export, init 144 genesis := simapp.LiquidityKeeper.ExportGenesis(ctx) 145 simapp.LiquidityKeeper.InitGenesis(ctx, *genesis) 146 err := types.ValidateGenesis(*genesis) 147 require.NoError(t, err) 148 genesisNew := simapp.LiquidityKeeper.ExportGenesis(ctx) 149 err = types.ValidateGenesis(*genesisNew) 150 require.NoError(t, err) 151 require.Equal(t, genesis, genesisNew) 152 for _, record := range genesisNew.PoolRecords { 153 err = record.Validate() 154 require.NoError(t, err) 155 } 156 157 // validate genesis fail case 158 batch.DepositMsgIndex = 0 159 simapp.LiquidityKeeper.SetPoolBatch(ctx, batch) 160 genesisNew = simapp.LiquidityKeeper.ExportGenesis(ctx) 161 err = types.ValidateGenesis(*genesisNew) 162 require.ErrorIs(t, err, types.ErrBadBatchMsgIndex) 163 batch.WithdrawMsgIndex = 0 164 simapp.LiquidityKeeper.SetPoolBatch(ctx, batch) 165 genesisNew = simapp.LiquidityKeeper.ExportGenesis(ctx) 166 err = types.ValidateGenesis(*genesisNew) 167 require.ErrorIs(t, err, types.ErrBadBatchMsgIndex) 168 batch.SwapMsgIndex = 20 169 simapp.LiquidityKeeper.SetPoolBatch(ctx, batch) 170 genesisNew = simapp.LiquidityKeeper.ExportGenesis(ctx) 171 err = types.ValidateGenesis(*genesisNew) 172 require.ErrorIs(t, err, types.ErrBadBatchMsgIndex) 173 } 174 175 func TestMaxOrderRatio(t *testing.T) { 176 simapp, ctx := app.CreateTestInput() 177 simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams()) 178 params := simapp.LiquidityKeeper.GetParams(ctx) 179 180 // define test denom X, Y for Liquidity Pool 181 denomX, denomY := types.AlphabeticalDenomPair(DenomX, DenomY) 182 183 X := params.MinInitDepositAmount 184 Y := params.MinInitDepositAmount 185 186 addrs := app.AddTestAddrs(simapp, ctx, 20, params.PoolCreationFee) 187 poolID := app.TestCreatePool(t, simapp, ctx, X, Y, denomX, denomY, addrs[0]) 188 189 // begin block, init 190 app.TestDepositPool(t, simapp, ctx, X, Y, addrs[1:2], poolID, true) 191 192 // next block 193 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 194 liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper) 195 196 maxOrderRatio := params.MaxOrderAmountRatio 197 198 // Success case, not exceed GetMaxOrderRatio orders 199 priceBuy, _ := sdk.NewDecFromStr("1.1") 200 priceSell, _ := sdk.NewDecFromStr("1.2") 201 202 offerCoin := sdk.NewCoin(denomX, sdk.NewInt(1000)) 203 offerCoinY := sdk.NewCoin(denomY, sdk.NewInt(1000)) 204 205 app.SaveAccountWithFee(simapp, ctx, addrs[1], sdk.NewCoins(offerCoin), offerCoin) 206 app.SaveAccountWithFee(simapp, ctx, addrs[2], sdk.NewCoins(offerCoinY), offerCoinY) 207 208 msgBuy := types.NewMsgSwapWithinBatch(addrs[1], poolID, DefaultSwapTypeId, offerCoin, DenomY, priceBuy, params.SwapFeeRate) 209 msgSell := types.NewMsgSwapWithinBatch(addrs[2], poolID, DefaultSwapTypeId, offerCoinY, DenomX, priceSell, params.SwapFeeRate) 210 211 _, err := simapp.LiquidityKeeper.SwapWithinBatch(ctx, msgBuy, 0) 212 require.NoError(t, err) 213 214 _, err = simapp.LiquidityKeeper.SwapWithinBatch(ctx, msgSell, 0) 215 require.NoError(t, err) 216 217 // Fail case, exceed GetMaxOrderRatio orders 218 offerCoin = sdk.NewCoin(denomX, X) 219 offerCoinY = sdk.NewCoin(denomY, Y) 220 221 app.SaveAccountWithFee(simapp, ctx, addrs[1], sdk.NewCoins(offerCoin), offerCoin) 222 app.SaveAccountWithFee(simapp, ctx, addrs[2], sdk.NewCoins(offerCoinY), offerCoinY) 223 224 msgBuy = types.NewMsgSwapWithinBatch(addrs[1], poolID, DefaultSwapTypeId, offerCoin, DenomY, priceBuy, params.SwapFeeRate) 225 msgSell = types.NewMsgSwapWithinBatch(addrs[2], poolID, DefaultSwapTypeId, offerCoinY, DenomX, priceSell, params.SwapFeeRate) 226 227 _, err = simapp.LiquidityKeeper.SwapWithinBatch(ctx, msgBuy, 0) 228 require.Equal(t, types.ErrExceededMaxOrderable, err) 229 230 _, err = simapp.LiquidityKeeper.SwapWithinBatch(ctx, msgSell, 0) 231 require.Equal(t, types.ErrExceededMaxOrderable, err) 232 233 // Success case, same GetMaxOrderRatio orders 234 offerCoin = sdk.NewCoin(denomX, X.ToDec().Mul(maxOrderRatio).TruncateInt()) 235 offerCoinY = sdk.NewCoin(denomY, Y.ToDec().Mul(maxOrderRatio).TruncateInt()) 236 237 app.SaveAccountWithFee(simapp, ctx, addrs[1], sdk.NewCoins(offerCoin), offerCoin) 238 app.SaveAccountWithFee(simapp, ctx, addrs[2], sdk.NewCoins(offerCoinY), offerCoinY) 239 240 msgBuy = types.NewMsgSwapWithinBatch(addrs[1], poolID, DefaultSwapTypeId, offerCoin, DenomY, priceBuy, params.SwapFeeRate) 241 msgSell = types.NewMsgSwapWithinBatch(addrs[2], poolID, DefaultSwapTypeId, offerCoinY, DenomX, priceSell, params.SwapFeeRate) 242 243 _, err = simapp.LiquidityKeeper.SwapWithinBatch(ctx, msgBuy, 0) 244 require.NoError(t, err) 245 246 _, err = simapp.LiquidityKeeper.SwapWithinBatch(ctx, msgSell, 0) 247 require.NoError(t, err) 248 249 // Success case, same GetMaxOrderRatio orders 250 offerCoin = sdk.NewCoin(denomX, X.ToDec().Mul(maxOrderRatio).TruncateInt().AddRaw(1)) 251 offerCoinY = sdk.NewCoin(denomY, Y.ToDec().Mul(maxOrderRatio).TruncateInt().AddRaw(1)) 252 253 offerCoin = sdk.NewCoin(denomX, params.MinInitDepositAmount.Quo(sdk.NewInt(2))) 254 offerCoinY = sdk.NewCoin(denomY, params.MinInitDepositAmount.Quo(sdk.NewInt(10))) 255 app.SaveAccountWithFee(simapp, ctx, addrs[1], sdk.NewCoins(offerCoin), offerCoin) 256 app.SaveAccountWithFee(simapp, ctx, addrs[2], sdk.NewCoins(offerCoinY), offerCoinY) 257 258 msgBuy = types.NewMsgSwapWithinBatch(addrs[1], poolID, DefaultSwapTypeId, offerCoin, DenomY, priceBuy, params.SwapFeeRate) 259 msgSell = types.NewMsgSwapWithinBatch(addrs[2], poolID, DefaultSwapTypeId, offerCoinY, DenomX, priceSell, params.SwapFeeRate) 260 261 _, err = simapp.LiquidityKeeper.SwapWithinBatch(ctx, msgBuy, 0) 262 require.Equal(t, types.ErrExceededMaxOrderable, err) 263 264 _, err = simapp.LiquidityKeeper.SwapWithinBatch(ctx, msgSell, 0) 265 require.NoError(t, err) 266 } 267 268 func TestOrderBookSort(t *testing.T) { 269 orderMap := make(types.OrderMap) 270 a, _ := sdk.NewDecFromStr("0.1") 271 b, _ := sdk.NewDecFromStr("0.2") 272 c, _ := sdk.NewDecFromStr("0.3") 273 orderMap[a.String()] = types.Order{ 274 Price: a, 275 BuyOfferAmt: sdk.ZeroInt(), 276 SellOfferAmt: sdk.ZeroInt(), 277 } 278 orderMap[b.String()] = types.Order{ 279 Price: b, 280 BuyOfferAmt: sdk.ZeroInt(), 281 SellOfferAmt: sdk.ZeroInt(), 282 } 283 orderMap[c.String()] = types.Order{ 284 Price: c, 285 BuyOfferAmt: sdk.ZeroInt(), 286 SellOfferAmt: sdk.ZeroInt(), 287 } 288 // make orderbook to sort orderMap 289 orderBook := orderMap.SortOrderBook() 290 fmt.Println(orderBook) 291 292 res := orderBook.Less(0, 1) 293 require.True(t, res) 294 res = orderBook.Less(1, 2) 295 require.True(t, res) 296 res = orderBook.Less(2, 1) 297 require.False(t, res) 298 299 orderBook.Swap(1, 2) 300 fmt.Println(orderBook) 301 require.Equal(t, c, orderBook[1].Price) 302 require.Equal(t, b, orderBook[2].Price) 303 304 orderBook.Sort() 305 fmt.Println(orderBook) 306 require.Equal(t, a, orderBook[0].Price) 307 require.Equal(t, b, orderBook[1].Price) 308 require.Equal(t, c, orderBook[2].Price) 309 310 orderBook.Reverse() 311 fmt.Println(orderBook) 312 require.Equal(t, a, orderBook[2].Price) 313 require.Equal(t, b, orderBook[1].Price) 314 require.Equal(t, c, orderBook[0].Price) 315 } 316 317 func TestExecutableAmt(t *testing.T) { 318 orderMap := make(types.OrderMap) 319 a, _ := sdk.NewDecFromStr("0.1") 320 b, _ := sdk.NewDecFromStr("0.2") 321 c, _ := sdk.NewDecFromStr("0.3") 322 orderMap[a.String()] = types.Order{ 323 Price: a, 324 BuyOfferAmt: sdk.ZeroInt(), 325 SellOfferAmt: sdk.NewInt(30000000), 326 } 327 orderMap[b.String()] = types.Order{ 328 Price: b, 329 BuyOfferAmt: sdk.NewInt(90000000), 330 SellOfferAmt: sdk.ZeroInt(), 331 } 332 orderMap[c.String()] = types.Order{ 333 Price: c, 334 BuyOfferAmt: sdk.NewInt(50000000), 335 SellOfferAmt: sdk.ZeroInt(), 336 } 337 // make orderbook to sort orderMap 338 orderBook := orderMap.SortOrderBook() 339 340 executableBuyAmtX, executableSellAmtY := orderBook.ExecutableAmt(b) 341 require.Equal(t, sdk.NewInt(140000000), executableBuyAmtX) 342 require.Equal(t, sdk.NewInt(30000000), executableSellAmtY) 343 } 344 345 func TestPriceDirection(t *testing.T) { 346 // increase case 347 orderMap := make(types.OrderMap) 348 a, _ := sdk.NewDecFromStr("1") 349 b, _ := sdk.NewDecFromStr("1.1") 350 c, _ := sdk.NewDecFromStr("1.2") 351 orderMap[a.String()] = types.Order{ 352 Price: a, 353 BuyOfferAmt: sdk.NewInt(40000000), 354 SellOfferAmt: sdk.ZeroInt(), 355 } 356 orderMap[b.String()] = types.Order{ 357 Price: b, 358 BuyOfferAmt: sdk.NewInt(40000000), 359 SellOfferAmt: sdk.ZeroInt(), 360 } 361 orderMap[c.String()] = types.Order{ 362 Price: c, 363 BuyOfferAmt: sdk.ZeroInt(), 364 SellOfferAmt: sdk.NewInt(20000000), 365 } 366 // make orderbook to sort orderMap 367 orderBook := orderMap.SortOrderBook() 368 poolPrice, _ := sdk.NewDecFromStr("1.0") 369 result := orderBook.PriceDirection(poolPrice) 370 require.Equal(t, types.Increasing, result) 371 372 // decrease case 373 orderMap = make(types.OrderMap) 374 a, _ = sdk.NewDecFromStr("0.7") 375 b, _ = sdk.NewDecFromStr("0.9") 376 c, _ = sdk.NewDecFromStr("0.8") 377 orderMap[a.String()] = types.Order{ 378 Price: a, 379 BuyOfferAmt: sdk.NewInt(20000000), 380 SellOfferAmt: sdk.ZeroInt(), 381 } 382 orderMap[b.String()] = types.Order{ 383 Price: b, 384 BuyOfferAmt: sdk.ZeroInt(), 385 SellOfferAmt: sdk.NewInt(40000000), 386 } 387 orderMap[c.String()] = types.Order{ 388 Price: c, 389 BuyOfferAmt: sdk.NewInt(10000000), 390 SellOfferAmt: sdk.ZeroInt(), 391 } 392 // make orderbook to sort orderMap 393 orderBook = orderMap.SortOrderBook() 394 poolPrice, _ = sdk.NewDecFromStr("1.0") 395 result = orderBook.PriceDirection(poolPrice) 396 require.Equal(t, types.Decreasing, result) 397 398 // stay case 399 orderMap = make(types.OrderMap) 400 a, _ = sdk.NewDecFromStr("1.0") 401 402 orderMap[a.String()] = types.Order{ 403 Price: a, 404 BuyOfferAmt: sdk.NewInt(50000000), 405 SellOfferAmt: sdk.NewInt(50000000), 406 } 407 orderBook = orderMap.SortOrderBook() 408 poolPrice, _ = sdk.NewDecFromStr("1.0") 409 result = orderBook.PriceDirection(poolPrice) 410 require.Equal(t, types.Staying, result) 411 } 412 413 func TestComputePriceDirection(t *testing.T) { 414 // increase case 415 orderMap := make(types.OrderMap) 416 a, _ := sdk.NewDecFromStr("1") 417 b, _ := sdk.NewDecFromStr("1.1") 418 c, _ := sdk.NewDecFromStr("1.2") 419 orderMap[a.String()] = types.Order{ 420 Price: a, 421 BuyOfferAmt: sdk.NewInt(40000000), 422 SellOfferAmt: sdk.ZeroInt(), 423 } 424 orderMap[b.String()] = types.Order{ 425 Price: b, 426 BuyOfferAmt: sdk.NewInt(40000000), 427 SellOfferAmt: sdk.ZeroInt(), 428 } 429 orderMap[c.String()] = types.Order{ 430 Price: c, 431 BuyOfferAmt: sdk.ZeroInt(), 432 SellOfferAmt: sdk.NewInt(20000000), 433 } 434 // make orderbook to sort orderMap 435 orderBook := orderMap.SortOrderBook() 436 437 X := orderMap[a.String()].BuyOfferAmt.ToDec().Add(orderMap[b.String()].BuyOfferAmt.ToDec()) 438 Y := orderMap[c.String()].SellOfferAmt.ToDec() 439 440 poolPrice := X.Quo(Y) 441 direction := orderBook.PriceDirection(poolPrice) 442 result, found := orderBook.Match(X, Y) 443 result2, found2 := orderBook.CalculateMatch(direction, X, Y) 444 require.Equal(t, found2, found) 445 require.Equal(t, result2, result) 446 447 // decrease case 448 orderMap = make(types.OrderMap) 449 a, _ = sdk.NewDecFromStr("0.7") 450 b, _ = sdk.NewDecFromStr("0.9") 451 c, _ = sdk.NewDecFromStr("0.8") 452 orderMap[a.String()] = types.Order{ 453 Price: a, 454 BuyOfferAmt: sdk.NewInt(20000000), 455 SellOfferAmt: sdk.ZeroInt(), 456 } 457 orderMap[b.String()] = types.Order{ 458 Price: b, 459 BuyOfferAmt: sdk.ZeroInt(), 460 SellOfferAmt: sdk.NewInt(40000000), 461 } 462 orderMap[c.String()] = types.Order{ 463 Price: c, 464 BuyOfferAmt: sdk.NewInt(10000000), 465 SellOfferAmt: sdk.ZeroInt(), 466 } 467 // make orderbook to sort orderMap 468 orderBook = orderMap.SortOrderBook() 469 470 X = orderMap[a.String()].BuyOfferAmt.ToDec().Add(orderMap[c.String()].BuyOfferAmt.ToDec()) 471 Y = orderMap[b.String()].SellOfferAmt.ToDec() 472 473 poolPrice = X.Quo(Y) 474 direction = orderBook.PriceDirection(poolPrice) 475 result, found = orderBook.Match(X, Y) 476 result2, found2 = orderBook.CalculateMatch(direction, X, Y) 477 require.Equal(t, found2, found) 478 require.Equal(t, result2, result) 479 480 // stay case 481 orderMap = make(types.OrderMap) 482 a, _ = sdk.NewDecFromStr("1.0") 483 484 orderMap[a.String()] = types.Order{ 485 Price: a, 486 BuyOfferAmt: sdk.NewInt(50000000), 487 SellOfferAmt: sdk.NewInt(50000000), 488 } 489 orderBook = orderMap.SortOrderBook() 490 491 X = orderMap[a.String()].BuyOfferAmt.ToDec() 492 Y = orderMap[a.String()].SellOfferAmt.ToDec() 493 poolPrice = X.Quo(Y) 494 495 result, _ = orderBook.Match(X, Y) 496 result2 = orderBook.CalculateMatchStay(poolPrice) 497 require.Equal(t, result2, result) 498 } 499 500 func TestCalculateMatchStay(t *testing.T) { 501 currentPrice := sdk.MustNewDecFromStr("1.0") 502 orderBook := types.OrderBook{ 503 {Price: sdk.MustNewDecFromStr("1.0"), BuyOfferAmt: sdk.NewInt(5), SellOfferAmt: sdk.NewInt(7)}, 504 } 505 require.Equal(t, types.Staying, orderBook.PriceDirection(currentPrice)) 506 r := orderBook.CalculateMatchStay(currentPrice) 507 require.Equal(t, sdk.NewDec(5), r.EX) 508 require.Equal(t, sdk.NewDec(5), r.EY) 509 } 510 511 // Match Stay case with fractional match type 512 func TestCalculateMatchStayEdgeCase(t *testing.T) { 513 currentPrice, err := sdk.NewDecFromStr("1.844380246375231658") 514 require.NoError(t, err) 515 var orderBook types.OrderBook 516 orderbookEdgeCase := `[{"Price":"1.827780824157854573","BuyOfferAmt":"12587364000","SellOfferAmt":"6200948000","BatchPoolSwapMsgs":[{"msg_index":12,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"2097894000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg36er2cp","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"2097894000"},"demand_coin_denom":"denomY","order_price":"1.827780824157854573"}},{"msg_index":16,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"4669506000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg44npvhm","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"4669506000"},"demand_coin_denom":"denomY","order_price":"1.827780824157854573"}},{"msg_index":23,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"609066000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfzwk37gt","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"609066000"},"demand_coin_denom":"denomY","order_price":"1.827780824157854573"}},{"msg_index":39,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"5210898000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfckxufsg","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"5210898000"},"demand_coin_denom":"denomY","order_price":"1.827780824157854573"}},{"msg_index":56,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1284220000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg44npvhm","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1284220000"},"demand_coin_denom":"denomX","order_price":"1.827780824157854573"}},{"msg_index":78,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1981368000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfhft040s","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1981368000"},"demand_coin_denom":"denomX","order_price":"1.827780824157854573"}},{"msg_index":85,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2935360000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5c2yrhrufk","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2935360000"},"demand_coin_denom":"denomX","order_price":"1.827780824157854573"}}]},{"Price":"1.829625204404229805","BuyOfferAmt":"9203664000","SellOfferAmt":"6971480000","BatchPoolSwapMsgs":[{"msg_index":18,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"5210898000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cghxkq0yk","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"5210898000"},"demand_coin_denom":"denomY","order_price":"1.829625204404229805"}},{"msg_index":36,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"3992766000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf46wwkua","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"3992766000"},"demand_coin_denom":"denomY","order_price":"1.829625204404229805"}},{"msg_index":44,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3155512000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgrua237l","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3155512000"},"demand_coin_denom":"denomX","order_price":"1.829625204404229805"}},{"msg_index":55,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"513688000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg5g94e2f","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"513688000"},"demand_coin_denom":"denomX","order_price":"1.829625204404229805"}},{"msg_index":61,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3302280000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfqansamx","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3302280000"},"demand_coin_denom":"denomX","order_price":"1.829625204404229805"}}]},{"Price":"1.831469584650605036","BuyOfferAmt":"18001284000","SellOfferAmt":"2311596000","BatchPoolSwapMsgs":[{"msg_index":21,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"3248352000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfqansamx","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"3248352000"},"demand_coin_denom":"denomY","order_price":"1.831469584650605036"}},{"msg_index":32,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"5007876000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf34yvsn8","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"5007876000"},"demand_coin_denom":"denomY","order_price":"1.831469584650605036"}},{"msg_index":33,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"5955312000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfjmhexac","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"5955312000"},"demand_coin_denom":"denomY","order_price":"1.831469584650605036"}},{"msg_index":34,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"3789744000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfnxpdnq2","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"3789744000"},"demand_coin_denom":"denomY","order_price":"1.831469584650605036"}},{"msg_index":65,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2311596000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfyjejm5u","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2311596000"},"demand_coin_denom":"denomX","order_price":"1.831469584650605036"}}]},{"Price":"1.833313964896980268","BuyOfferAmt":"12113646000","SellOfferAmt":"4806652000","BatchPoolSwapMsgs":[{"msg_index":6,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"6632052000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg9qjf5zg","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"6632052000"},"demand_coin_denom":"denomY","order_price":"1.833313964896980268"}},{"msg_index":28,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"5481594000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf8u28d6r","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"5481594000"},"demand_coin_denom":"denomY","order_price":"1.833313964896980268"}},{"msg_index":41,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"660456000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgqjwl8sq","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"660456000"},"demand_coin_denom":"denomX","order_price":"1.833313964896980268"}},{"msg_index":64,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2421672000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfrnq9t4e","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2421672000"},"demand_coin_denom":"denomX","order_price":"1.833313964896980268"}},{"msg_index":73,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1724524000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfjmhexac","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1724524000"},"demand_coin_denom":"denomX","order_price":"1.833313964896980268"}}]},{"Price":"1.835158345143355500","BuyOfferAmt":"0","SellOfferAmt":"6421100000","BatchPoolSwapMsgs":[{"msg_index":47,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2715208000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgxwpuzvh","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2715208000"},"demand_coin_denom":"denomX","order_price":"1.835158345143355500"}},{"msg_index":58,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2678516000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cghxkq0yk","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2678516000"},"demand_coin_denom":"denomX","order_price":"1.835158345143355500"}},{"msg_index":82,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1027376000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5c2p3t40m7","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1027376000"},"demand_coin_denom":"denomX","order_price":"1.835158345143355500"}}]},{"Price":"1.837002725389730731","BuyOfferAmt":"9135990000","SellOfferAmt":"3852660000","BatchPoolSwapMsgs":[{"msg_index":13,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"744414000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgj52kuk7","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"744414000"},"demand_coin_denom":"denomY","order_price":"1.837002725389730731"}},{"msg_index":19,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"5143224000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgcemnnmw","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"5143224000"},"demand_coin_denom":"denomY","order_price":"1.837002725389730731"}},{"msg_index":22,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"541392000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfpq9ygx5","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"541392000"},"demand_coin_denom":"denomY","order_price":"1.837002725389730731"}},{"msg_index":35,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"2706960000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf58c6rp0","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"2706960000"},"demand_coin_denom":"denomY","order_price":"1.837002725389730731"}},{"msg_index":48,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2274904000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg8nhgh39","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2274904000"},"demand_coin_denom":"denomX","order_price":"1.837002725389730731"}},{"msg_index":51,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1394296000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgs80hl9n","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1394296000"},"demand_coin_denom":"denomX","order_price":"1.837002725389730731"}},{"msg_index":80,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"183460000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfetsgud6","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"183460000"},"demand_coin_denom":"denomX","order_price":"1.837002725389730731"}}]},{"Price":"1.838847105636105963","BuyOfferAmt":"6226008000","SellOfferAmt":"2715208000","BatchPoolSwapMsgs":[{"msg_index":5,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"6226008000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgyayapl6","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"6226008000"},"demand_coin_denom":"denomY","order_price":"1.838847105636105963"}},{"msg_index":43,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2715208000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgzpt7yrd","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2715208000"},"demand_coin_denom":"denomX","order_price":"1.838847105636105963"}}]},{"Price":"1.840691485882481195","BuyOfferAmt":"6496704000","SellOfferAmt":"3155512000","BatchPoolSwapMsgs":[{"msg_index":8,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"6496704000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg8nhgh39","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"6496704000"},"demand_coin_denom":"denomY","order_price":"1.840691485882481195"}},{"msg_index":81,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3155512000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5c2qvap6xv","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3155512000"},"demand_coin_denom":"denomX","order_price":"1.840691485882481195"}}]},{"Price":"1.842535866128856426","BuyOfferAmt":"0","SellOfferAmt":"1137452000","BatchPoolSwapMsgs":[{"msg_index":45,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1137452000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgyayapl6","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1137452000"},"demand_coin_denom":"denomX","order_price":"1.842535866128856426"}}]},{"Price":"1.844380246375231658","BuyOfferAmt":"15700368000","SellOfferAmt":"2274904000","BatchPoolSwapMsgs":[{"msg_index":14,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"1759524000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgnfuzftv","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"1759524000"},"demand_coin_denom":"denomY","order_price":"1.844380246375231658"}},{"msg_index":24,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"1624176000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfrnq9t4e","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"1624176000"},"demand_coin_denom":"denomY","order_price":"1.844380246375231658"}},{"msg_index":25,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"3248352000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfyjejm5u","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"3248352000"},"demand_coin_denom":"denomY","order_price":"1.844380246375231658"}},{"msg_index":29,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"4263462000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfgr8539m","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"4263462000"},"demand_coin_denom":"denomY","order_price":"1.844380246375231658"}},{"msg_index":31,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"4804854000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfsgjc9w4","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"4804854000"},"demand_coin_denom":"denomY","order_price":"1.844380246375231658"}},{"msg_index":59,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1651140000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgcemnnmw","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1651140000"},"demand_coin_denom":"denomX","order_price":"1.844380246375231658"}},{"msg_index":62,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"623764000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfpq9ygx5","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"623764000"},"demand_coin_denom":"denomX","order_price":"1.844380246375231658"}}]},{"Price":"1.846224626621606890","BuyOfferAmt":"19963830000","SellOfferAmt":"3338972000","BatchPoolSwapMsgs":[{"msg_index":11,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"6429030000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgs80hl9n","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"6429030000"},"demand_coin_denom":"denomY","order_price":"1.846224626621606890"}},{"msg_index":20,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"5143224000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgeyd8xxu","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"5143224000"},"demand_coin_denom":"denomY","order_price":"1.846224626621606890"}},{"msg_index":27,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"2300916000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfxpunc83","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"2300916000"},"demand_coin_denom":"denomY","order_price":"1.846224626621606890"}},{"msg_index":38,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"6090660000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfhft040s","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"6090660000"},"demand_coin_denom":"denomY","order_price":"1.846224626621606890"}},{"msg_index":42,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"660456000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgp0ctjdj","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"660456000"},"demand_coin_denom":"denomX","order_price":"1.846224626621606890"}},{"msg_index":68,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2678516000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf8u28d6r","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2678516000"},"demand_coin_denom":"denomX","order_price":"1.846224626621606890"}}]},{"Price":"1.848069006867982121","BuyOfferAmt":"0","SellOfferAmt":"3302280000","BatchPoolSwapMsgs":[{"msg_index":46,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2201520000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg9qjf5zg","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2201520000"},"demand_coin_denom":"denomX","order_price":"1.848069006867982121"}},{"msg_index":70,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1100760000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cff73qycf","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1100760000"},"demand_coin_denom":"denomX","order_price":"1.848069006867982121"}}]},{"Price":"1.849913387114357353","BuyOfferAmt":"2233242000","SellOfferAmt":"10420528000","BatchPoolSwapMsgs":[{"msg_index":4,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"2233242000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgrua237l","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"2233242000"},"demand_coin_denom":"denomY","order_price":"1.849913387114357353"}},{"msg_index":54,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"917300000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgnfuzftv","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"917300000"},"demand_coin_denom":"denomX","order_price":"1.849913387114357353"}},{"msg_index":60,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3485740000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgeyd8xxu","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3485740000"},"demand_coin_denom":"denomX","order_price":"1.849913387114357353"}},{"msg_index":63,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"697148000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfzwk37gt","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"697148000"},"demand_coin_denom":"denomX","order_price":"1.849913387114357353"}},{"msg_index":66,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2421672000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf900xwfw","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2421672000"},"demand_coin_denom":"denomX","order_price":"1.849913387114357353"}},{"msg_index":84,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1357604000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5c2rzw5vgn","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1357604000"},"demand_coin_denom":"denomX","order_price":"1.849913387114357353"}},{"msg_index":87,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1541064000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5c2xsjzl6m","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1541064000"},"demand_coin_denom":"denomX","order_price":"1.849913387114357353"}}]},{"Price":"1.851757767360732585","BuyOfferAmt":"23550552000","SellOfferAmt":"1577756000","BatchPoolSwapMsgs":[{"msg_index":1,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"5075550000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgqjwl8sq","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"5075550000"},"demand_coin_denom":"denomY","order_price":"1.851757767360732585"}},{"msg_index":7,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"4128114000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgxwpuzvh","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"4128114000"},"demand_coin_denom":"denomY","order_price":"1.851757767360732585"}},{"msg_index":9,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"4940202000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cggv6mtwa","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"4940202000"},"demand_coin_denom":"denomY","order_price":"1.851757767360732585"}},{"msg_index":15,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"3113004000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg5g94e2f","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"3113004000"},"demand_coin_denom":"denomY","order_price":"1.851757767360732585"}},{"msg_index":26,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"6293682000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf900xwfw","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"6293682000"},"demand_coin_denom":"denomY","order_price":"1.851757767360732585"}},{"msg_index":67,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"146768000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfxpunc83","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"146768000"},"demand_coin_denom":"denomX","order_price":"1.851757767360732585"}},{"msg_index":71,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1430988000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfsgjc9w4","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1430988000"},"demand_coin_denom":"denomX","order_price":"1.851757767360732585"}}]},{"Price":"1.853602147607107816","BuyOfferAmt":"3519048000","SellOfferAmt":"5577184000","BatchPoolSwapMsgs":[{"msg_index":10,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"3519048000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgf3v07n0","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"3519048000"},"demand_coin_denom":"denomY","order_price":"1.853602147607107816"}},{"msg_index":52,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"403612000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg36er2cp","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"403612000"},"demand_coin_denom":"denomX","order_price":"1.853602147607107816"}},{"msg_index":53,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"770532000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgj52kuk7","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"770532000"},"demand_coin_denom":"denomX","order_price":"1.853602147607107816"}},{"msg_index":72,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"146768000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf34yvsn8","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"146768000"},"demand_coin_denom":"denomX","order_price":"1.853602147607107816"}},{"msg_index":74,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3155512000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfnxpdnq2","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3155512000"},"demand_coin_denom":"denomX","order_price":"1.853602147607107816"}},{"msg_index":75,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"183460000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf58c6rp0","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"183460000"},"demand_coin_denom":"denomX","order_price":"1.853602147607107816"}},{"msg_index":76,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"917300000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf46wwkua","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"917300000"},"demand_coin_denom":"denomX","order_price":"1.853602147607107816"}}]},{"Price":"1.855446527853483048","BuyOfferAmt":"5752290000","SellOfferAmt":"1357604000","BatchPoolSwapMsgs":[{"msg_index":3,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"3654396000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgzpt7yrd","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"3654396000"},"demand_coin_denom":"denomY","order_price":"1.855446527853483048"}},{"msg_index":17,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"2097894000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgkmq56ey","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"2097894000"},"demand_coin_denom":"denomY","order_price":"1.855446527853483048"}},{"msg_index":49,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1357604000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cggv6mtwa","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1357604000"},"demand_coin_denom":"denomX","order_price":"1.855446527853483048"}}]},{"Price":"1.857290908099858280","BuyOfferAmt":"2774634000","SellOfferAmt":"4256272000","BatchPoolSwapMsgs":[{"msg_index":37,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"2774634000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfk5amqjz","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"2774634000"},"demand_coin_denom":"denomY","order_price":"1.857290908099858280"}},{"msg_index":50,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2128136000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgf3v07n0","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2128136000"},"demand_coin_denom":"denomX","order_price":"1.857290908099858280"}},{"msg_index":77,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"256844000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfk5amqjz","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"256844000"},"demand_coin_denom":"denomX","order_price":"1.857290908099858280"}},{"msg_index":83,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1871292000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5c2zlcqe4p","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1871292000"},"demand_coin_denom":"denomX","order_price":"1.857290908099858280"}}]},{"Price":"1.859135288346233511","BuyOfferAmt":"10760166000","SellOfferAmt":"5283648000","BatchPoolSwapMsgs":[{"msg_index":2,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"1421154000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgp0ctjdj","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"1421154000"},"demand_coin_denom":"denomY","order_price":"1.859135288346233511"}},{"msg_index":30,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"4331136000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cff73qycf","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"4331136000"},"demand_coin_denom":"denomY","order_price":"1.859135288346233511"}},{"msg_index":40,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"5007876000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfetsgud6","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"5007876000"},"demand_coin_denom":"denomY","order_price":"1.859135288346233511"}},{"msg_index":57,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1137452000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgkmq56ey","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1137452000"},"demand_coin_denom":"denomX","order_price":"1.859135288346233511"}},{"msg_index":69,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"293536000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfgr8539m","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"293536000"},"demand_coin_denom":"denomX","order_price":"1.859135288346233511"}},{"msg_index":79,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3302280000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfckxufsg","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3302280000"},"demand_coin_denom":"denomX","order_price":"1.859135288346233511"}},{"msg_index":86,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"550380000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5c297phf5y","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"550380000"},"demand_coin_denom":"denomX","order_price":"1.859135288346233511"}}]}]` 517 json.Unmarshal([]byte(orderbookEdgeCase), &orderBook) 518 r := orderBook.CalculateMatchStay(currentPrice) 519 require.Equal(t, types.FractionalMatch, r.MatchType) 520 // stay case with fractional 521 } 522 523 // Match Stay case with no match type 524 func TestCalculateNoMatchEdgeCase(t *testing.T) { 525 currentPrice, err := sdk.NewDecFromStr("1.007768598527187219") 526 require.NoError(t, err) 527 var orderBook types.OrderBook 528 orderbookEdgeCase := `[{"Price":"1.007768598527187219","BuyOfferAmt":"0","SellOfferAmt":"417269600","BatchPoolSwapMsgs":[{"msg_index":1,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"417269600"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgqjwl8sq","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"417269600"},"demand_coin_denom":"denomX","order_price":"1.007768598527187219"}}]},{"Price":"1.011799672921295968","BuyOfferAmt":"0","SellOfferAmt":"2190665400","BatchPoolSwapMsgs":[{"msg_index":2,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2190665400"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgp0ctjdj","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2190665400"},"demand_coin_denom":"denomX","order_price":"1.011799672921295968"}}]}]` 529 json.Unmarshal([]byte(orderbookEdgeCase), &orderBook) 530 r := orderBook.CalculateMatchStay(currentPrice) 531 require.Equal(t, types.NoMatch, r.MatchType) 532 // stay case with fractional 533 } 534 535 // Reproduce GetOrderMapEdgeCase, selling Y for X case, ErrInvalidDenom case 536 func TestMakeOrderMapEdgeCase(t *testing.T) { 537 onlyNotMatched := false 538 var swapMsgs []*types.SwapMsgState 539 swapMsgsJson := `[{"msg_index":1,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"19228500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgqjwl8sq","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"19228500"},"demand_coin_denom":"denomY","order_price":"0.027506527499265415"}},{"msg_index":2,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"141009000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgp0ctjdj","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"141009000"},"demand_coin_denom":"denomY","order_price":"0.027341323129900457"}},{"msg_index":3,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"23501500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgzpt7yrd","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"23501500"},"demand_coin_denom":"denomY","order_price":"0.027616663745508720"}},{"msg_index":4,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"200831000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgrua237l","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"200831000"},"demand_coin_denom":"denomY","order_price":"0.027589129683947893"}},{"msg_index":5,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"160237500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgyayapl6","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"160237500"},"demand_coin_denom":"denomY","order_price":"0.027313789068339631"}},{"msg_index":6,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"175193000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg9qjf5zg","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"175193000"},"demand_coin_denom":"denomY","order_price":"0.027478993437704589"}},{"msg_index":7,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"183739000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgxwpuzvh","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"183739000"},"demand_coin_denom":"denomY","order_price":"0.027699265930191198"}},{"msg_index":8,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"32047500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg8nhgh39","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"32047500"},"demand_coin_denom":"denomY","order_price":"0.027451459376143762"}},{"msg_index":9,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"111098000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cggv6mtwa","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"111098000"},"demand_coin_denom":"denomY","order_price":"0.027286255006778805"}},{"msg_index":10,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"166647000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgf3v07n0","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"166647000"},"demand_coin_denom":"denomY","order_price":"0.027341323129900457"}},{"msg_index":11,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"98279000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgs80hl9n","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"98279000"},"demand_coin_denom":"denomY","order_price":"0.027368857191461284"}},{"msg_index":12,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"8546000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg36er2cp","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"8546000"},"demand_coin_denom":"denomY","order_price":"0.027396391253022110"}},{"msg_index":13,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"87596500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgj52kuk7","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"87596500"},"demand_coin_denom":"denomY","order_price":"0.027451459376143762"}},{"msg_index":14,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"111098000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgnfuzftv","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"111098000"},"demand_coin_denom":"denomY","order_price":"0.027478993437704589"}},{"msg_index":15,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"38457000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg5g94e2f","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"38457000"},"demand_coin_denom":"denomY","order_price":"0.027451459376143762"}},{"msg_index":16,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"153828000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg44npvhm","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"153828000"},"demand_coin_denom":"denomY","order_price":"0.027616663745508720"}},{"msg_index":17,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"70504500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgkmq56ey","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"70504500"},"demand_coin_denom":"denomY","order_price":"0.027451459376143762"}},{"msg_index":18,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"47003000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cghxkq0yk","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"47003000"},"demand_coin_denom":"denomY","order_price":"0.027396391253022110"}},{"msg_index":19,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"132463000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgcemnnmw","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"132463000"},"demand_coin_denom":"denomY","order_price":"0.027726799991752025"}},{"msg_index":20,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"66231500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgeyd8xxu","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"66231500"},"demand_coin_denom":"denomY","order_price":"0.027561595622387067"}},{"msg_index":21,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"119644000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfqansamx","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"119644000"},"demand_coin_denom":"denomY","order_price":"0.027506527499265415"}},{"msg_index":22,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"17092000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfpq9ygx5","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"17092000"},"demand_coin_denom":"denomY","order_price":"0.027341323129900457"}},{"msg_index":23,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"209377000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfzwk37gt","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"209377000"},"demand_coin_denom":"denomY","order_price":"0.027478993437704589"}},{"msg_index":24,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"207240500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfrnq9t4e","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"207240500"},"demand_coin_denom":"denomY","order_price":"0.027396391253022110"}},{"msg_index":25,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"155964500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfyjejm5u","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"155964500"},"demand_coin_denom":"denomY","order_price":"0.027423925314582936"}},{"msg_index":26,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"194421500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf900xwfw","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"194421500"},"demand_coin_denom":"denomY","order_price":"0.027286255006778805"}},{"msg_index":27,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"102552000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfxpunc83","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"102552000"},"demand_coin_denom":"denomY","order_price":"0.027368857191461284"}},{"msg_index":28,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"151691500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf8u28d6r","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"151691500"},"demand_coin_denom":"denomY","order_price":"0.027478993437704589"}},{"msg_index":29,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"113234500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfgr8539m","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"113234500"},"demand_coin_denom":"denomY","order_price":"0.027368857191461284"}},{"msg_index":30,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"117507500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cff73qycf","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"117507500"},"demand_coin_denom":"denomY","order_price":"0.027423925314582936"}},{"msg_index":31,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"141009000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfsgjc9w4","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"141009000"},"demand_coin_denom":"denomY","order_price":"0.027423925314582936"}},{"msg_index":32,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"200831000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf34yvsn8","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"200831000"},"demand_coin_denom":"denomY","order_price":"0.027534061560826241"}},{"msg_index":33,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"141009000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfjmhexac","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"141009000"},"demand_coin_denom":"denomY","order_price":"0.027726799991752025"}},{"msg_index":34,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"98279000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfnxpdnq2","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"98279000"},"demand_coin_denom":"denomY","order_price":"0.027478993437704589"}},{"msg_index":35,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"76914000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf58c6rp0","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"76914000"},"demand_coin_denom":"denomY","order_price":"0.027423925314582936"}},{"msg_index":36,"executed":true,"exchanged_offer_coin":{"denom":"denomX","amount":"0"},"remaining_offer_coin":{"denom":"denomX","amount":"23501500"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf46wwkua","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomX","amount":"23501500"},"demand_coin_denom":"denomY","order_price":"0.027754334053312851"}},{"msg_index":37,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"4733282800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgqjwl8sq","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"4733282800"},"demand_coin_denom":"denomX","order_price":"0.027699265930191198"}},{"msg_index":38,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3957334800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgp0ctjdj","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3957334800"},"demand_coin_denom":"denomX","order_price":"0.027478993437704589"}},{"msg_index":39,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2483033600"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgzpt7yrd","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2483033600"},"demand_coin_denom":"denomX","order_price":"0.027589129683947893"}},{"msg_index":40,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"5509230800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgrua237l","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"5509230800"},"demand_coin_denom":"denomX","order_price":"0.027561595622387067"}},{"msg_index":41,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2327844000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgyayapl6","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2327844000"},"demand_coin_denom":"denomX","order_price":"0.027423925314582936"}},{"msg_index":42,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"4733282800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg9qjf5zg","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"4733282800"},"demand_coin_denom":"denomX","order_price":"0.027451459376143762"}},{"msg_index":43,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"7061126800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgxwpuzvh","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"7061126800"},"demand_coin_denom":"denomX","order_price":"0.027726799991752025"}},{"msg_index":44,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"4655688000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg8nhgh39","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"4655688000"},"demand_coin_denom":"denomX","order_price":"0.027589129683947893"}},{"msg_index":45,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3026197200"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cggv6mtwa","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3026197200"},"demand_coin_denom":"denomX","order_price":"0.027589129683947893"}},{"msg_index":46,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"7293911200"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgf3v07n0","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"7293911200"},"demand_coin_denom":"denomX","order_price":"0.027616663745508720"}},{"msg_index":47,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"4810877600"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgs80hl9n","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"4810877600"},"demand_coin_denom":"denomX","order_price":"0.027534061560826241"}},{"msg_index":48,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"4345308800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg36er2cp","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"4345308800"},"demand_coin_denom":"denomX","order_price":"0.027451459376143762"}},{"msg_index":49,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"5509230800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgj52kuk7","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"5509230800"},"demand_coin_denom":"denomX","order_price":"0.027368857191461284"}},{"msg_index":50,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"4190119200"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgnfuzftv","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"4190119200"},"demand_coin_denom":"denomX","order_price":"0.027451459376143762"}},{"msg_index":51,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"543163600"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg5g94e2f","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"543163600"},"demand_coin_denom":"denomX","order_price":"0.027286255006778805"}},{"msg_index":52,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"4578093200"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cg44npvhm","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"4578093200"},"demand_coin_denom":"denomX","order_price":"0.027506527499265415"}},{"msg_index":53,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"6517963200"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgkmq56ey","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"6517963200"},"demand_coin_denom":"denomX","order_price":"0.027368857191461284"}},{"msg_index":54,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"4190119200"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cghxkq0yk","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"4190119200"},"demand_coin_denom":"denomX","order_price":"0.027368857191461284"}},{"msg_index":55,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1939870000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgcemnnmw","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1939870000"},"demand_coin_denom":"denomX","order_price":"0.027754334053312851"}},{"msg_index":56,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"1163922000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cgeyd8xxu","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"1163922000"},"demand_coin_denom":"denomX","order_price":"0.027478993437704589"}},{"msg_index":57,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"5897204800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfqansamx","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"5897204800"},"demand_coin_denom":"denomX","order_price":"0.027644197807069546"}},{"msg_index":58,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"155189600"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfpq9ygx5","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"155189600"},"demand_coin_denom":"denomX","order_price":"0.027671731868630372"}},{"msg_index":59,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2250249200"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfzwk37gt","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2250249200"},"demand_coin_denom":"denomX","order_price":"0.027286255006778805"}},{"msg_index":60,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"2948602400"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfrnq9t4e","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"2948602400"},"demand_coin_denom":"denomX","order_price":"0.027286255006778805"}},{"msg_index":61,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"7449100800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfyjejm5u","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"7449100800"},"demand_coin_denom":"denomX","order_price":"0.027313789068339631"}},{"msg_index":62,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"6129989200"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf900xwfw","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"6129989200"},"demand_coin_denom":"denomX","order_price":"0.027341323129900457"}},{"msg_index":63,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3491766000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfxpunc83","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3491766000"},"demand_coin_denom":"denomX","order_price":"0.027534061560826241"}},{"msg_index":64,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"6362773600"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf8u28d6r","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"6362773600"},"demand_coin_denom":"denomX","order_price":"0.027726799991752025"}},{"msg_index":65,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"7138721600"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfgr8539m","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"7138721600"},"demand_coin_denom":"denomX","order_price":"0.027534061560826241"}},{"msg_index":66,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3724550400"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cff73qycf","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3724550400"},"demand_coin_denom":"denomX","order_price":"0.027616663745508720"}},{"msg_index":67,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"3103792000"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfsgjc9w4","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"3103792000"},"demand_coin_denom":"denomX","order_price":"0.027589129683947893"}},{"msg_index":68,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"232784400"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cf34yvsn8","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"232784400"},"demand_coin_denom":"denomX","order_price":"0.027478993437704589"}},{"msg_index":69,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"6052394400"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfjmhexac","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"6052394400"},"demand_coin_denom":"denomX","order_price":"0.027478993437704589"}},{"msg_index":70,"executed":true,"exchanged_offer_coin":{"denom":"denomY","amount":"0"},"remaining_offer_coin":{"denom":"denomY","amount":"5121256800"},"msg":{"swap_requester_address":"cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5cfnxpdnq2","pool_id":1,"pool_type_id":1,"offer_coin":{"denom":"denomY","amount":"5121256800"},"demand_coin_denom":"denomX","order_price":"0.027644197807069546"}}]` 540 json.Unmarshal([]byte(swapMsgsJson), &swapMsgs) 541 orderMap, xToY, yToX := types.MakeOrderMap(swapMsgs, DenomX, DenomY, onlyNotMatched) 542 require.NotZero(t, len(orderMap)) 543 require.NotNil(t, xToY) 544 require.NotNil(t, yToX) 545 546 // ErrInvalidDenom case 547 require.Panics(t, func() { 548 types.MakeOrderMap(swapMsgs, "12421miklfdjnfiasdjfidosa8381813818---", DenomY, onlyNotMatched) 549 }) 550 } 551 552 func TestOrderbookValidate(t *testing.T) { 553 for _, testCase := range []struct { 554 currentPrice string 555 buyPrice string 556 sellPrice string 557 valid bool 558 }{ 559 { 560 currentPrice: "1.0", 561 buyPrice: "0.99", 562 sellPrice: "1.01", 563 valid: true, 564 }, 565 { 566 // maxBuyOrderPrice > minSellOrderPrice 567 currentPrice: "1.0", 568 buyPrice: "1.01", 569 sellPrice: "0.99", 570 valid: false, 571 }, 572 { 573 currentPrice: "1.0", 574 buyPrice: "1.1", 575 sellPrice: "1.2", 576 valid: true, 577 }, 578 { 579 // maxBuyOrderPrice/currentPrice > 1.10 580 currentPrice: "1.0", 581 buyPrice: "1.11", 582 sellPrice: "1.2", 583 valid: false, 584 }, 585 { 586 currentPrice: "1.0", 587 buyPrice: "0.8", 588 sellPrice: "0.9", 589 valid: true, 590 }, 591 { 592 // minSellOrderPrice/currentPrice < 0.90 593 currentPrice: "1.0", 594 buyPrice: "0.8", 595 sellPrice: "0.89", 596 valid: false, 597 }, 598 { 599 // not positive price 600 currentPrice: "0.0", 601 buyPrice: "0.00000000001", 602 sellPrice: "0.000000000011", 603 valid: false, 604 }, 605 } { 606 buyPrice := sdk.MustNewDecFromStr(testCase.buyPrice) 607 sellPrice := sdk.MustNewDecFromStr(testCase.sellPrice) 608 orderMap := types.OrderMap{ 609 buyPrice.String(): { 610 Price: buyPrice, 611 BuyOfferAmt: sdk.OneInt(), 612 SellOfferAmt: sdk.ZeroInt(), 613 }, 614 sellPrice.String(): { 615 Price: sellPrice, 616 BuyOfferAmt: sdk.ZeroInt(), 617 SellOfferAmt: sdk.OneInt(), 618 }, 619 } 620 orderBook := orderMap.SortOrderBook() 621 require.Equal(t, testCase.valid, orderBook.Validate(sdk.MustNewDecFromStr(testCase.currentPrice))) 622 } 623 } 624 625 func TestCountNotMatchedMsgs(t *testing.T) { 626 for _, tc := range []struct { 627 msgs []*types.SwapMsgState 628 cnt int 629 }{ 630 { 631 []*types.SwapMsgState{}, 632 0, 633 }, 634 { 635 []*types.SwapMsgState{ 636 {Executed: true, Succeeded: false}, 637 {Executed: true, Succeeded: false}, 638 }, 639 2, 640 }, 641 { 642 []*types.SwapMsgState{ 643 {}, 644 {Executed: true, Succeeded: true, ToBeDeleted: false}, 645 {Executed: true, Succeeded: true, ToBeDeleted: true}, 646 }, 647 0, 648 }, 649 } { 650 require.Equal(t, tc.cnt, types.CountNotMatchedMsgs(tc.msgs)) 651 } 652 } 653 654 func TestCountFractionalMatchedMsgs(t *testing.T) { 655 for _, tc := range []struct { 656 msgs []*types.SwapMsgState 657 cnt int 658 }{ 659 { 660 []*types.SwapMsgState{}, 661 0, 662 }, 663 { 664 []*types.SwapMsgState{ 665 {Executed: true, Succeeded: true, ToBeDeleted: false}, 666 {Executed: true, Succeeded: true, ToBeDeleted: false}, 667 }, 668 2, 669 }, 670 { 671 []*types.SwapMsgState{ 672 {}, 673 {Executed: true, Succeeded: false}, 674 {Executed: true, Succeeded: true, ToBeDeleted: true}, 675 }, 676 0, 677 }, 678 } { 679 require.Equal(t, tc.cnt, types.CountFractionalMatchedMsgs(tc.msgs)) 680 } 681 }