github.com/gravity-devs/liquidity@v1.5.3/x/liquidity/client/cli/cli_test.go (about)

     1  //go:build norace
     2  // +build norace
     3  
     4  package cli_test
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"fmt"
    10  	"io"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/gogo/protobuf/proto"
    16  	"github.com/spf13/viper"
    17  	"github.com/stretchr/testify/suite"
    18  
    19  	"github.com/cosmos/cosmos-sdk/client"
    20  	"github.com/cosmos/cosmos-sdk/client/flags"
    21  	"github.com/cosmos/cosmos-sdk/codec"
    22  	"github.com/cosmos/cosmos-sdk/codec/types"
    23  	"github.com/cosmos/cosmos-sdk/server"
    24  	servertypes "github.com/cosmos/cosmos-sdk/server/types"
    25  	"github.com/cosmos/cosmos-sdk/testutil"
    26  	clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
    27  	"github.com/cosmos/cosmos-sdk/testutil/network"
    28  	sdk "github.com/cosmos/cosmos-sdk/types"
    29  	"github.com/cosmos/cosmos-sdk/types/module"
    30  	genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
    31  	genutiltest "github.com/cosmos/cosmos-sdk/x/genutil/client/testutil"
    32  	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
    33  	paramscutils "github.com/cosmos/cosmos-sdk/x/params/client/utils"
    34  
    35  	lapp "github.com/gravity-devs/liquidity/app"
    36  	"github.com/gravity-devs/liquidity/x/liquidity"
    37  	"github.com/gravity-devs/liquidity/x/liquidity/client/cli"
    38  	liquiditytestutil "github.com/gravity-devs/liquidity/x/liquidity/client/testutil"
    39  	liquiditytypes "github.com/gravity-devs/liquidity/x/liquidity/types"
    40  
    41  	tmcli "github.com/tendermint/tendermint/libs/cli"
    42  	tmjson "github.com/tendermint/tendermint/libs/json"
    43  	tmlog "github.com/tendermint/tendermint/libs/log"
    44  	tmtypes "github.com/tendermint/tendermint/types"
    45  	tmdb "github.com/tendermint/tm-db"
    46  )
    47  
    48  type IntegrationTestSuite struct {
    49  	suite.Suite
    50  
    51  	cfg     network.Config
    52  	network *network.Network
    53  
    54  	db *tmdb.MemDB // in-memory database is needed for exporting genesis cli integration test
    55  }
    56  
    57  // SetupTest creates a new network for _each_ integration test. We create a new
    58  // network for each test because there are some state modifications that are
    59  // needed to be made in order to make useful queries. However, we don't want
    60  // these state changes to be present in other tests.
    61  func (s *IntegrationTestSuite) SetupTest() {
    62  	s.T().Log("setting up integration test suite")
    63  
    64  	db := tmdb.NewMemDB()
    65  
    66  	cfg := liquiditytestutil.NewConfig(db)
    67  	cfg.NumValidators = 1
    68  
    69  	var liquidityGenState liquiditytypes.GenesisState
    70  	err := cfg.Codec.UnmarshalJSON(cfg.GenesisState[liquiditytypes.ModuleName], &liquidityGenState)
    71  	s.Require().NoError(err)
    72  
    73  	liquidityGenState.Params = liquiditytypes.DefaultParams()
    74  
    75  	cfg.GenesisState[liquiditytypes.ModuleName] = cfg.Codec.MustMarshalJSON(&liquidityGenState)
    76  	cfg.AccountTokens = sdk.NewInt(100_000_000_000) // node0token denom
    77  	cfg.StakingTokens = sdk.NewInt(100_000_000_000) // stake denom
    78  
    79  	genesisStateGov := govtypes.DefaultGenesisState()
    80  	genesisStateGov.DepositParams = govtypes.NewDepositParams(sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, govtypes.DefaultMinDepositTokens)), time.Duration(15)*time.Second)
    81  	genesisStateGov.VotingParams = govtypes.NewVotingParams(time.Duration(3) * time.Second)
    82  	genesisStateGov.TallyParams.Quorum = sdk.MustNewDecFromStr("0.01")
    83  	bz, err := cfg.Codec.MarshalJSON(genesisStateGov)
    84  	s.Require().NoError(err)
    85  	cfg.GenesisState["gov"] = bz
    86  
    87  	s.cfg = cfg
    88  	s.network = network.New(s.T(), s.cfg)
    89  	s.db = db
    90  
    91  	_, err = s.network.WaitForHeight(1)
    92  	s.Require().NoError(err)
    93  }
    94  
    95  // TearDownTest cleans up the curret test network after each test in the suite.
    96  func (s *IntegrationTestSuite) TearDownTest() {
    97  	s.T().Log("tearing down integration test suite")
    98  	s.network.Cleanup()
    99  }
   100  
   101  // TestIntegrationTestSuite every integration test suite.
   102  func TestIntegrationTestSuite(t *testing.T) {
   103  	suite.Run(t, new(IntegrationTestSuite))
   104  }
   105  
   106  func (s *IntegrationTestSuite) TestNewCreatePoolCmd() {
   107  	val := s.network.Validators[0]
   108  
   109  	// use two different tokens that are minted to the test account
   110  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   111  
   112  	testCases := []struct {
   113  		name         string
   114  		args         []string
   115  		expectErr    bool
   116  		respType     proto.Message
   117  		expectedCode uint32
   118  	}{
   119  		{
   120  			"invalid pool type id",
   121  			[]string{
   122  				"invalidpooltypeid",
   123  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   124  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   125  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   126  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   127  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   128  			},
   129  			true, nil, 0,
   130  		},
   131  		{
   132  			"pool type id is not supported",
   133  			[]string{
   134  				fmt.Sprintf("%d", uint32(2)),
   135  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000)), sdk.NewCoin("denomZ", sdk.NewInt(100_000_000))).String(),
   136  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   137  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   138  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   139  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   140  			},
   141  			true, nil, 0,
   142  		},
   143  		{
   144  			"invalid number of denoms",
   145  			[]string{
   146  				fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   147  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000)), sdk.NewCoin("denomZ", sdk.NewInt(100_000_000))).String(),
   148  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   149  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   150  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   151  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   152  			},
   153  			true, nil, 0,
   154  		},
   155  		{
   156  			"deposit coin less than minimum deposit amount",
   157  			[]string{
   158  				fmt.Sprintf("%d", uint32(1)),
   159  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(1_000)), sdk.NewCoin(denomY, sdk.NewInt(10_000_000))).String(),
   160  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   161  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   162  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   163  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   164  			},
   165  			false, &sdk.TxResponse{}, 9,
   166  		},
   167  		{
   168  			"valid transaction",
   169  			[]string{
   170  				fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   171  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   172  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   173  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   174  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   175  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   176  			},
   177  			false, &sdk.TxResponse{}, 0,
   178  		},
   179  	}
   180  
   181  	for _, tc := range testCases {
   182  		tc := tc
   183  
   184  		s.Run(tc.name, func() {
   185  			cmd := cli.NewCreatePoolCmd()
   186  			clientCtx := val.ClientCtx
   187  
   188  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   189  
   190  			if tc.expectErr {
   191  				s.Require().Error(err)
   192  			} else {
   193  				s.Require().NoError(err, out.String())
   194  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   195  
   196  				txResp := tc.respType.(*sdk.TxResponse)
   197  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   198  			}
   199  		})
   200  	}
   201  }
   202  
   203  func (s *IntegrationTestSuite) TestNewDepositWithinBatchCmd() {
   204  	val := s.network.Validators[0]
   205  
   206  	// use two different tokens that are minted to the test account
   207  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   208  
   209  	// liquidity pool should be created prior to test this integration test
   210  	_, err := liquiditytestutil.MsgCreatePoolExec(
   211  		val.ClientCtx,
   212  		val.Address.String(),
   213  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   214  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   215  	)
   216  	s.Require().NoError(err)
   217  
   218  	err = s.network.WaitForNextBlock()
   219  	s.Require().NoError(err)
   220  
   221  	testCases := []struct {
   222  		name         string
   223  		args         []string
   224  		expectErr    bool
   225  		respType     proto.Message
   226  		expectedCode uint32
   227  	}{
   228  		{
   229  			"invalid pool id",
   230  			[]string{
   231  				"invalidpoolid",
   232  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(1_000_000)), sdk.NewCoin(denomY, sdk.NewInt(1_000_000))).String(),
   233  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   234  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   235  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   236  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   237  			},
   238  			true, nil, 0,
   239  		},
   240  		{
   241  			"invalid number of denoms",
   242  			[]string{
   243  				fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   244  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(1_000_000)), sdk.NewCoin(denomY, sdk.NewInt(1_000_000)), sdk.NewCoin("denomZ", sdk.NewInt(1_000_000))).String(),
   245  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   246  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   247  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   248  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   249  			},
   250  			true, nil, 0,
   251  		},
   252  		{
   253  			"valid transaction",
   254  			[]string{
   255  				fmt.Sprintf("%d", uint32(1)),
   256  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(10_000_000)), sdk.NewCoin(denomY, sdk.NewInt(10_000_000))).String(),
   257  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   258  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   259  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   260  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   261  			},
   262  			false, &sdk.TxResponse{}, 0,
   263  		},
   264  	}
   265  
   266  	for _, tc := range testCases {
   267  		tc := tc
   268  
   269  		s.Run(tc.name, func() {
   270  			cmd := cli.NewDepositWithinBatchCmd()
   271  			clientCtx := val.ClientCtx
   272  
   273  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   274  
   275  			if tc.expectErr {
   276  				s.Require().Error(err)
   277  			} else {
   278  				s.Require().NoError(err, out.String())
   279  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   280  
   281  				txResp := tc.respType.(*sdk.TxResponse)
   282  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   283  			}
   284  		})
   285  	}
   286  }
   287  
   288  func (s *IntegrationTestSuite) TestNewWithdrawWithinBatchCmd() {
   289  	val := s.network.Validators[0]
   290  
   291  	// use two different tokens that are minted to the test account
   292  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   293  
   294  	// liquidity pool should be created prior to test this integration test
   295  	_, err := liquiditytestutil.MsgCreatePoolExec(
   296  		val.ClientCtx,
   297  		val.Address.String(),
   298  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   299  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   300  	)
   301  	s.Require().NoError(err)
   302  
   303  	err = s.network.WaitForNextBlock()
   304  	s.Require().NoError(err)
   305  
   306  	testCases := []struct {
   307  		name         string
   308  		args         []string
   309  		expectErr    bool
   310  		respType     proto.Message
   311  		expectedCode uint32
   312  	}{
   313  		{
   314  			"invalid pool id",
   315  			[]string{
   316  				"invalidpoolid",
   317  				sdk.NewCoins(sdk.NewCoin("poolC33A77E752C183913636A37FE1388ACA22FE7BED792BEB2E72EF2DA857703D8D", sdk.NewInt(10_000))).String(),
   318  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   319  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   320  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   321  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   322  			},
   323  			true, nil, 0,
   324  		},
   325  		{
   326  			"bad pool coin",
   327  			[]string{
   328  				fmt.Sprintf("%d", uint32(1)),
   329  				sdk.NewCoins(sdk.NewCoin("badpoolcoindenom", sdk.NewInt(10_000))).String(),
   330  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   331  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   332  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   333  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   334  			},
   335  			false, &sdk.TxResponse{}, 29,
   336  		},
   337  		{
   338  			"valid transaction",
   339  			[]string{
   340  				fmt.Sprintf("%d", uint32(1)),
   341  				sdk.NewCoins(sdk.NewCoin("poolC33A77E752C183913636A37FE1388ACA22FE7BED792BEB2E72EF2DA857703D8D", sdk.NewInt(10_000))).String(),
   342  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   343  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   344  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   345  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   346  			},
   347  			false, &sdk.TxResponse{}, 0,
   348  		},
   349  	}
   350  
   351  	for _, tc := range testCases {
   352  		tc := tc
   353  
   354  		s.Run(tc.name, func() {
   355  			cmd := cli.NewWithdrawWithinBatchCmd()
   356  			clientCtx := val.ClientCtx
   357  
   358  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   359  
   360  			if tc.expectErr {
   361  				s.Require().Error(err)
   362  			} else {
   363  				s.Require().NoError(err, out.String())
   364  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   365  
   366  				txResp := tc.respType.(*sdk.TxResponse)
   367  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   368  			}
   369  		})
   370  	}
   371  }
   372  
   373  func (s *IntegrationTestSuite) TestNewSwapWithinBatchCmd() {
   374  	val := s.network.Validators[0]
   375  
   376  	// use two different tokens that are minted to the test account
   377  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   378  
   379  	// liquidity pool should be created prior to test this integration test
   380  	_, err := liquiditytestutil.MsgCreatePoolExec(
   381  		val.ClientCtx,
   382  		val.Address.String(),
   383  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   384  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   385  	)
   386  	s.Require().NoError(err)
   387  
   388  	err = s.network.WaitForNextBlock()
   389  	s.Require().NoError(err)
   390  
   391  	testCases := []struct {
   392  		name         string
   393  		args         []string
   394  		expectErr    bool
   395  		respType     proto.Message
   396  		expectedCode uint32
   397  	}{
   398  		{
   399  			"invalid pool id",
   400  			[]string{
   401  				"invalidpoolid",
   402  				fmt.Sprintf("%d", uint32(1)),
   403  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(10_000))).String(),
   404  				denomY,
   405  				fmt.Sprintf("%.2f", 0.02),
   406  				fmt.Sprintf("%.3f", 0.003),
   407  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   408  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   409  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   410  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   411  			},
   412  			true, nil, 0,
   413  		},
   414  		{
   415  			"swap type id not supported",
   416  			[]string{
   417  				fmt.Sprintf("%d", uint32(1)),
   418  				fmt.Sprintf("%d", uint32(2)),
   419  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(10_000))).String(),
   420  				denomY,
   421  				fmt.Sprintf("%.2f", 0.02),
   422  				fmt.Sprintf("%.2f", 0.03),
   423  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   424  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   425  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   426  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   427  			},
   428  			true, nil, 0,
   429  		},
   430  		{
   431  			"bad offer coin fee",
   432  			[]string{
   433  				fmt.Sprintf("%d", uint32(1)),
   434  				fmt.Sprintf("%d", uint32(1)),
   435  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(10_000))).String(),
   436  				denomY,
   437  				fmt.Sprintf("%.2f", 0.02),
   438  				fmt.Sprintf("%.2f", 0.01),
   439  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   440  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   441  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   442  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   443  			},
   444  			false, &sdk.TxResponse{}, 35,
   445  		},
   446  		{
   447  			"valid transaction",
   448  			[]string{
   449  				fmt.Sprintf("%d", uint32(1)),
   450  				fmt.Sprintf("%d", liquiditytypes.DefaultSwapTypeID),
   451  				sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(10_000))).String(),
   452  				denomY,
   453  				fmt.Sprintf("%.2f", 1.0),
   454  				fmt.Sprintf("%.3f", 0.003),
   455  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   456  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   457  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   458  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   459  			},
   460  			false, &sdk.TxResponse{}, 0,
   461  		},
   462  	}
   463  
   464  	for _, tc := range testCases {
   465  		tc := tc
   466  
   467  		s.Run(tc.name, func() {
   468  			cmd := cli.NewSwapWithinBatchCmd()
   469  			clientCtx := val.ClientCtx
   470  
   471  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   472  
   473  			if tc.expectErr {
   474  				s.Require().Error(err)
   475  			} else {
   476  				s.Require().NoError(err, out.String())
   477  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   478  
   479  				txResp := tc.respType.(*sdk.TxResponse)
   480  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   481  			}
   482  		})
   483  	}
   484  }
   485  
   486  func (s *IntegrationTestSuite) TestGetCmdQueryParams() {
   487  	val := s.network.Validators[0]
   488  
   489  	testCases := []struct {
   490  		name           string
   491  		args           []string
   492  		expectedOutput string
   493  	}{
   494  		{
   495  			"json output",
   496  			[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
   497  			`{"pool_types":[{"id":1,"name":"StandardLiquidityPool","min_reserve_coin_num":2,"max_reserve_coin_num":2,"description":"Standard liquidity pool with pool price function X/Y, ESPM constraint, and two kinds of reserve coins"}],"min_init_deposit_amount":"1000000","init_pool_coin_mint_amount":"1000000","max_reserve_coin_amount":"0","pool_creation_fee":[{"denom":"stake","amount":"40000000"}],"swap_fee_rate":"0.003000000000000000","withdraw_fee_rate":"0.000000000000000000","max_order_amount_ratio":"0.100000000000000000","unit_batch_height":1,"circuit_breaker_enabled":false}`,
   498  		},
   499  		{
   500  			"text output",
   501  			[]string{fmt.Sprintf("--%s=text", tmcli.OutputFlag)},
   502  			`circuit_breaker_enabled: false
   503  init_pool_coin_mint_amount: "1000000"
   504  max_order_amount_ratio: "0.100000000000000000"
   505  max_reserve_coin_amount: "0"
   506  min_init_deposit_amount: "1000000"
   507  pool_creation_fee:
   508  - amount: "40000000"
   509    denom: stake
   510  pool_types:
   511  - description: Standard liquidity pool with pool price function X/Y, ESPM constraint,
   512      and two kinds of reserve coins
   513    id: 1
   514    max_reserve_coin_num: 2
   515    min_reserve_coin_num: 2
   516    name: StandardLiquidityPool
   517  swap_fee_rate: "0.003000000000000000"
   518  unit_batch_height: 1
   519  withdraw_fee_rate: "0.000000000000000000"`,
   520  		},
   521  	}
   522  
   523  	for _, tc := range testCases {
   524  		tc := tc
   525  
   526  		s.Run(tc.name, func() {
   527  			cmd := cli.GetCmdQueryParams()
   528  			clientCtx := val.ClientCtx
   529  
   530  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   531  			s.Require().NoError(err)
   532  			s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String()))
   533  		})
   534  	}
   535  }
   536  
   537  func (s *IntegrationTestSuite) TestGetCmdQueryLiquidityPool() {
   538  	val := s.network.Validators[0]
   539  
   540  	// use two different tokens that are minted to the test account
   541  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   542  
   543  	// liquidity pool should be created prior to test this integration test
   544  	_, err := liquiditytestutil.MsgCreatePoolExec(
   545  		val.ClientCtx,
   546  		val.Address.String(),
   547  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   548  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   549  	)
   550  	s.Require().NoError(err)
   551  
   552  	err = s.network.WaitForNextBlock()
   553  	s.Require().NoError(err)
   554  
   555  	testCases := []struct {
   556  		name      string
   557  		args      []string
   558  		expectErr bool
   559  	}{
   560  		{
   561  			"with invalid pool id",
   562  			[]string{
   563  				"invalidpoolid",
   564  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   565  			},
   566  			true,
   567  		},
   568  		{
   569  			"with not supported pool id",
   570  			[]string{
   571  				fmt.Sprintf("%d", uint32(2)),
   572  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   573  			},
   574  			true,
   575  		},
   576  		{
   577  			"valid case with pool id",
   578  			[]string{
   579  				fmt.Sprintf("%d", uint32(1)),
   580  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   581  			},
   582  			false,
   583  		},
   584  		{
   585  			"with invalid pool coin denom",
   586  			[]string{
   587  				fmt.Sprintf("--%s=%s", cli.FlagPoolCoinDenom, "invalid_value"),
   588  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   589  			},
   590  			true,
   591  		},
   592  		{
   593  			"with empty pool coin denom",
   594  			[]string{
   595  				fmt.Sprintf("--%s", cli.FlagPoolCoinDenom),
   596  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   597  			},
   598  			true,
   599  		},
   600  		{
   601  			"valid case with pool coin denom",
   602  			[]string{
   603  				fmt.Sprintf("--%s=%s", cli.FlagPoolCoinDenom, "poolC33A77E752C183913636A37FE1388ACA22FE7BED792BEB2E72EF2DA857703D8D"),
   604  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   605  			},
   606  			false,
   607  		},
   608  		{
   609  			"with invalid reserve acc",
   610  			[]string{
   611  				fmt.Sprintf("--%s=%s", cli.FlagReserveAcc, "invalid_value"),
   612  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   613  			},
   614  			true,
   615  		},
   616  		{
   617  			"with empty reserve acc",
   618  			[]string{
   619  				fmt.Sprintf("--%s", cli.FlagReserveAcc),
   620  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   621  			},
   622  			true,
   623  		},
   624  		{
   625  			"valid case with reserve acc",
   626  			[]string{
   627  				fmt.Sprintf("--%s=%s", cli.FlagReserveAcc, "cosmos1cva80e6jcxpezd3k5dl7zwy2eg30u7ld3y0a67"),
   628  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   629  			},
   630  			false,
   631  		},
   632  	}
   633  
   634  	for _, tc := range testCases {
   635  		tc := tc
   636  
   637  		s.Run(tc.name, func() {
   638  			cmd := cli.GetCmdQueryLiquidityPool()
   639  			clientCtx := val.ClientCtx
   640  
   641  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   642  
   643  			if tc.expectErr {
   644  				s.Require().Error(err)
   645  			} else {
   646  				var resp liquiditytypes.QueryLiquidityPoolResponse
   647  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp)
   648  				s.Require().NoError(err)
   649  				s.Require().Equal(uint64(1), resp.GetPool().Id)
   650  				s.Require().Equal(uint32(1), resp.GetPool().TypeId)
   651  				s.Require().Len(resp.GetPool().ReserveCoinDenoms, 2)
   652  			}
   653  		})
   654  	}
   655  }
   656  
   657  func (s *IntegrationTestSuite) TestGetCmdQueryLiquidityPools() {
   658  	val := s.network.Validators[0]
   659  
   660  	// use two different tokens that are minted to the test account
   661  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   662  
   663  	// liquidity pool should be created prior to test this integration test
   664  	_, err := liquiditytestutil.MsgCreatePoolExec(
   665  		val.ClientCtx,
   666  		val.Address.String(),
   667  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   668  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   669  	)
   670  	s.Require().NoError(err)
   671  
   672  	err = s.network.WaitForNextBlock()
   673  	s.Require().NoError(err)
   674  
   675  	testCases := []struct {
   676  		name      string
   677  		args      []string
   678  		expectErr bool
   679  	}{
   680  		{
   681  			"valid case",
   682  			[]string{
   683  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   684  			},
   685  			false,
   686  		},
   687  	}
   688  
   689  	for _, tc := range testCases {
   690  		tc := tc
   691  
   692  		s.Run(tc.name, func() {
   693  			cmd := cli.GetCmdQueryLiquidityPools()
   694  			clientCtx := val.ClientCtx
   695  
   696  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   697  
   698  			if tc.expectErr {
   699  				s.Require().Error(err)
   700  			} else {
   701  				var resps liquiditytypes.QueryLiquidityPoolsResponse
   702  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resps)
   703  				s.Require().NoError(err)
   704  
   705  				for _, pool := range resps.GetPools() {
   706  					s.Require().Equal(uint64(1), pool.Id)
   707  					s.Require().Equal(uint32(1), pool.TypeId)
   708  					s.Require().Len(pool.ReserveCoinDenoms, 2)
   709  				}
   710  			}
   711  		})
   712  	}
   713  }
   714  
   715  func (s *IntegrationTestSuite) TestGetCmdQueryLiquidityPoolBatch() {
   716  	val := s.network.Validators[0]
   717  
   718  	// use two different tokens that are minted to the test account
   719  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   720  
   721  	// liquidity pool should be created prior to test this integration test
   722  	_, err := liquiditytestutil.MsgCreatePoolExec(
   723  		val.ClientCtx,
   724  		val.Address.String(),
   725  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   726  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   727  	)
   728  	s.Require().NoError(err)
   729  
   730  	testCases := []struct {
   731  		name      string
   732  		args      []string
   733  		expectErr bool
   734  	}{
   735  		{
   736  			"with invalid pool id",
   737  			[]string{
   738  				"invalidpoolid",
   739  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   740  			},
   741  			true,
   742  		},
   743  		{
   744  			"with not supported pool id",
   745  			[]string{
   746  				fmt.Sprintf("%d", uint32(2)),
   747  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   748  			},
   749  			true,
   750  		},
   751  		{
   752  			"valid case",
   753  			[]string{
   754  				fmt.Sprintf("%d", uint32(1)),
   755  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   756  			},
   757  			false,
   758  		},
   759  	}
   760  
   761  	for _, tc := range testCases {
   762  		tc := tc
   763  
   764  		s.Run(tc.name, func() {
   765  			cmd := cli.GetCmdQueryLiquidityPoolBatch()
   766  			clientCtx := val.ClientCtx
   767  
   768  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   769  
   770  			if tc.expectErr {
   771  				s.Require().Error(err)
   772  			} else {
   773  				var resp liquiditytypes.QueryLiquidityPoolBatchResponse
   774  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp)
   775  				s.Require().NoError(err)
   776  				s.Require().Equal(uint64(1), resp.GetBatch().PoolId)
   777  				s.Require().Equal(false, resp.GetBatch().Executed)
   778  			}
   779  		})
   780  	}
   781  }
   782  
   783  func (s *IntegrationTestSuite) TestGetCmdQueryPoolBatchDepositMsg() {
   784  	val := s.network.Validators[0]
   785  
   786  	// use two different tokens that are minted to the test account
   787  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   788  
   789  	// liquidity pool should be created prior to test this integration test
   790  	_, err := liquiditytestutil.MsgCreatePoolExec(
   791  		val.ClientCtx,
   792  		val.Address.String(),
   793  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   794  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   795  	)
   796  	s.Require().NoError(err)
   797  
   798  	err = s.network.WaitForNextBlock()
   799  	s.Require().NoError(err)
   800  
   801  	// create new deposit
   802  	_, err = liquiditytestutil.MsgDepositWithinBatchExec(
   803  		val.ClientCtx,
   804  		val.Address.String(),
   805  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   806  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(10_000_000)), sdk.NewCoin(denomY, sdk.NewInt(10_000_000))).String(),
   807  	)
   808  	s.Require().NoError(err)
   809  
   810  	testCases := []struct {
   811  		name      string
   812  		args      []string
   813  		expectErr bool
   814  	}{
   815  		{
   816  			"with invalid pool id",
   817  			[]string{
   818  				"invalidpoolid",
   819  				fmt.Sprintf("%d", uint32(1)),
   820  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   821  			},
   822  			true,
   823  		},
   824  		{
   825  			"with not supported pool id",
   826  			[]string{
   827  				fmt.Sprintf("%d", uint32(2)),
   828  				fmt.Sprintf("%d", uint32(1)),
   829  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   830  			},
   831  			true,
   832  		},
   833  		{
   834  			"valid case",
   835  			[]string{
   836  				fmt.Sprintf("%d", uint32(1)),
   837  				fmt.Sprintf("%d", uint32(1)),
   838  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   839  			},
   840  			false,
   841  		},
   842  	}
   843  
   844  	for _, tc := range testCases {
   845  		tc := tc
   846  
   847  		s.Run(tc.name, func() {
   848  			cmd := cli.GetCmdQueryPoolBatchDepositMsg()
   849  			clientCtx := val.ClientCtx
   850  
   851  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   852  
   853  			if tc.expectErr {
   854  				s.Require().Error(err)
   855  			} else {
   856  				var resp liquiditytypes.QueryPoolBatchDepositMsgResponse
   857  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp)
   858  				s.Require().NoError(err)
   859  				s.Require().Equal(val.Address.String(), resp.GetDeposit().Msg.DepositorAddress)
   860  				s.Require().Equal(true, resp.GetDeposit().Executed)
   861  				s.Require().Equal(true, resp.GetDeposit().Succeeded)
   862  				s.Require().Equal(true, resp.GetDeposit().ToBeDeleted)
   863  			}
   864  		})
   865  	}
   866  }
   867  
   868  func (s *IntegrationTestSuite) TestGetCmdQueryPoolBatchDepositMsgs() {
   869  	val := s.network.Validators[0]
   870  
   871  	// use two different tokens that are minted to the test account
   872  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   873  
   874  	// liquidity pool should be created prior to test this integration test
   875  	_, err := liquiditytestutil.MsgCreatePoolExec(
   876  		val.ClientCtx,
   877  		val.Address.String(),
   878  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   879  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   880  	)
   881  	s.Require().NoError(err)
   882  
   883  	err = s.network.WaitForNextBlock()
   884  	s.Require().NoError(err)
   885  
   886  	// create new deposit
   887  	_, err = liquiditytestutil.MsgDepositWithinBatchExec(
   888  		val.ClientCtx,
   889  		val.Address.String(),
   890  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   891  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(10_000_000)), sdk.NewCoin(denomY, sdk.NewInt(10_000_000))).String(),
   892  	)
   893  	s.Require().NoError(err)
   894  
   895  	testCases := []struct {
   896  		name      string
   897  		args      []string
   898  		expectErr bool
   899  	}{
   900  		{
   901  			"with invalid pool id",
   902  			[]string{
   903  				"invalidpoolid",
   904  				fmt.Sprintf("%d", uint32(1)),
   905  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   906  			},
   907  			true,
   908  		},
   909  		{
   910  			"with not supported pool id",
   911  			[]string{
   912  				fmt.Sprintf("%d", uint32(2)),
   913  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   914  			},
   915  			true,
   916  		},
   917  		{
   918  			"valid case",
   919  			[]string{
   920  				fmt.Sprintf("%d", uint32(1)),
   921  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   922  			},
   923  			false,
   924  		},
   925  	}
   926  
   927  	for _, tc := range testCases {
   928  		tc := tc
   929  
   930  		s.Run(tc.name, func() {
   931  			cmd := cli.GetCmdQueryPoolBatchDepositMsgs()
   932  			clientCtx := val.ClientCtx
   933  
   934  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   935  
   936  			if tc.expectErr {
   937  				s.Require().Error(err)
   938  			} else {
   939  				var resps liquiditytypes.QueryPoolBatchDepositMsgsResponse
   940  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resps)
   941  				s.Require().NoError(err)
   942  
   943  				for _, deposit := range resps.GetDeposits() {
   944  					s.Require().Equal(true, deposit.Executed)
   945  					s.Require().Equal(true, deposit.Succeeded)
   946  					s.Require().Equal(true, deposit.ToBeDeleted)
   947  				}
   948  			}
   949  		})
   950  	}
   951  }
   952  
   953  func (s *IntegrationTestSuite) TestGetCmdQueryPoolBatchWithdrawMsg() {
   954  	val := s.network.Validators[0]
   955  
   956  	// use two different tokens that are minted to the test account
   957  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
   958  
   959  	// liquidity pool should be created prior to test this integration test
   960  	_, err := liquiditytestutil.MsgCreatePoolExec(
   961  		val.ClientCtx,
   962  		val.Address.String(),
   963  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
   964  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
   965  	)
   966  	s.Require().NoError(err)
   967  
   968  	err = s.network.WaitForNextBlock()
   969  	s.Require().NoError(err)
   970  
   971  	// withdraw pool coin from the pool
   972  	poolCoinDenom := "poolC33A77E752C183913636A37FE1388ACA22FE7BED792BEB2E72EF2DA857703D8D"
   973  	_, err = liquiditytestutil.MsgWithdrawWithinBatchExec(
   974  		val.ClientCtx,
   975  		val.Address.String(),
   976  		fmt.Sprintf("%d", uint32(1)),
   977  		sdk.NewCoins(sdk.NewCoin(poolCoinDenom, sdk.NewInt(10_000))).String(),
   978  	)
   979  	s.Require().NoError(err)
   980  
   981  	testCases := []struct {
   982  		name      string
   983  		args      []string
   984  		expectErr bool
   985  	}{
   986  		{
   987  			"with invalid pool id",
   988  			[]string{
   989  				"invalidpoolid",
   990  				fmt.Sprintf("%d", uint32(1)),
   991  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
   992  			},
   993  			true,
   994  		},
   995  		{
   996  			"with not suppoorted pool id",
   997  			[]string{
   998  				fmt.Sprintf("%d", uint32(2)),
   999  				fmt.Sprintf("%d", uint32(1)),
  1000  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1001  			},
  1002  			true,
  1003  		},
  1004  		{
  1005  			"valid case",
  1006  			[]string{
  1007  				fmt.Sprintf("%d", uint32(1)),
  1008  				fmt.Sprintf("%d", uint32(1)),
  1009  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1010  			},
  1011  			false,
  1012  		},
  1013  	}
  1014  
  1015  	for _, tc := range testCases {
  1016  		tc := tc
  1017  
  1018  		s.Run(tc.name, func() {
  1019  			cmd := cli.GetCmdQueryPoolBatchWithdrawMsg()
  1020  			clientCtx := val.ClientCtx
  1021  
  1022  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1023  
  1024  			if tc.expectErr {
  1025  				s.Require().Error(err)
  1026  			} else {
  1027  				var resp liquiditytypes.QueryPoolBatchWithdrawMsgResponse
  1028  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp)
  1029  				s.Require().NoError(err)
  1030  				s.Require().Equal(val.Address.String(), resp.GetWithdraw().Msg.WithdrawerAddress)
  1031  				s.Require().Equal(poolCoinDenom, resp.GetWithdraw().Msg.PoolCoin.Denom)
  1032  				s.Require().Equal(true, resp.GetWithdraw().Executed)
  1033  				s.Require().Equal(true, resp.GetWithdraw().Succeeded)
  1034  				s.Require().Equal(true, resp.GetWithdraw().ToBeDeleted)
  1035  			}
  1036  		})
  1037  	}
  1038  }
  1039  
  1040  func (s *IntegrationTestSuite) TestGetCmdQueryPoolBatchWithdrawMsgs() {
  1041  	val := s.network.Validators[0]
  1042  
  1043  	// use two different tokens that are minted to the test account
  1044  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
  1045  
  1046  	// liquidity pool should be created prior to test this integration test
  1047  	_, err := liquiditytestutil.MsgCreatePoolExec(
  1048  		val.ClientCtx,
  1049  		val.Address.String(),
  1050  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
  1051  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(100_000_000)), sdk.NewCoin(denomY, sdk.NewInt(100_000_000))).String(),
  1052  	)
  1053  	s.Require().NoError(err)
  1054  
  1055  	err = s.network.WaitForNextBlock()
  1056  	s.Require().NoError(err)
  1057  
  1058  	// withdraw pool coin from the pool
  1059  	_, err = liquiditytestutil.MsgWithdrawWithinBatchExec(
  1060  		val.ClientCtx,
  1061  		val.Address.String(),
  1062  		fmt.Sprintf("%d", uint32(1)),
  1063  		sdk.NewCoins(sdk.NewCoin("poolC33A77E752C183913636A37FE1388ACA22FE7BED792BEB2E72EF2DA857703D8D", sdk.NewInt(10_000))).String(),
  1064  	)
  1065  	s.Require().NoError(err)
  1066  
  1067  	testCases := []struct {
  1068  		name      string
  1069  		args      []string
  1070  		expectErr bool
  1071  	}{
  1072  		{
  1073  			"with invalid pool id",
  1074  			[]string{
  1075  				"invalidpoolid",
  1076  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1077  			},
  1078  			true,
  1079  		},
  1080  		{
  1081  			"with not supported pool id",
  1082  			[]string{
  1083  				fmt.Sprintf("%d", uint32(2)),
  1084  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1085  			},
  1086  			true,
  1087  		},
  1088  		{
  1089  			"valid case",
  1090  			[]string{
  1091  				fmt.Sprintf("%d", uint32(1)),
  1092  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1093  			},
  1094  			false,
  1095  		},
  1096  	}
  1097  
  1098  	for _, tc := range testCases {
  1099  		tc := tc
  1100  
  1101  		s.Run(tc.name, func() {
  1102  			cmd := cli.GetCmdQueryPoolBatchWithdrawMsgs()
  1103  			clientCtx := val.ClientCtx
  1104  
  1105  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1106  
  1107  			if tc.expectErr {
  1108  				s.Require().Error(err)
  1109  			} else {
  1110  				var resps liquiditytypes.QueryPoolBatchWithdrawMsgsResponse
  1111  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resps)
  1112  				s.Require().NoError(err)
  1113  
  1114  				for _, withdraw := range resps.GetWithdraws() {
  1115  					s.Require().Equal(val.Address.String(), withdraw.Msg.WithdrawerAddress)
  1116  					s.Require().Equal(true, withdraw.Executed)
  1117  					s.Require().Equal(true, withdraw.Succeeded)
  1118  					s.Require().Equal(true, withdraw.ToBeDeleted)
  1119  				}
  1120  			}
  1121  		})
  1122  	}
  1123  }
  1124  
  1125  func (s *IntegrationTestSuite) TestGetCmdQueryPoolBatchSwapMsg() {
  1126  	val := s.network.Validators[0]
  1127  
  1128  	// use two different tokens that are minted to the test account
  1129  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
  1130  	X := sdk.NewCoin(denomX, sdk.NewInt(1_000_000_000))
  1131  	Y := sdk.NewCoin(denomY, sdk.NewInt(5_000_000_000))
  1132  
  1133  	// liquidity pool should be created prior to test this integration test
  1134  	_, err := liquiditytestutil.MsgCreatePoolExec(
  1135  		val.ClientCtx,
  1136  		val.Address.String(),
  1137  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
  1138  		sdk.NewCoins(X, Y).String(),
  1139  	)
  1140  	s.Require().NoError(err)
  1141  
  1142  	err = s.network.WaitForNextBlock()
  1143  	s.Require().NoError(err)
  1144  
  1145  	// swap coins from the pool
  1146  	offerCoin := sdk.NewCoin(denomY, sdk.NewInt(50_000_000))
  1147  	_, err = liquiditytestutil.MsgSwapWithinBatchExec(
  1148  		val.ClientCtx,
  1149  		val.Address.String(),
  1150  		fmt.Sprintf("%d", uint32(1)),
  1151  		fmt.Sprintf("%d", liquiditytypes.DefaultSwapTypeID),
  1152  		offerCoin.String(),
  1153  		denomX,
  1154  		fmt.Sprintf("%.3f", 0.019),
  1155  		fmt.Sprintf("%.3f", 0.003),
  1156  	)
  1157  	s.Require().NoError(err)
  1158  
  1159  	testCases := []struct {
  1160  		name      string
  1161  		args      []string
  1162  		expectErr bool
  1163  	}{
  1164  		{
  1165  			"with invalid pool id",
  1166  			[]string{
  1167  				"invalidpoolid",
  1168  				fmt.Sprintf("%d", uint32(1)),
  1169  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1170  			},
  1171  			true,
  1172  		},
  1173  		{
  1174  			"with not supported pool id",
  1175  			[]string{
  1176  				fmt.Sprintf("%d", uint32(2)),
  1177  				fmt.Sprintf("%d", uint32(1)),
  1178  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1179  			},
  1180  			true,
  1181  		},
  1182  		{
  1183  			"valid case",
  1184  			[]string{
  1185  				fmt.Sprintf("%d", uint32(1)),
  1186  				fmt.Sprintf("%d", uint32(1)),
  1187  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1188  			},
  1189  			false,
  1190  		},
  1191  	}
  1192  
  1193  	for _, tc := range testCases {
  1194  		tc := tc
  1195  
  1196  		s.Run(tc.name, func() {
  1197  			cmd := cli.GetCmdQueryPoolBatchSwapMsg()
  1198  			clientCtx := val.ClientCtx
  1199  
  1200  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1201  
  1202  			if tc.expectErr {
  1203  				s.Require().Error(err)
  1204  			} else {
  1205  				var resp liquiditytypes.QueryPoolBatchSwapMsgResponse
  1206  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp)
  1207  				s.Require().NoError(err)
  1208  				s.Require().Equal(val.Address.String(), resp.GetSwap().Msg.SwapRequesterAddress)
  1209  				s.Require().Equal(true, resp.GetSwap().Executed)
  1210  				s.Require().Equal(true, resp.GetSwap().Succeeded)
  1211  				s.Require().Equal(true, resp.GetSwap().ToBeDeleted)
  1212  			}
  1213  		})
  1214  	}
  1215  }
  1216  
  1217  func (s *IntegrationTestSuite) TestGetCircuitBreaker() {
  1218  	val := s.network.Validators[0]
  1219  
  1220  	// use two different tokens that are minted to the test account
  1221  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
  1222  	X := sdk.NewCoin(denomX, sdk.NewInt(1_000_000_000))
  1223  	Y := sdk.NewCoin(denomY, sdk.NewInt(5_000_000_000))
  1224  
  1225  	// liquidity pool should be created prior to test this integration test
  1226  	_, err := liquiditytestutil.MsgCreatePoolExec(
  1227  		val.ClientCtx,
  1228  		val.Address.String(),
  1229  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
  1230  		sdk.NewCoins(X, Y).String(),
  1231  	)
  1232  	s.Require().NoError(err)
  1233  
  1234  	err = s.network.WaitForNextBlock()
  1235  	s.Require().NoError(err)
  1236  
  1237  	// swap coins from the pool
  1238  	offerCoin := sdk.NewCoin(denomY, sdk.NewInt(50_000_000))
  1239  	output, err := liquiditytestutil.MsgSwapWithinBatchExec(
  1240  		val.ClientCtx,
  1241  		val.Address.String(),
  1242  		fmt.Sprintf("%d", uint32(1)),
  1243  		fmt.Sprintf("%d", liquiditytypes.DefaultSwapTypeID),
  1244  		offerCoin.String(),
  1245  		denomX,
  1246  		fmt.Sprintf("%.3f", 0.019),
  1247  		fmt.Sprintf("%.3f", 0.003),
  1248  	)
  1249  	var txRes sdk.TxResponse
  1250  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(output.Bytes(), &txRes))
  1251  	s.Require().Equal(txRes.Code, uint32(0))
  1252  	s.Require().NoError(err)
  1253  
  1254  	circuitBreakerEnabled := true
  1255  	circuitBreakerEnabledStr, err := json.Marshal(&circuitBreakerEnabled)
  1256  	if err != nil {
  1257  		panic(err)
  1258  	}
  1259  
  1260  	paramChange := paramscutils.ParamChangeProposalJSON{
  1261  		Title:       "enable-circuit-breaker",
  1262  		Description: "enable circuit breaker",
  1263  		Changes: []paramscutils.ParamChangeJSON{{
  1264  			Subspace: liquiditytypes.ModuleName,
  1265  			Key:      "CircuitBreakerEnabled",
  1266  			Value:    circuitBreakerEnabledStr,
  1267  		},
  1268  		},
  1269  		Deposit: sdk.NewCoin(s.cfg.BondDenom, govtypes.DefaultMinDepositTokens).String(),
  1270  	}
  1271  	paramChangeProp, err := json.Marshal(&paramChange)
  1272  	if err != nil {
  1273  		panic(err)
  1274  	}
  1275  
  1276  	//create a param change proposal with deposit
  1277  	_, err = liquiditytestutil.MsgParamChangeProposalExec(
  1278  		val.ClientCtx,
  1279  		val.Address.String(),
  1280  		testutil.WriteToNewTempFile(s.T(), string(paramChangeProp)).Name(),
  1281  	)
  1282  	err = s.network.WaitForNextBlock()
  1283  	s.Require().NoError(err)
  1284  
  1285  	_, err = liquiditytestutil.MsgVote(val.ClientCtx, val.Address.String(), "1", "yes")
  1286  	s.Require().NoError(err)
  1287  	err = s.network.WaitForNextBlock()
  1288  	s.Require().NoError(err)
  1289  
  1290  	// check if circuit breaker is enabled
  1291  	expectedOutput := `{"pool_types":[{"id":1,"name":"StandardLiquidityPool","min_reserve_coin_num":2,"max_reserve_coin_num":2,"description":"Standard liquidity pool with pool price function X/Y, ESPM constraint, and two kinds of reserve coins"}],"min_init_deposit_amount":"1000000","init_pool_coin_mint_amount":"1000000","max_reserve_coin_amount":"0","pool_creation_fee":[{"denom":"stake","amount":"40000000"}],"swap_fee_rate":"0.003000000000000000","withdraw_fee_rate":"0.000000000000000000","max_order_amount_ratio":"0.100000000000000000","unit_batch_height":1,"circuit_breaker_enabled":true}`
  1292  	out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdQueryParams(), []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)})
  1293  	s.Require().NoError(err)
  1294  	s.Require().Equal(expectedOutput, strings.TrimSpace(out.String()))
  1295  
  1296  	// fail swap coins because of circuit breaker
  1297  	output, err = liquiditytestutil.MsgSwapWithinBatchExec(
  1298  		val.ClientCtx,
  1299  		val.Address.String(),
  1300  		fmt.Sprintf("%d", uint32(1)),
  1301  		fmt.Sprintf("%d", liquiditytypes.DefaultSwapTypeID),
  1302  		offerCoin.String(),
  1303  		denomX,
  1304  		fmt.Sprintf("%.3f", 0.019),
  1305  		fmt.Sprintf("%.3f", 0.003),
  1306  	)
  1307  	s.Require().NoError(err)
  1308  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(output.Bytes(), &txRes))
  1309  	s.Require().Equal(txRes.Code, uint32(40))
  1310  	s.Require().Equal(txRes.RawLog, "failed to execute message; message index: 0: circuit breaker is triggered")
  1311  
  1312  	// fail create new pool because of circuit breaker
  1313  	output, err = liquiditytestutil.MsgCreatePoolExec(
  1314  		val.ClientCtx,
  1315  		val.Address.String(),
  1316  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
  1317  		sdk.NewCoins(X, Y).String(),
  1318  	)
  1319  	s.Require().NoError(err)
  1320  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(output.Bytes(), &txRes))
  1321  	s.Require().Equal(txRes.Code, uint32(40))
  1322  	s.Require().Equal(txRes.RawLog, "failed to execute message; message index: 0: circuit breaker is triggered")
  1323  
  1324  	// fail create new deposit because of circuit breaker
  1325  	_, err = liquiditytestutil.MsgDepositWithinBatchExec(
  1326  		val.ClientCtx,
  1327  		val.Address.String(),
  1328  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
  1329  		sdk.NewCoins(sdk.NewCoin(denomX, sdk.NewInt(10_000_000)), sdk.NewCoin(denomY, sdk.NewInt(10_000_000))).String(),
  1330  	)
  1331  	s.Require().NoError(err)
  1332  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(output.Bytes(), &txRes))
  1333  	s.Require().Equal(txRes.Code, uint32(40))
  1334  	s.Require().Equal(txRes.RawLog, "failed to execute message; message index: 0: circuit breaker is triggered")
  1335  
  1336  	// success withdraw pool coin from the pool even though circuit breaker is true
  1337  	poolCoinDenom := "poolC33A77E752C183913636A37FE1388ACA22FE7BED792BEB2E72EF2DA857703D8D"
  1338  	output, err = liquiditytestutil.MsgWithdrawWithinBatchExec(
  1339  		val.ClientCtx,
  1340  		val.Address.String(),
  1341  		fmt.Sprintf("%d", uint32(1)),
  1342  		sdk.NewCoins(sdk.NewCoin(poolCoinDenom, sdk.NewInt(500000))).String(),
  1343  	)
  1344  	s.Require().NoError(err)
  1345  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(output.Bytes(), &txRes))
  1346  	s.Require().Equal(txRes.Code, uint32(0))
  1347  
  1348  	output, err = liquiditytestutil.MsgWithdrawWithinBatchExec(
  1349  		val.ClientCtx,
  1350  		val.Address.String(),
  1351  		fmt.Sprintf("%d", uint32(1)),
  1352  		sdk.NewCoins(sdk.NewCoin(poolCoinDenom, sdk.NewInt(499999))).String(),
  1353  	)
  1354  	s.Require().NoError(err)
  1355  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(output.Bytes(), &txRes))
  1356  	s.Require().Equal(txRes.Code, uint32(0))
  1357  
  1358  	// withdraw last pool coin
  1359  	output, err = liquiditytestutil.MsgWithdrawWithinBatchExec(
  1360  		val.ClientCtx,
  1361  		val.Address.String(),
  1362  		fmt.Sprintf("%d", uint32(1)),
  1363  		sdk.NewCoins(sdk.NewCoin(poolCoinDenom, sdk.NewInt(1))).String(),
  1364  	)
  1365  	s.Require().NoError(err)
  1366  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(output.Bytes(), &txRes))
  1367  	s.Require().Equal(txRes.Code, uint32(0))
  1368  
  1369  	// fail withdraw because of the pool is depleted
  1370  	output, err = liquiditytestutil.MsgWithdrawWithinBatchExec(
  1371  		val.ClientCtx,
  1372  		val.Address.String(),
  1373  		fmt.Sprintf("%d", uint32(1)),
  1374  		sdk.NewCoins(sdk.NewCoin(poolCoinDenom, sdk.NewInt(1))).String(),
  1375  	)
  1376  	s.Require().NoError(err)
  1377  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(output.Bytes(), &txRes))
  1378  	s.Require().Equal(txRes.Code, uint32(39))
  1379  	s.Require().Equal(txRes.RawLog, "failed to execute message; message index: 0: the pool is depleted of reserve coin, reinitializing is required by deposit")
  1380  }
  1381  
  1382  func (s *IntegrationTestSuite) TestGetCmdQueryPoolBatchSwapMsgs() {
  1383  	val := s.network.Validators[0]
  1384  
  1385  	// use two different tokens that are minted to the test account
  1386  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
  1387  	X := sdk.NewCoin(denomX, sdk.NewInt(1_000_000_000))
  1388  	Y := sdk.NewCoin(denomY, sdk.NewInt(5_000_000_000))
  1389  
  1390  	// liquidity pool should be created prior to test this integration test
  1391  	_, err := liquiditytestutil.MsgCreatePoolExec(
  1392  		val.ClientCtx,
  1393  		val.Address.String(),
  1394  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
  1395  		sdk.NewCoins(X, Y).String(),
  1396  	)
  1397  	s.Require().NoError(err)
  1398  
  1399  	err = s.network.WaitForNextBlock()
  1400  	s.Require().NoError(err)
  1401  
  1402  	// swap coins from the pool
  1403  	offerCoin := sdk.NewCoin(denomY, sdk.NewInt(50_000_000))
  1404  	_, err = liquiditytestutil.MsgSwapWithinBatchExec(
  1405  		val.ClientCtx,
  1406  		val.Address.String(),
  1407  		fmt.Sprintf("%d", uint32(1)),
  1408  		fmt.Sprintf("%d", liquiditytypes.DefaultSwapTypeID),
  1409  		offerCoin.String(),
  1410  		denomX,
  1411  		fmt.Sprintf("%.3f", 0.019),
  1412  		fmt.Sprintf("%.3f", 0.003),
  1413  	)
  1414  	s.Require().NoError(err)
  1415  
  1416  	testCases := []struct {
  1417  		name      string
  1418  		args      []string
  1419  		expectErr bool
  1420  	}{
  1421  		{
  1422  			"with invalid pool id",
  1423  			[]string{
  1424  				"invalidpoolid",
  1425  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1426  			},
  1427  			true,
  1428  		},
  1429  		{
  1430  			"with not supported pool id",
  1431  			[]string{
  1432  				fmt.Sprintf("%d", uint32(2)),
  1433  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1434  			},
  1435  			true,
  1436  		},
  1437  		{
  1438  			"valid case",
  1439  			[]string{
  1440  				fmt.Sprintf("%d", uint32(1)),
  1441  				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
  1442  			},
  1443  			false,
  1444  		},
  1445  	}
  1446  
  1447  	for _, tc := range testCases {
  1448  		tc := tc
  1449  
  1450  		s.Run(tc.name, func() {
  1451  			cmd := cli.GetCmdQueryPoolBatchSwapMsgs()
  1452  			clientCtx := val.ClientCtx
  1453  
  1454  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1455  
  1456  			if tc.expectErr {
  1457  				s.Require().Error(err)
  1458  			} else {
  1459  				var resps liquiditytypes.QueryPoolBatchSwapMsgsResponse
  1460  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resps)
  1461  				s.Require().NoError(err)
  1462  
  1463  				for _, swap := range resps.GetSwaps() {
  1464  					s.Require().Equal(val.Address.String(), swap.Msg.SwapRequesterAddress)
  1465  					s.Require().Equal(true, swap.Executed)
  1466  					s.Require().Equal(true, swap.Succeeded)
  1467  					s.Require().Equal(true, swap.ToBeDeleted)
  1468  				}
  1469  			}
  1470  		})
  1471  	}
  1472  }
  1473  
  1474  func (s *IntegrationTestSuite) TestInitGenesis() {
  1475  	testCases := []struct {
  1476  		name      string
  1477  		flags     func(dir string) []string
  1478  		expectErr bool
  1479  		err       error
  1480  	}{
  1481  		{
  1482  			name: "default genesis state",
  1483  			flags: func(dir string) []string {
  1484  				return []string{
  1485  					"liquidity-test",
  1486  				}
  1487  			},
  1488  			expectErr: false,
  1489  			err:       nil,
  1490  		},
  1491  	}
  1492  	for _, tc := range testCases {
  1493  		tc := tc
  1494  		s.Run(tc.name, func() {
  1495  			testMbm := module.NewBasicManager(liquidity.AppModuleBasic{})
  1496  
  1497  			home := s.T().TempDir()
  1498  			logger := tmlog.NewNopLogger()
  1499  			cfg, err := genutiltest.CreateDefaultTendermintConfig(home)
  1500  			s.Require().NoError(err)
  1501  
  1502  			serverCtx := server.NewContext(viper.New(), cfg, logger)
  1503  			interfaceRegistry := types.NewInterfaceRegistry()
  1504  			marshaler := codec.NewProtoCodec(interfaceRegistry)
  1505  			clientCtx := client.Context{}.
  1506  				WithCodec(marshaler).
  1507  				WithHomeDir(home)
  1508  
  1509  			ctx := context.Background()
  1510  			ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
  1511  			ctx = context.WithValue(ctx, server.ServerContextKey, serverCtx)
  1512  
  1513  			cmd := genutilcli.InitCmd(testMbm, home)
  1514  			cmd.SetArgs(
  1515  				tc.flags(home),
  1516  			)
  1517  
  1518  			if tc.expectErr {
  1519  				err := cmd.ExecuteContext(ctx)
  1520  				s.Require().EqualError(err, tc.err.Error())
  1521  			} else {
  1522  				s.Require().NoError(cmd.ExecuteContext(ctx))
  1523  			}
  1524  		})
  1525  	}
  1526  }
  1527  
  1528  func (s *IntegrationTestSuite) TestExportGenesis() {
  1529  	clientCtx := s.network.Validators[0].ClientCtx
  1530  	serverCtx := s.network.Validators[0].Ctx
  1531  
  1532  	home := clientCtx.HomeDir
  1533  
  1534  	// verify genesis file saved in temp directory
  1535  	genDocFile := clientCtx.HomeDir + "/config/genesis.json"
  1536  	genDoc, err := tmtypes.GenesisDocFromFile(genDocFile)
  1537  	s.Require().NoError(err)
  1538  	s.Require().NotNil(genDoc)
  1539  
  1540  	val := s.network.Validators[0]
  1541  
  1542  	// use two different tokens that are minted to the test account
  1543  	denomX, denomY := liquiditytypes.AlphabeticalDenomPair("node0token", s.network.Config.BondDenom)
  1544  	X := sdk.NewCoin(denomX, sdk.NewInt(1_000_000_000))
  1545  	Y := sdk.NewCoin(denomY, sdk.NewInt(5_000_000_000))
  1546  
  1547  	// create liquidity pool
  1548  	_, err = liquiditytestutil.MsgCreatePoolExec(
  1549  		val.ClientCtx,
  1550  		val.Address.String(),
  1551  		fmt.Sprintf("%d", liquiditytypes.DefaultPoolTypeID),
  1552  		sdk.NewCoins(X, Y).String(),
  1553  	)
  1554  	s.Require().NoError(err)
  1555  
  1556  	err = s.network.WaitForNextBlock()
  1557  	s.Require().NoError(err)
  1558  
  1559  	cmd := server.ExportCmd(
  1560  		func(_ tmlog.Logger, _ tmdb.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailWhiteList []string,
  1561  			appOpts servertypes.AppOptions) (servertypes.ExportedApp, error) {
  1562  
  1563  			encCfg := lapp.MakeEncodingConfig()
  1564  			encCfg.Marshaler = codec.NewProtoCodec(encCfg.InterfaceRegistry)
  1565  
  1566  			// get logger and in-memory database
  1567  			logger := serverCtx.Logger
  1568  			db := s.db
  1569  
  1570  			var app *lapp.LiquidityApp
  1571  			if height != -1 {
  1572  				app = lapp.NewLiquidityApp(logger, db, traceStore, false, map[int64]bool{}, "", uint(1), encCfg, appOpts)
  1573  
  1574  				if err := app.LoadHeight(height); err != nil {
  1575  					return servertypes.ExportedApp{}, err
  1576  				}
  1577  			} else {
  1578  				app = lapp.NewLiquidityApp(logger, db, traceStore, true, map[int64]bool{}, "", uint(1), encCfg, appOpts)
  1579  			}
  1580  
  1581  			return app.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
  1582  		},
  1583  		home,
  1584  	)
  1585  
  1586  	args := []string{fmt.Sprintf("--%s=%s", flags.FlagHome, home)}
  1587  
  1588  	out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
  1589  	s.Require().NoError(err)
  1590  
  1591  	var exportedGenDoc tmtypes.GenesisDoc
  1592  	err = tmjson.Unmarshal(out.Bytes(), &exportedGenDoc)
  1593  	s.Require().NoError(err)
  1594  
  1595  	s.Require().Equal(clientCtx.ChainID, exportedGenDoc.ChainID)
  1596  }