github.com/Finschia/finschia-sdk@v0.49.1/x/staking/client/testutil/suite.go (about)

     1  package testutil
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	ostcli "github.com/Finschia/ostracon/libs/cli"
    10  	"github.com/Finschia/ostracon/rpc/client/http"
    11  	"github.com/gogo/protobuf/proto"
    12  	"github.com/stretchr/testify/suite"
    13  	"github.com/tendermint/tendermint/proto/tendermint/crypto"
    14  
    15  	"github.com/Finschia/finschia-sdk/client/flags"
    16  	"github.com/Finschia/finschia-sdk/crypto/hd"
    17  	"github.com/Finschia/finschia-sdk/crypto/keyring"
    18  	"github.com/Finschia/finschia-sdk/crypto/keys/ed25519"
    19  	clitestutil "github.com/Finschia/finschia-sdk/testutil/cli"
    20  	"github.com/Finschia/finschia-sdk/testutil/network"
    21  	sdk "github.com/Finschia/finschia-sdk/types"
    22  	"github.com/Finschia/finschia-sdk/types/query"
    23  	banktestutil "github.com/Finschia/finschia-sdk/x/bank/client/testutil"
    24  	"github.com/Finschia/finschia-sdk/x/staking/client/cli"
    25  	"github.com/Finschia/finschia-sdk/x/staking/types"
    26  )
    27  
    28  type IntegrationTestSuite struct {
    29  	suite.Suite
    30  
    31  	cfg     network.Config
    32  	network *network.Network
    33  }
    34  
    35  func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
    36  	return &IntegrationTestSuite{cfg: cfg}
    37  }
    38  
    39  func (s *IntegrationTestSuite) SetupSuite() {
    40  	s.T().Log("setting up integration test suite")
    41  
    42  	if testing.Short() {
    43  		s.T().Skip("skipping test in unit-tests mode.")
    44  	}
    45  
    46  	s.network = network.New(s.T(), s.cfg)
    47  
    48  	_, err := s.network.WaitForHeight(1)
    49  	s.Require().NoError(err)
    50  
    51  	unbond, err := sdk.ParseCoinNormalized("10stake")
    52  	s.Require().NoError(err)
    53  
    54  	val := s.network.Validators[0]
    55  	val2 := s.network.Validators[1]
    56  
    57  	// redelegate
    58  	_, err = MsgRedelegateExec(
    59  		val.ClientCtx,
    60  		val.Address,
    61  		val.ValAddress,
    62  		val2.ValAddress,
    63  		unbond,
    64  		fmt.Sprintf("--%s=%d", flags.FlagGas, 300000),
    65  	)
    66  	s.Require().NoError(err)
    67  	_, err = s.network.WaitForHeight(1)
    68  	s.Require().NoError(err)
    69  	// unbonding
    70  	_, err = MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbond)
    71  	s.Require().NoError(err)
    72  	_, err = s.network.WaitForHeight(1)
    73  	s.Require().NoError(err)
    74  }
    75  
    76  func (s *IntegrationTestSuite) TearDownSuite() {
    77  	s.T().Log("tearing down integration test suite")
    78  	s.network.Cleanup()
    79  }
    80  
    81  func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() {
    82  	require := s.Require()
    83  	val := s.network.Validators[0]
    84  
    85  	consPrivKey := ed25519.GenPrivKey()
    86  	consPubKeyBz, err := s.cfg.Codec.MarshalInterfaceJSON(consPrivKey.PubKey())
    87  	require.NoError(err)
    88  	require.NotNil(consPubKeyBz)
    89  
    90  	info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewValidator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
    91  	require.NoError(err)
    92  
    93  	newAddr := sdk.AccAddress(info.GetPubKey().Address())
    94  	_, err = banktestutil.MsgSendExec(
    95  		val.ClientCtx,
    96  		val.Address,
    97  		newAddr,
    98  		sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
    99  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   100  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   101  	)
   102  	require.NoError(err)
   103  
   104  	testCases := []struct {
   105  		name         string
   106  		args         []string
   107  		expectErr    bool
   108  		expectedCode uint32
   109  		respType     proto.Message
   110  	}{
   111  		{
   112  			"invalid transaction (missing amount)",
   113  			[]string{
   114  				fmt.Sprintf("--%s=AFAF00C4", cli.FlagIdentity),
   115  				fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
   116  				fmt.Sprintf("--%s=contact@newvalidator.io", cli.FlagSecurityContact),
   117  				fmt.Sprintf("--%s='Hey, I am a new validator. Please delegate!'", cli.FlagDetails),
   118  				fmt.Sprintf("--%s=0.5", cli.FlagCommissionRate),
   119  				fmt.Sprintf("--%s=1.0", cli.FlagCommissionMaxRate),
   120  				fmt.Sprintf("--%s=0.1", cli.FlagCommissionMaxChangeRate),
   121  				fmt.Sprintf("--%s=1", cli.FlagMinSelfDelegation),
   122  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr),
   123  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   124  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   125  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   126  			},
   127  			true, 0, nil,
   128  		},
   129  		{
   130  			"invalid transaction (missing pubkey)",
   131  			[]string{
   132  				fmt.Sprintf("--%s=%dstake", cli.FlagAmount, 100),
   133  				fmt.Sprintf("--%s=AFAF00C4", cli.FlagIdentity),
   134  				fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
   135  				fmt.Sprintf("--%s=contact@newvalidator.io", cli.FlagSecurityContact),
   136  				fmt.Sprintf("--%s='Hey, I am a new validator. Please delegate!'", cli.FlagDetails),
   137  				fmt.Sprintf("--%s=0.5", cli.FlagCommissionRate),
   138  				fmt.Sprintf("--%s=1.0", cli.FlagCommissionMaxRate),
   139  				fmt.Sprintf("--%s=0.1", cli.FlagCommissionMaxChangeRate),
   140  				fmt.Sprintf("--%s=1", cli.FlagMinSelfDelegation),
   141  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr),
   142  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   143  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   144  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   145  			},
   146  			true, 0, nil,
   147  		},
   148  		{
   149  			"invalid transaction (missing moniker)",
   150  			[]string{
   151  				fmt.Sprintf("--%s=%s", cli.FlagPubKey, consPubKeyBz),
   152  				fmt.Sprintf("--%s=%dstake", cli.FlagAmount, 100),
   153  				fmt.Sprintf("--%s=AFAF00C4", cli.FlagIdentity),
   154  				fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
   155  				fmt.Sprintf("--%s=contact@newvalidator.io", cli.FlagSecurityContact),
   156  				fmt.Sprintf("--%s='Hey, I am a new validator. Please delegate!'", cli.FlagDetails),
   157  				fmt.Sprintf("--%s=0.5", cli.FlagCommissionRate),
   158  				fmt.Sprintf("--%s=1.0", cli.FlagCommissionMaxRate),
   159  				fmt.Sprintf("--%s=0.1", cli.FlagCommissionMaxChangeRate),
   160  				fmt.Sprintf("--%s=1", cli.FlagMinSelfDelegation),
   161  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr),
   162  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   163  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   164  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   165  			},
   166  			true, 0, nil,
   167  		},
   168  		{
   169  			"valid transaction",
   170  			[]string{
   171  				fmt.Sprintf("--%s=%s", cli.FlagPubKey, consPubKeyBz),
   172  				fmt.Sprintf("--%s=%dstake", cli.FlagAmount, 100),
   173  				fmt.Sprintf("--%s=NewValidator", cli.FlagMoniker),
   174  				fmt.Sprintf("--%s=AFAF00C4", cli.FlagIdentity),
   175  				fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
   176  				fmt.Sprintf("--%s=contact@newvalidator.io", cli.FlagSecurityContact),
   177  				fmt.Sprintf("--%s='Hey, I am a new validator. Please delegate!'", cli.FlagDetails),
   178  				fmt.Sprintf("--%s=0.5", cli.FlagCommissionRate),
   179  				fmt.Sprintf("--%s=1.0", cli.FlagCommissionMaxRate),
   180  				fmt.Sprintf("--%s=0.1", cli.FlagCommissionMaxChangeRate),
   181  				fmt.Sprintf("--%s=1", cli.FlagMinSelfDelegation),
   182  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr),
   183  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   184  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   185  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   186  			},
   187  			false, 0, &sdk.TxResponse{},
   188  		},
   189  	}
   190  
   191  	for _, tc := range testCases {
   192  		s.Run(tc.name, func() {
   193  			cmd := cli.NewCreateValidatorCmd()
   194  			clientCtx := val.ClientCtx
   195  
   196  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   197  			if tc.expectErr {
   198  				require.Error(err)
   199  			} else {
   200  				require.NoError(err, "test: %s\noutput: %s", tc.name, out.String())
   201  				err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType)
   202  				require.NoError(err, out.String(), "test: %s, output\n:", tc.name, out.String())
   203  
   204  				txResp := tc.respType.(*sdk.TxResponse)
   205  				require.Equal(tc.expectedCode, txResp.Code,
   206  					"test: %s, output\n:", tc.name, out.String())
   207  
   208  				events := txResp.Logs[0].GetEvents()
   209  				for i := 0; i < len(events); i++ {
   210  					if events[i].GetType() == "create_validator" {
   211  						attributes := events[i].GetAttributes()
   212  						require.Equal(attributes[1].Value, "100stake")
   213  						break
   214  					}
   215  				}
   216  			}
   217  		})
   218  	}
   219  }
   220  
   221  func (s *IntegrationTestSuite) TestGetCmdQueryValidator() {
   222  	val := s.network.Validators[0]
   223  	testCases := []struct {
   224  		name      string
   225  		args      []string
   226  		expectErr bool
   227  	}{
   228  		{
   229  			"with invalid address ",
   230  			[]string{"somethinginvalidaddress", fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   231  			true,
   232  		},
   233  		{
   234  			"with valid and not existing address",
   235  			[]string{"linkvaloper1mqn4snc20sxt6lrecjclmdglfdmtql4408kwvl", fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   236  			true,
   237  		},
   238  		{
   239  			"happy case",
   240  			[]string{val.ValAddress.String(), fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   241  			false,
   242  		},
   243  	}
   244  	for _, tc := range testCases {
   245  		s.Run(tc.name, func() {
   246  			cmd := cli.GetCmdQueryValidator()
   247  			clientCtx := val.ClientCtx
   248  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   249  			if tc.expectErr {
   250  				s.Require().Error(err)
   251  				s.Require().NotEqual("internal", err.Error())
   252  			} else {
   253  				var result types.Validator
   254  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result))
   255  				s.Require().Equal(val.ValAddress.String(), result.OperatorAddress)
   256  			}
   257  		})
   258  	}
   259  }
   260  
   261  func (s *IntegrationTestSuite) TestGetCmdQueryValidators() {
   262  	val := s.network.Validators[0]
   263  
   264  	testCases := []struct {
   265  		name              string
   266  		args              []string
   267  		minValidatorCount int
   268  	}{
   269  		{
   270  			"one validator case",
   271  			[]string{
   272  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   273  				fmt.Sprintf("--%s=1", flags.FlagLimit),
   274  			},
   275  			1,
   276  		},
   277  		{
   278  			"multi validator case",
   279  			[]string{fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   280  			len(s.network.Validators),
   281  		},
   282  	}
   283  
   284  	for _, tc := range testCases {
   285  		s.Run(tc.name, func() {
   286  			cmd := cli.GetCmdQueryValidators()
   287  			clientCtx := val.ClientCtx
   288  
   289  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   290  			s.Require().NoError(err)
   291  
   292  			var result types.QueryValidatorsResponse
   293  			s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result))
   294  			s.Require().Equal(tc.minValidatorCount, len(result.Validators))
   295  		})
   296  	}
   297  }
   298  
   299  func (s *IntegrationTestSuite) TestGetCmdQueryDelegation() {
   300  	val := s.network.Validators[0]
   301  	val2 := s.network.Validators[1]
   302  
   303  	testCases := []struct {
   304  		name     string
   305  		args     []string
   306  		expErr   bool
   307  		respType proto.Message
   308  		expected proto.Message
   309  	}{
   310  		{
   311  			"with wrong delegator address",
   312  			[]string{
   313  				"wrongDelAddr",
   314  				val2.ValAddress.String(),
   315  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   316  			},
   317  			true, nil, nil,
   318  		},
   319  		{
   320  			"with wrong validator address",
   321  			[]string{
   322  				val.Address.String(),
   323  				"wrongValAddr",
   324  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   325  			},
   326  			true, nil, nil,
   327  		},
   328  		{
   329  			"with json output",
   330  			[]string{
   331  				val.Address.String(),
   332  				val2.ValAddress.String(),
   333  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   334  			},
   335  			false,
   336  			&types.DelegationResponse{},
   337  			&types.DelegationResponse{
   338  				Delegation: types.Delegation{
   339  					DelegatorAddress: val.Address.String(),
   340  					ValidatorAddress: val2.ValAddress.String(),
   341  					Shares:           sdk.NewDec(10),
   342  				},
   343  				Balance: sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)),
   344  			},
   345  		},
   346  	}
   347  
   348  	for _, tc := range testCases {
   349  		s.Run(tc.name, func() {
   350  			cmd := cli.GetCmdQueryDelegation()
   351  			clientCtx := val.ClientCtx
   352  
   353  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   354  			if tc.expErr {
   355  				s.Require().Error(err)
   356  			} else {
   357  				s.Require().NoError(err)
   358  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   359  				s.Require().Equal(tc.expected.String(), tc.respType.String())
   360  			}
   361  		})
   362  	}
   363  }
   364  
   365  func (s *IntegrationTestSuite) TestGetCmdQueryDelegations() {
   366  	val := s.network.Validators[0]
   367  
   368  	testCases := []struct {
   369  		name     string
   370  		args     []string
   371  		expErr   bool
   372  		respType proto.Message
   373  		expected proto.Message
   374  	}{
   375  		{
   376  			"with no delegator address",
   377  			[]string{},
   378  			true, nil, nil,
   379  		},
   380  		{
   381  			"with wrong delegator address",
   382  			[]string{"wrongDelAddr"},
   383  			true, nil, nil,
   384  		},
   385  		{
   386  			"valid request (height specific)",
   387  			[]string{
   388  				val.Address.String(),
   389  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   390  				fmt.Sprintf("--%s=1", flags.FlagHeight),
   391  			},
   392  			false,
   393  			&types.QueryDelegatorDelegationsResponse{},
   394  			&types.QueryDelegatorDelegationsResponse{
   395  				DelegationResponses: types.DelegationResponses{
   396  					types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
   397  				},
   398  				Pagination: &query.PageResponse{},
   399  			},
   400  		},
   401  	}
   402  
   403  	for _, tc := range testCases {
   404  		s.Run(tc.name, func() {
   405  			cmd := cli.GetCmdQueryDelegations()
   406  			clientCtx := val.ClientCtx
   407  
   408  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   409  			if tc.expErr {
   410  				s.Require().Error(err)
   411  			} else {
   412  				s.Require().NoError(err)
   413  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   414  				s.Require().Equal(tc.expected.String(), tc.respType.String())
   415  			}
   416  		})
   417  	}
   418  }
   419  
   420  func (s *IntegrationTestSuite) TestGetCmdQueryValidatorDelegations() {
   421  	val := s.network.Validators[0]
   422  
   423  	testCases := []struct {
   424  		name     string
   425  		args     []string
   426  		expErr   bool
   427  		respType proto.Message
   428  		expected proto.Message
   429  	}{
   430  		{
   431  			"with no validator address",
   432  			[]string{},
   433  			true, nil, nil,
   434  		},
   435  		{
   436  			"wrong validator address",
   437  			[]string{"wrongValAddr"},
   438  			true, nil, nil,
   439  		},
   440  		{
   441  			"valid request(height specific)",
   442  			[]string{
   443  				val.Address.String(),
   444  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   445  				fmt.Sprintf("--%s=1", flags.FlagHeight),
   446  			},
   447  			false,
   448  			&types.QueryValidatorDelegationsResponse{},
   449  			&types.QueryValidatorDelegationsResponse{
   450  				DelegationResponses: types.DelegationResponses{
   451  					types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
   452  				},
   453  				Pagination: &query.PageResponse{},
   454  			},
   455  		},
   456  	}
   457  
   458  	for _, tc := range testCases {
   459  		s.Run(tc.name, func() {
   460  			cmd := cli.GetCmdQueryDelegations()
   461  			clientCtx := val.ClientCtx
   462  
   463  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   464  			if tc.expErr {
   465  				s.Require().Error(err)
   466  			} else {
   467  				s.Require().NoError(err)
   468  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   469  				s.Require().Equal(tc.expected.String(), tc.respType.String())
   470  			}
   471  		})
   472  	}
   473  }
   474  
   475  func (s *IntegrationTestSuite) TestGetCmdQueryUnbondingDelegations() {
   476  	val := s.network.Validators[0]
   477  
   478  	testCases := []struct {
   479  		name   string
   480  		args   []string
   481  		expErr bool
   482  	}{
   483  		{
   484  			"wrong delegator address",
   485  			[]string{
   486  				"wrongDelAddr",
   487  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   488  			},
   489  			true,
   490  		},
   491  		{
   492  			"valid request",
   493  			[]string{
   494  				val.Address.String(),
   495  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   496  			},
   497  			false,
   498  		},
   499  	}
   500  
   501  	for _, tc := range testCases {
   502  		s.Run(tc.name, func() {
   503  			cmd := cli.GetCmdQueryUnbondingDelegations()
   504  			clientCtx := val.ClientCtx
   505  
   506  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   507  
   508  			if tc.expErr {
   509  				s.Require().Error(err)
   510  			} else {
   511  				var ubds types.QueryDelegatorUnbondingDelegationsResponse
   512  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &ubds)
   513  
   514  				s.Require().NoError(err)
   515  				s.Require().Len(ubds.UnbondingResponses, 1)
   516  				s.Require().Equal(ubds.UnbondingResponses[0].DelegatorAddress, val.Address.String())
   517  			}
   518  		})
   519  	}
   520  }
   521  
   522  func (s *IntegrationTestSuite) TestGetCmdQueryUnbondingDelegation() {
   523  	val := s.network.Validators[0]
   524  
   525  	testCases := []struct {
   526  		name   string
   527  		args   []string
   528  		expErr bool
   529  	}{
   530  		{
   531  			"wrong delegator address",
   532  			[]string{
   533  				"wrongDelAddr",
   534  				val.ValAddress.String(),
   535  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   536  			},
   537  			true,
   538  		},
   539  		{
   540  			"wrong validator address",
   541  			[]string{
   542  				val.Address.String(),
   543  				"wrongValAddr",
   544  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   545  			},
   546  			true,
   547  		},
   548  		{
   549  			"valid request",
   550  			[]string{
   551  				val.Address.String(),
   552  				val.ValAddress.String(),
   553  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   554  			},
   555  			false,
   556  		},
   557  	}
   558  
   559  	for _, tc := range testCases {
   560  		s.Run(tc.name, func() {
   561  			cmd := cli.GetCmdQueryUnbondingDelegation()
   562  			clientCtx := val.ClientCtx
   563  
   564  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   565  
   566  			if tc.expErr {
   567  				s.Require().Error(err)
   568  			} else {
   569  				var ubd types.UnbondingDelegation
   570  
   571  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &ubd)
   572  				s.Require().NoError(err)
   573  				s.Require().Equal(ubd.DelegatorAddress, val.Address.String())
   574  				s.Require().Equal(ubd.ValidatorAddress, val.ValAddress.String())
   575  				s.Require().Len(ubd.Entries, 1)
   576  			}
   577  		})
   578  	}
   579  }
   580  
   581  func (s *IntegrationTestSuite) TestGetCmdQueryValidatorUnbondingDelegations() {
   582  	val := s.network.Validators[0]
   583  
   584  	testCases := []struct {
   585  		name   string
   586  		args   []string
   587  		expErr bool
   588  	}{
   589  		{
   590  			"wrong validator address",
   591  			[]string{
   592  				"wrongValAddr",
   593  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   594  			},
   595  			true,
   596  		},
   597  		{
   598  			"valid request",
   599  			[]string{
   600  				val.ValAddress.String(),
   601  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   602  			},
   603  			false,
   604  		},
   605  	}
   606  
   607  	for _, tc := range testCases {
   608  		s.Run(tc.name, func() {
   609  			cmd := cli.GetCmdQueryValidatorUnbondingDelegations()
   610  			clientCtx := val.ClientCtx
   611  
   612  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   613  
   614  			if tc.expErr {
   615  				s.Require().Error(err)
   616  			} else {
   617  				var ubds types.QueryValidatorUnbondingDelegationsResponse
   618  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &ubds)
   619  
   620  				s.Require().NoError(err)
   621  				s.Require().Len(ubds.UnbondingResponses, 1)
   622  				s.Require().Equal(ubds.UnbondingResponses[0].DelegatorAddress, val.Address.String())
   623  			}
   624  		})
   625  	}
   626  }
   627  
   628  func (s *IntegrationTestSuite) TestGetCmdQueryRedelegations() {
   629  	val := s.network.Validators[0]
   630  	val2 := s.network.Validators[1]
   631  
   632  	testCases := []struct {
   633  		name   string
   634  		args   []string
   635  		expErr bool
   636  	}{
   637  		{
   638  			"wrong delegator address",
   639  			[]string{
   640  				"wrongdeladdr",
   641  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   642  			},
   643  			true,
   644  		},
   645  		{
   646  			"valid request",
   647  			[]string{
   648  				val.Address.String(),
   649  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   650  			},
   651  			false,
   652  		},
   653  	}
   654  
   655  	for _, tc := range testCases {
   656  		s.Run(tc.name, func() {
   657  			cmd := cli.GetCmdQueryRedelegations()
   658  			clientCtx := val.ClientCtx
   659  
   660  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   661  
   662  			if tc.expErr {
   663  				s.Require().Error(err)
   664  			} else {
   665  				var redelegations types.QueryRedelegationsResponse
   666  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &redelegations)
   667  
   668  				s.Require().NoError(err)
   669  
   670  				s.Require().Len(redelegations.RedelegationResponses, 1)
   671  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.DelegatorAddress, val.Address.String())
   672  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorSrcAddress, val.ValAddress.String())
   673  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorDstAddress, val2.ValAddress.String())
   674  			}
   675  		})
   676  	}
   677  }
   678  
   679  func (s *IntegrationTestSuite) TestGetCmdQueryRedelegation() {
   680  	val := s.network.Validators[0]
   681  	val2 := s.network.Validators[1]
   682  
   683  	testCases := []struct {
   684  		name   string
   685  		args   []string
   686  		expErr bool
   687  	}{
   688  		{
   689  			"wrong delegator address",
   690  			[]string{
   691  				"wrongdeladdr",
   692  				val.ValAddress.String(),
   693  				val2.ValAddress.String(),
   694  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   695  			},
   696  			true,
   697  		},
   698  		{
   699  			"wrong source validator address address",
   700  			[]string{
   701  				val.Address.String(),
   702  				"wrongSrcValAddress",
   703  				val2.ValAddress.String(),
   704  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   705  			},
   706  			true,
   707  		},
   708  		{
   709  			"wrong destination validator address address",
   710  			[]string{
   711  				val.Address.String(),
   712  				val.ValAddress.String(),
   713  				"wrongDestValAddress",
   714  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   715  			},
   716  			true,
   717  		},
   718  		{
   719  			"valid request",
   720  			[]string{
   721  				val.Address.String(),
   722  				val.ValAddress.String(),
   723  				val2.ValAddress.String(),
   724  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   725  			},
   726  			false,
   727  		},
   728  	}
   729  
   730  	for _, tc := range testCases {
   731  		s.Run(tc.name, func() {
   732  			cmd := cli.GetCmdQueryRedelegation()
   733  			clientCtx := val.ClientCtx
   734  
   735  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   736  
   737  			if tc.expErr {
   738  				s.Require().Error(err)
   739  			} else {
   740  				var redelegations types.QueryRedelegationsResponse
   741  
   742  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &redelegations)
   743  				s.Require().NoError(err)
   744  
   745  				s.Require().Len(redelegations.RedelegationResponses, 1)
   746  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.DelegatorAddress, val.Address.String())
   747  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorSrcAddress, val.ValAddress.String())
   748  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorDstAddress, val2.ValAddress.String())
   749  			}
   750  		})
   751  	}
   752  }
   753  
   754  func (s *IntegrationTestSuite) TestGetCmdQueryValidatorRedelegations() {
   755  	val := s.network.Validators[0]
   756  	val2 := s.network.Validators[1]
   757  
   758  	testCases := []struct {
   759  		name   string
   760  		args   []string
   761  		expErr bool
   762  	}{
   763  		{
   764  			"wrong validator address",
   765  			[]string{
   766  				"wrongValAddr",
   767  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   768  			},
   769  			true,
   770  		},
   771  		{
   772  			"valid request",
   773  			[]string{
   774  				val.ValAddress.String(),
   775  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   776  			},
   777  			false,
   778  		},
   779  	}
   780  
   781  	for _, tc := range testCases {
   782  		s.Run(tc.name, func() {
   783  			cmd := cli.GetCmdQueryValidatorRedelegations()
   784  			clientCtx := val.ClientCtx
   785  
   786  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   787  
   788  			if tc.expErr {
   789  				s.Require().Error(err)
   790  			} else {
   791  				var redelegations types.QueryRedelegationsResponse
   792  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &redelegations)
   793  
   794  				s.Require().NoError(err)
   795  
   796  				s.Require().Len(redelegations.RedelegationResponses, 1)
   797  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.DelegatorAddress, val.Address.String())
   798  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorSrcAddress, val.ValAddress.String())
   799  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorDstAddress, val2.ValAddress.String())
   800  			}
   801  		})
   802  	}
   803  }
   804  
   805  func (s *IntegrationTestSuite) TestGetCmdQueryHistoricalInfo() {
   806  	val := s.network.Validators[0]
   807  
   808  	testCases := []struct {
   809  		name  string
   810  		args  []string
   811  		error bool
   812  	}{
   813  		{
   814  			"wrong height",
   815  			[]string{
   816  				"-1",
   817  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   818  			},
   819  			true,
   820  		},
   821  		{
   822  			"valid request",
   823  			[]string{
   824  				"1",
   825  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   826  			},
   827  			false,
   828  		},
   829  	}
   830  
   831  	for _, tc := range testCases {
   832  		s.Run(tc.name, func() {
   833  			cmd := cli.GetCmdQueryHistoricalInfo()
   834  			clientCtx := val.ClientCtx
   835  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   836  
   837  			if tc.error {
   838  				s.Require().Error(err)
   839  			} else {
   840  				var historicalInfo types.HistoricalInfo
   841  
   842  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &historicalInfo)
   843  				s.Require().NoError(err)
   844  				s.Require().NotNil(historicalInfo)
   845  			}
   846  		})
   847  	}
   848  }
   849  
   850  func (s *IntegrationTestSuite) TestGetCmdQueryParams() {
   851  	val := s.network.Validators[0]
   852  	testCases := []struct {
   853  		name           string
   854  		args           []string
   855  		expectedOutput string
   856  	}{
   857  		{
   858  			"with text output",
   859  			[]string{fmt.Sprintf("--%s=text", ostcli.OutputFlag)},
   860  			`bond_denom: stake
   861  historical_entries: 10000
   862  max_entries: 7
   863  max_validators: 100
   864  unbonding_time: 1814400s`,
   865  		},
   866  		{
   867  			"with json output",
   868  			[]string{fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   869  			`{"unbonding_time":"1814400s","max_validators":100,"max_entries":7,"historical_entries":10000,"bond_denom":"stake"}`,
   870  		},
   871  	}
   872  	for _, tc := range testCases {
   873  		s.Run(tc.name, func() {
   874  			cmd := cli.GetCmdQueryParams()
   875  			clientCtx := val.ClientCtx
   876  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   877  			s.Require().NoError(err)
   878  			s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String()))
   879  		})
   880  	}
   881  }
   882  
   883  func (s *IntegrationTestSuite) TestGetCmdQueryPool() {
   884  	val := s.network.Validators[0]
   885  	testCases := []struct {
   886  		name           string
   887  		args           []string
   888  		expectedOutput string
   889  	}{
   890  		{
   891  			"with text",
   892  			[]string{
   893  				fmt.Sprintf("--%s=text", ostcli.OutputFlag),
   894  				fmt.Sprintf("--%s=1", flags.FlagHeight),
   895  			},
   896  			fmt.Sprintf(`bonded_tokens: "%s"
   897  not_bonded_tokens: "0"`, cli.DefaultTokens.Mul(sdk.NewInt(2)).String()),
   898  		},
   899  		{
   900  			"with json",
   901  			[]string{
   902  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   903  				fmt.Sprintf("--%s=1", flags.FlagHeight),
   904  			},
   905  			fmt.Sprintf(`{"not_bonded_tokens":"0","bonded_tokens":"%s"}`, cli.DefaultTokens.Mul(sdk.NewInt(2)).String()),
   906  		},
   907  	}
   908  	for _, tc := range testCases {
   909  		s.Run(tc.name, func() {
   910  			cmd := cli.GetCmdQueryPool()
   911  			clientCtx := val.ClientCtx
   912  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   913  			s.Require().NoError(err)
   914  			s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String()))
   915  		})
   916  	}
   917  }
   918  
   919  func (s *IntegrationTestSuite) TestNewEditValidatorCmd() {
   920  	val := s.network.Validators[0]
   921  
   922  	details := "bio"
   923  	identity := "test identity"
   924  	securityContact := "test contact"
   925  	website := "https://test.com"
   926  
   927  	testCases := []struct {
   928  		name         string
   929  		args         []string
   930  		expectErr    bool
   931  		expectedCode uint32
   932  		respType     proto.Message
   933  	}{
   934  		{
   935  			"with no edit flag (since all are optional)",
   936  			[]string{
   937  				fmt.Sprintf("--%s=%s", flags.FlagFrom, "with wrong from address"),
   938  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   939  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   940  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   941  			},
   942  			true, 0, nil,
   943  		},
   944  		{
   945  			"with no edit flag (since all are optional)",
   946  			[]string{
   947  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   948  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   949  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   950  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   951  			},
   952  			false, 0, &sdk.TxResponse{},
   953  		},
   954  		{
   955  			"edit validator details",
   956  			[]string{
   957  				fmt.Sprintf("--details=%s", details),
   958  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   959  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   960  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   961  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   962  			},
   963  			false, 0, &sdk.TxResponse{},
   964  		},
   965  		{
   966  			"edit validator identity",
   967  			[]string{
   968  				fmt.Sprintf("--identity=%s", identity),
   969  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   970  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   971  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   972  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   973  			},
   974  			false, 0, &sdk.TxResponse{},
   975  		},
   976  		{
   977  			"edit validator security-contact",
   978  			[]string{
   979  				fmt.Sprintf("--security-contact=%s", securityContact),
   980  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   981  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   982  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   983  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   984  			},
   985  			false, 0, &sdk.TxResponse{},
   986  		},
   987  		{
   988  			"edit validator website",
   989  			[]string{
   990  				fmt.Sprintf("--website=%s", website),
   991  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   992  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   993  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   994  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   995  			},
   996  			false, 0, &sdk.TxResponse{},
   997  		},
   998  		{
   999  			"with all edit flags",
  1000  			[]string{
  1001  				fmt.Sprintf("--details=%s", details),
  1002  				fmt.Sprintf("--identity=%s", identity),
  1003  				fmt.Sprintf("--security-contact=%s", securityContact),
  1004  				fmt.Sprintf("--website=%s", website),
  1005  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1006  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1007  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1008  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1009  			},
  1010  			false, 0, &sdk.TxResponse{},
  1011  		},
  1012  	}
  1013  
  1014  	for _, tc := range testCases {
  1015  		s.Run(tc.name, func() {
  1016  			cmd := cli.NewEditValidatorCmd()
  1017  			clientCtx := val.ClientCtx
  1018  
  1019  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1020  			if tc.expectErr {
  1021  				s.Require().Error(err)
  1022  			} else {
  1023  				s.Require().NoError(err, out.String())
  1024  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
  1025  
  1026  				txResp := tc.respType.(*sdk.TxResponse)
  1027  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
  1028  			}
  1029  		})
  1030  	}
  1031  }
  1032  
  1033  func (s *IntegrationTestSuite) TestNewDelegateCmd() {
  1034  	val := s.network.Validators[0]
  1035  
  1036  	info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
  1037  	s.Require().NoError(err)
  1038  
  1039  	newAddr := sdk.AccAddress(info.GetPubKey().Address())
  1040  
  1041  	_, err = banktestutil.MsgSendExec(
  1042  		val.ClientCtx,
  1043  		val.Address,
  1044  		newAddr,
  1045  		sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1046  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1047  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1048  	)
  1049  	s.Require().NoError(err)
  1050  
  1051  	testCases := []struct {
  1052  		name         string
  1053  		args         []string
  1054  		expectErr    bool
  1055  		expectedCode uint32
  1056  		respType     proto.Message
  1057  	}{
  1058  		{
  1059  			"without delegate amount",
  1060  			[]string{
  1061  				val.ValAddress.String(),
  1062  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
  1063  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1064  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1065  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1066  			},
  1067  			true, 0, nil,
  1068  		},
  1069  		{
  1070  			"without validator address",
  1071  			[]string{
  1072  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1073  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
  1074  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1075  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1076  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1077  			},
  1078  			true, 0, nil,
  1079  		},
  1080  		{
  1081  			"valid transaction of delegate",
  1082  			[]string{
  1083  				val.ValAddress.String(),
  1084  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1085  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
  1086  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1087  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1088  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1089  			},
  1090  			false, 0, &sdk.TxResponse{},
  1091  		},
  1092  	}
  1093  
  1094  	for _, tc := range testCases {
  1095  		s.Run(tc.name, func() {
  1096  			cmd := cli.NewDelegateCmd()
  1097  			clientCtx := val.ClientCtx
  1098  
  1099  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1100  			if tc.expectErr {
  1101  				s.Require().Error(err)
  1102  			} else {
  1103  				s.Require().NoError(err, out.String())
  1104  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
  1105  
  1106  				txResp := tc.respType.(*sdk.TxResponse)
  1107  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
  1108  			}
  1109  		})
  1110  	}
  1111  }
  1112  
  1113  func (s *IntegrationTestSuite) TestNewRedelegateCmd() {
  1114  	val := s.network.Validators[0]
  1115  	val2 := s.network.Validators[1]
  1116  
  1117  	testCases := []struct {
  1118  		name         string
  1119  		args         []string
  1120  		expectErr    bool
  1121  		expectedCode uint32
  1122  		respType     proto.Message
  1123  	}{
  1124  		{
  1125  			"without amount",
  1126  			[]string{
  1127  				val.ValAddress.String(),  // src-validator-addr
  1128  				val2.ValAddress.String(), // dst-validator-addr
  1129  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1130  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1131  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1132  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1133  			},
  1134  			true, 0, nil,
  1135  		},
  1136  		{
  1137  			"with wrong source validator address",
  1138  			[]string{
  1139  				`linkvaloper120yvjfy7m2gnu9mvusrs40cxxhpt8nr3jr36d2`,   // src-validator-addr
  1140  				val2.ValAddress.String(),                               // dst-validator-addr
  1141  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(), // amount
  1142  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1143  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1144  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1145  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1146  			},
  1147  			false, 3, &sdk.TxResponse{},
  1148  		},
  1149  		{
  1150  			"with wrong destination validator address",
  1151  			[]string{
  1152  				val.ValAddress.String(),                                // dst-validator-addr
  1153  				`linkvaloper120yvjfy7m2gnu9mvusrs40cxxhpt8nr3jr36d2`,   // src-validator-addr
  1154  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(), // amount
  1155  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1156  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1157  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1158  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1159  			},
  1160  			false, 31, &sdk.TxResponse{},
  1161  		},
  1162  		{
  1163  			"valid transaction of delegate",
  1164  			[]string{
  1165  				val.ValAddress.String(),                                // src-validator-addr
  1166  				val2.ValAddress.String(),                               // dst-validator-addr
  1167  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(), // amount
  1168  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1169  				fmt.Sprintf("--%s=%s", flags.FlagGas, "auto"),
  1170  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1171  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1172  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1173  			},
  1174  			false, 0, &sdk.TxResponse{},
  1175  		},
  1176  	}
  1177  
  1178  	for _, tc := range testCases {
  1179  		s.Run(tc.name, func() {
  1180  			cmd := cli.NewRedelegateCmd()
  1181  			clientCtx := val.ClientCtx
  1182  
  1183  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1184  			if tc.expectErr {
  1185  				s.Require().Error(err)
  1186  			} else {
  1187  				s.Require().NoError(err, out.String())
  1188  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
  1189  
  1190  				txResp := tc.respType.(*sdk.TxResponse)
  1191  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
  1192  			}
  1193  		})
  1194  	}
  1195  }
  1196  
  1197  func (s *IntegrationTestSuite) TestNewUnbondCmd() {
  1198  	val := s.network.Validators[0]
  1199  
  1200  	testCases := []struct {
  1201  		name         string
  1202  		args         []string
  1203  		expectErr    bool
  1204  		expectedCode uint32
  1205  		respType     proto.Message
  1206  	}{
  1207  		{
  1208  			"Without unbond amount",
  1209  			[]string{
  1210  				val.ValAddress.String(),
  1211  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1212  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1213  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1214  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1215  			},
  1216  			true, 0, nil,
  1217  		},
  1218  		{
  1219  			"Without validator address",
  1220  			[]string{
  1221  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1222  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1223  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1224  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1225  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1226  			},
  1227  			true, 0, nil,
  1228  		},
  1229  		{
  1230  			"valid transaction of unbond",
  1231  			[]string{
  1232  				val.ValAddress.String(),
  1233  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1234  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1235  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1236  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1237  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1238  			},
  1239  			false, 0, &sdk.TxResponse{},
  1240  		},
  1241  	}
  1242  
  1243  	for _, tc := range testCases {
  1244  		s.Run(tc.name, func() {
  1245  			cmd := cli.NewUnbondCmd()
  1246  			clientCtx := val.ClientCtx
  1247  
  1248  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1249  			if tc.expectErr {
  1250  				s.Require().Error(err)
  1251  			} else {
  1252  				s.Require().NoError(err, out.String())
  1253  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
  1254  
  1255  				txResp := tc.respType.(*sdk.TxResponse)
  1256  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
  1257  			}
  1258  		})
  1259  	}
  1260  }
  1261  
  1262  // TestBlockResults tests that the validator updates correctly show when
  1263  // calling the /block_results RPC endpoint.
  1264  // ref: https://github.com/cosmos/cosmos-sdk/issues/7401.
  1265  func (s *IntegrationTestSuite) TestBlockResults() {
  1266  	require := s.Require()
  1267  	val := s.network.Validators[0]
  1268  
  1269  	// Create new account in the keyring.
  1270  	info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewDelegator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
  1271  	require.NoError(err)
  1272  	newAddr := sdk.AccAddress(info.GetPubKey().Address())
  1273  
  1274  	// Send some funds to the new account.
  1275  	_, err = banktestutil.MsgSendExec(
  1276  		val.ClientCtx,
  1277  		val.Address,
  1278  		newAddr,
  1279  		sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1280  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1281  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1282  	)
  1283  	require.NoError(err)
  1284  
  1285  	// Use CLI to create a delegation from the new account to validator `val`.
  1286  	delHeight, err := s.network.LatestHeight()
  1287  	require.NoError(err)
  1288  	cmd := cli.NewDelegateCmd()
  1289  	_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, []string{
  1290  		val.ValAddress.String(),
  1291  		sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1292  		fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
  1293  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1294  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1295  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1296  	})
  1297  	require.NoError(err)
  1298  
  1299  	// Create a HTTP rpc client.
  1300  	rpcClient, err := http.New(val.RPCAddress, "/websocket")
  1301  	require.NoError(err)
  1302  
  1303  	// Loop until we find a block result with the correct validator updates.
  1304  	// By experience, it happens around 2 blocks after `delHeight`.
  1305  	for {
  1306  		latestHeight, err := s.network.LatestHeight()
  1307  		require.NoError(err)
  1308  
  1309  		// Wait maximum 10 blocks, or else fail test.
  1310  		if latestHeight > delHeight+10 {
  1311  			s.Fail("timeout reached")
  1312  		}
  1313  
  1314  		res, err := rpcClient.BlockResults(context.Background(), &latestHeight)
  1315  		require.NoError(err)
  1316  
  1317  		if len(res.ValidatorUpdates) > 0 {
  1318  			valUpdate := res.ValidatorUpdates[0]
  1319  			require.Equal(
  1320  				valUpdate.GetPubKey().Sum.(*crypto.PublicKey_Ed25519).Ed25519,
  1321  				val.PubKey.Bytes(),
  1322  			)
  1323  
  1324  			// We got our validator update, test passed.
  1325  			break
  1326  		}
  1327  
  1328  		err = s.network.WaitForNextBlock()
  1329  		require.NoError(err)
  1330  	}
  1331  }
  1332  
  1333  // https://github.com/cosmos/cosmos-sdk/issues/10660
  1334  func (s *IntegrationTestSuite) TestEditValidatorMoniker() {
  1335  	val := s.network.Validators[0]
  1336  	require := s.Require()
  1337  
  1338  	txCmd := cli.NewEditValidatorCmd()
  1339  	moniker := "testing"
  1340  	_, err := clitestutil.ExecTestCLICmd(val.ClientCtx, txCmd, []string{
  1341  		val.ValAddress.String(),
  1342  		fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1343  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1344  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1345  		fmt.Sprintf("--%s=%s", cli.FlagEditMoniker, moniker),
  1346  		fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
  1347  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1348  	})
  1349  	require.NoError(err)
  1350  
  1351  	queryCmd := cli.GetCmdQueryValidator()
  1352  	res, err := clitestutil.ExecTestCLICmd(
  1353  		val.ClientCtx, queryCmd,
  1354  		[]string{val.ValAddress.String(), fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
  1355  	)
  1356  	require.NoError(err)
  1357  	var result types.Validator
  1358  	require.NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &result))
  1359  	require.Equal(result.GetMoniker(), moniker)
  1360  
  1361  	_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, txCmd, []string{
  1362  		val.ValAddress.String(),
  1363  		fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1364  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1365  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1366  		fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
  1367  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1368  	})
  1369  	require.NoError(err)
  1370  
  1371  	res, err = clitestutil.ExecTestCLICmd(
  1372  		val.ClientCtx, queryCmd,
  1373  		[]string{val.ValAddress.String(), fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
  1374  	)
  1375  	require.NoError(err)
  1376  
  1377  	require.NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &result))
  1378  	require.Equal(result.GetMoniker(), moniker)
  1379  }