github.com/gravity-devs/liquidity@v1.5.3/x/liquidity/handler_test.go (about) 1 package liquidity_test 2 3 import ( 4 "fmt" 5 "testing" 6 7 sdk "github.com/cosmos/cosmos-sdk/types" 8 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 9 banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 10 "github.com/stretchr/testify/require" 11 12 "github.com/gravity-devs/liquidity/app" 13 "github.com/gravity-devs/liquidity/x/liquidity" 14 "github.com/gravity-devs/liquidity/x/liquidity/types" 15 ) 16 17 func TestBadMsg(t *testing.T) { 18 simapp, ctx := app.CreateTestInput() 19 simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams()) 20 handler := liquidity.NewHandler(simapp.LiquidityKeeper) 21 _, err := handler(ctx, nil) 22 require.ErrorIs(t, err, sdkerrors.ErrUnknownRequest) 23 _, err = handler(ctx, banktypes.NewMsgMultiSend(nil, nil)) 24 require.ErrorIs(t, err, sdkerrors.ErrUnknownRequest) 25 } 26 27 func TestMsgServerCreatePool(t *testing.T) { 28 simapp, ctx := app.CreateTestInput() 29 simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams()) 30 params := simapp.LiquidityKeeper.GetParams(ctx) 31 32 poolTypeID := types.DefaultPoolTypeID 33 addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee) 34 35 denomA := "uETH" 36 denomB := "uUSD" 37 denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB) 38 39 deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000))) 40 app.SaveAccount(simapp, ctx, addrs[0], deposit) 41 42 depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA) 43 depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB) 44 depositBalance := sdk.NewCoins(depositA, depositB) 45 46 require.Equal(t, deposit, depositBalance) 47 48 msg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance) 49 50 handler := liquidity.NewHandler(simapp.LiquidityKeeper) 51 _, err := handler(ctx, msg) 52 require.NoError(t, err) 53 54 pools := simapp.LiquidityKeeper.GetAllPools(ctx) 55 require.Equal(t, 1, len(pools)) 56 require.Equal(t, uint64(1), pools[0].Id) 57 require.Equal(t, uint64(1), simapp.LiquidityKeeper.GetNextPoolID(ctx)-1) 58 require.Equal(t, denomA, pools[0].ReserveCoinDenoms[0]) 59 require.Equal(t, denomB, pools[0].ReserveCoinDenoms[1]) 60 61 poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pools[0]) 62 creatorBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pools[0].PoolCoinDenom) 63 require.Equal(t, poolCoin, creatorBalance.Amount) 64 65 _, err = simapp.LiquidityKeeper.CreatePool(ctx, msg) 66 require.ErrorIs(t, err, types.ErrPoolAlreadyExists) 67 } 68 69 func TestMsgServerExecuteDeposit(t *testing.T) { 70 simapp, ctx := app.CreateTestInput() 71 simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams()) 72 params := simapp.LiquidityKeeper.GetParams(ctx) 73 74 poolTypeID := types.DefaultPoolTypeID 75 addrs := app.AddTestAddrs(simapp, ctx, 4, params.PoolCreationFee) 76 77 denomA := "uETH" 78 denomB := "uUSD" 79 denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB) 80 81 deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000))) 82 app.SaveAccount(simapp, ctx, addrs[0], deposit) 83 app.SaveAccount(simapp, ctx, addrs[1], deposit) 84 85 depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA) 86 depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB) 87 depositBalance := sdk.NewCoins(depositA, depositB) 88 89 require.Equal(t, deposit, depositBalance) 90 91 depositA = simapp.BankKeeper.GetBalance(ctx, addrs[1], denomA) 92 depositB = simapp.BankKeeper.GetBalance(ctx, addrs[1], denomB) 93 depositBalance = sdk.NewCoins(depositA, depositB) 94 95 require.Equal(t, deposit, depositBalance) 96 97 createMsg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance) 98 99 _, err := simapp.LiquidityKeeper.CreatePool(ctx, createMsg) 100 require.NoError(t, err) 101 102 pools := simapp.LiquidityKeeper.GetAllPools(ctx) 103 pool := pools[0] 104 105 poolCoinBefore := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool) 106 107 depositMsg := types.NewMsgDepositWithinBatch(addrs[1], pool.Id, deposit) 108 109 handler := liquidity.NewHandler(simapp.LiquidityKeeper) 110 _, err = handler(ctx, depositMsg) 111 require.NoError(t, err) 112 113 poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, depositMsg.PoolId) 114 require.True(t, found) 115 msgs := simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch) 116 require.Equal(t, 1, len(msgs)) 117 118 err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, msgs[0], poolBatch) 119 require.NoError(t, err) 120 121 poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool) 122 depositorBalance := simapp.BankKeeper.GetBalance(ctx, addrs[1], pool.PoolCoinDenom) 123 require.Equal(t, poolCoin.Sub(poolCoinBefore), depositorBalance.Amount) 124 } 125 126 func TestMsgServerExecuteWithdrawal(t *testing.T) { 127 simapp, ctx := app.CreateTestInput() 128 simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams()) 129 params := simapp.LiquidityKeeper.GetParams(ctx) 130 131 poolTypeID := types.DefaultPoolTypeID 132 addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee) 133 134 denomA := "uETH" 135 denomB := "uUSD" 136 denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB) 137 138 deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000))) 139 app.SaveAccount(simapp, ctx, addrs[0], deposit) 140 141 depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA) 142 depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB) 143 depositBalance := sdk.NewCoins(depositA, depositB) 144 145 require.Equal(t, deposit, depositBalance) 146 147 createMsg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance) 148 149 _, err := simapp.LiquidityKeeper.CreatePool(ctx, createMsg) 150 require.NoError(t, err) 151 152 pools := simapp.LiquidityKeeper.GetAllPools(ctx) 153 pool := pools[0] 154 155 poolCoinBefore := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool) 156 withdrawerPoolCoinBefore := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom) 157 158 fmt.Println(poolCoinBefore, withdrawerPoolCoinBefore.Amount) 159 require.Equal(t, poolCoinBefore, withdrawerPoolCoinBefore.Amount) 160 withdrawMsg := types.NewMsgWithdrawWithinBatch(addrs[0], pool.Id, sdk.NewCoin(pool.PoolCoinDenom, poolCoinBefore)) 161 162 handler := liquidity.NewHandler(simapp.LiquidityKeeper) 163 _, err = handler(ctx, withdrawMsg) 164 require.NoError(t, err) 165 166 poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, withdrawMsg.PoolId) 167 require.True(t, found) 168 msgs := simapp.LiquidityKeeper.GetAllPoolBatchWithdrawMsgStates(ctx, poolBatch) 169 require.Equal(t, 1, len(msgs)) 170 171 err = simapp.LiquidityKeeper.ExecuteWithdrawal(ctx, msgs[0], poolBatch) 172 require.NoError(t, err) 173 174 poolCoinAfter := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool) 175 withdrawerPoolCoinAfter := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom) 176 require.True(t, true, poolCoinAfter.IsZero()) 177 require.True(t, true, withdrawerPoolCoinAfter.IsZero()) 178 withdrawerDenomABalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[0]) 179 withdrawerDenomBBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[1]) 180 require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[0]), withdrawerDenomABalance.Amount) 181 require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[1]), withdrawerDenomBBalance.Amount) 182 183 } 184 185 func TestMsgServerGetLiquidityPoolMetadata(t *testing.T) { 186 simapp, ctx := app.CreateTestInput() 187 simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams()) 188 params := simapp.LiquidityKeeper.GetParams(ctx) 189 190 poolTypeID := types.DefaultPoolTypeID 191 addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee) 192 193 denomA := "uETH" 194 denomB := "uUSD" 195 denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB) 196 197 deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000))) 198 app.SaveAccount(simapp, ctx, addrs[0], deposit) 199 200 depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA) 201 depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB) 202 depositBalance := sdk.NewCoins(depositA, depositB) 203 204 require.Equal(t, deposit, depositBalance) 205 206 msg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance) 207 208 handler := liquidity.NewHandler(simapp.LiquidityKeeper) 209 _, err := handler(ctx, msg) 210 require.NoError(t, err) 211 212 pools := simapp.LiquidityKeeper.GetAllPools(ctx) 213 require.Equal(t, 1, len(pools)) 214 require.Equal(t, uint64(1), pools[0].Id) 215 require.Equal(t, uint64(1), simapp.LiquidityKeeper.GetNextPoolID(ctx)-1) 216 require.Equal(t, denomA, pools[0].ReserveCoinDenoms[0]) 217 require.Equal(t, denomB, pools[0].ReserveCoinDenoms[1]) 218 219 poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pools[0]) 220 creatorBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pools[0].PoolCoinDenom) 221 require.Equal(t, poolCoin, creatorBalance.Amount) 222 223 _, err = simapp.LiquidityKeeper.CreatePool(ctx, msg) 224 require.ErrorIs(t, err, types.ErrPoolAlreadyExists) 225 226 metaData := simapp.LiquidityKeeper.GetPoolMetaData(ctx, pools[0]) 227 require.Equal(t, pools[0].Id, metaData.PoolId) 228 229 reserveCoin := simapp.LiquidityKeeper.GetReserveCoins(ctx, pools[0]) 230 require.Equal(t, reserveCoin, metaData.ReserveCoins) 231 require.Equal(t, msg.DepositCoins, metaData.ReserveCoins) 232 233 totalSupply := sdk.NewCoin(pools[0].PoolCoinDenom, simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pools[0])) 234 require.Equal(t, totalSupply, metaData.PoolCoinTotalSupply) 235 require.Equal(t, creatorBalance, metaData.PoolCoinTotalSupply) 236 } 237 238 func TestMsgServerSwap(t *testing.T) { 239 simapp, ctx := app.CreateTestInput() 240 simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams()) 241 params := simapp.LiquidityKeeper.GetParams(ctx) 242 // init test app and context 243 244 // define test denom X, Y for Liquidity Pool 245 denomX, denomY := types.AlphabeticalDenomPair("denomX", "denomY") 246 X := params.MinInitDepositAmount 247 Y := params.MinInitDepositAmount 248 249 // init addresses for the test 250 addrs := app.AddTestAddrs(simapp, ctx, 20, params.PoolCreationFee) 251 252 // Create pool 253 // The create pool msg is not run in batch, but is processed immediately. 254 poolID := app.TestCreatePool(t, simapp, ctx, X, Y, denomX, denomY, addrs[0]) 255 256 // In case of deposit, withdraw, and swap msg, unlike other normal tx msgs, 257 // collect them in the batch and perform an execution at once at the endblock. 258 259 // add a deposit to pool and run batch execution on endblock 260 app.TestDepositPool(t, simapp, ctx, X, Y, addrs[1:2], poolID, true) 261 262 // next block, reinitialize batch and increase batchIndex at beginBlocker, 263 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 264 liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper) 265 266 // Create swap msg for test purposes and put it in the batch. 267 price, _ := sdk.NewDecFromStr("1.1") 268 priceY, _ := sdk.NewDecFromStr("1.2") 269 xOfferCoins := []sdk.Coin{sdk.NewCoin(denomX, sdk.NewInt(10000)), 270 sdk.NewCoin(denomX, sdk.NewInt(10000)), 271 sdk.NewCoin(denomX, sdk.NewInt(10000))} 272 yOfferCoins := []sdk.Coin{sdk.NewCoin(denomY, sdk.NewInt(5000))} 273 xOrderPrices := []sdk.Dec{price, price, price} 274 yOrderPrices := []sdk.Dec{priceY} 275 xOrderAddrs := addrs[1:4] 276 yOrderAddrs := addrs[5:6] 277 278 msg1 := app.GetSwapMsg(t, simapp, ctx, xOfferCoins, xOrderPrices, xOrderAddrs, poolID) 279 msg4 := app.GetSwapMsg(t, simapp, ctx, yOfferCoins, yOrderPrices, yOrderAddrs, poolID) 280 281 handler := liquidity.NewHandler(simapp.LiquidityKeeper) 282 _, err := handler(ctx, msg1[0]) 283 require.NoError(t, err) 284 _, err = handler(ctx, msg1[1]) 285 require.NoError(t, err) 286 _, err = handler(ctx, msg1[2]) 287 require.NoError(t, err) 288 _, err = handler(ctx, msg4[0]) 289 require.NoError(t, err) 290 batch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, poolID) 291 require.True(t, found) 292 notProcessedMsgs := simapp.LiquidityKeeper.GetAllNotProcessedPoolBatchSwapMsgStates(ctx, batch) 293 msgs := simapp.LiquidityKeeper.GetAllPoolBatchSwapMsgStatesAsPointer(ctx, batch) 294 require.Equal(t, 4, len(msgs)) 295 require.Equal(t, 4, len(notProcessedMsgs)) 296 }