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  }