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

     1  package testutil
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/gogo/protobuf/proto"
    10  	"github.com/stretchr/testify/suite"
    11  
    12  	ostcli "github.com/Finschia/ostracon/libs/cli"
    13  
    14  	"github.com/Finschia/finschia-sdk/client"
    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/testutil"
    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/x/feegrant"
    23  	"github.com/Finschia/finschia-sdk/x/feegrant/client/cli"
    24  	govtestutil "github.com/Finschia/finschia-sdk/x/gov/client/testutil"
    25  	govtypes "github.com/Finschia/finschia-sdk/x/gov/types"
    26  )
    27  
    28  const (
    29  	oneYear  = 365 * 24 * 60 * 60
    30  	tenHours = 10 * 60 * 60
    31  	oneHour  = 60 * 60
    32  )
    33  
    34  type IntegrationTestSuite struct {
    35  	suite.Suite
    36  
    37  	cfg          network.Config
    38  	network      *network.Network
    39  	addedGranter sdk.AccAddress
    40  	addedGrantee sdk.AccAddress
    41  	addedGrant   feegrant.Grant
    42  }
    43  
    44  func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
    45  	return &IntegrationTestSuite{cfg: cfg}
    46  }
    47  
    48  func (s *IntegrationTestSuite) SetupSuite() {
    49  	s.T().Log("setting up integration test suite")
    50  
    51  	if testing.Short() {
    52  		s.T().Skip("skipping test in unit-tests mode.")
    53  	}
    54  
    55  	s.network = network.New(s.T(), s.cfg)
    56  
    57  	_, err := s.network.WaitForHeight(1)
    58  	s.Require().NoError(err)
    59  
    60  	val := s.network.Validators[0]
    61  	granter := val.Address
    62  	grantee := s.network.Validators[1].Address
    63  
    64  	s.createGrant(granter, grantee)
    65  
    66  	grant, err := feegrant.NewGrant(granter, grantee, &feegrant.BasicAllowance{
    67  		SpendLimit: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(100))),
    68  	})
    69  	s.Require().NoError(err)
    70  
    71  	s.addedGrant = grant
    72  	s.addedGranter = granter
    73  	s.addedGrantee = grantee
    74  }
    75  
    76  // createGrant creates a new basic allowance fee grant from granter to grantee.
    77  func (s *IntegrationTestSuite) createGrant(granter, grantee sdk.Address) {
    78  	val := s.network.Validators[0]
    79  
    80  	clientCtx := val.ClientCtx
    81  	commonFlags := []string{
    82  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
    83  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
    84  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
    85  	}
    86  
    87  	fee := sdk.NewCoin("stake", sdk.NewInt(100))
    88  
    89  	args := append(
    90  		[]string{
    91  			granter.String(),
    92  			grantee.String(),
    93  			fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()),
    94  			fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
    95  			fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(oneYear)),
    96  		},
    97  		commonFlags...,
    98  	)
    99  
   100  	cmd := cli.NewCmdFeeGrant()
   101  
   102  	_, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
   103  	s.Require().NoError(err)
   104  	_, err = s.network.WaitForHeight(1)
   105  	s.Require().NoError(err)
   106  }
   107  
   108  func (s *IntegrationTestSuite) TearDownSuite() {
   109  	s.T().Log("tearing down integration test suite")
   110  	s.network.Cleanup()
   111  }
   112  
   113  func (s *IntegrationTestSuite) TestCmdGetFeeGrant() {
   114  	val := s.network.Validators[0]
   115  	granter := val.Address
   116  	grantee := s.addedGrantee
   117  	clientCtx := val.ClientCtx
   118  
   119  	testCases := []struct {
   120  		name         string
   121  		args         []string
   122  		expectErrMsg string
   123  		expectErr    bool
   124  		respType     *feegrant.Grant
   125  		resp         *feegrant.Grant
   126  	}{
   127  		{
   128  			"wrong granter",
   129  			[]string{
   130  				"wrong_granter",
   131  				grantee.String(),
   132  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   133  			},
   134  			"decoding bech32 failed",
   135  			true, nil, nil,
   136  		},
   137  		{
   138  			"wrong grantee",
   139  			[]string{
   140  				granter.String(),
   141  				"wrong_grantee",
   142  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   143  			},
   144  			"decoding bech32 failed",
   145  			true, nil, nil,
   146  		},
   147  		{
   148  			"non existed grant",
   149  			[]string{
   150  				"link19lrl5da53xtd2yssw2799y53uyaskadqkzv0ky",
   151  				grantee.String(),
   152  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   153  			},
   154  			"fee-grant not found",
   155  			true, nil, nil,
   156  		},
   157  		{
   158  			"valid req",
   159  			[]string{
   160  				granter.String(),
   161  				grantee.String(),
   162  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   163  			},
   164  			"",
   165  			false,
   166  			&feegrant.Grant{},
   167  			&s.addedGrant,
   168  		},
   169  	}
   170  
   171  	for _, tc := range testCases {
   172  		tc := tc
   173  
   174  		s.Run(tc.name, func() {
   175  			cmd := cli.GetCmdQueryFeeGrant()
   176  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   177  
   178  			if tc.expectErr {
   179  				s.Require().Error(err)
   180  				s.Require().Contains(err.Error(), tc.expectErrMsg)
   181  			} else {
   182  				s.Require().NoError(err)
   183  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   184  				s.Require().Equal(tc.respType.Grantee, tc.respType.Grantee)
   185  				s.Require().Equal(tc.respType.Granter, tc.respType.Granter)
   186  				grant, err := tc.respType.GetGrant()
   187  				s.Require().NoError(err)
   188  				grant1, err1 := tc.resp.GetGrant()
   189  				s.Require().NoError(err1)
   190  				s.Require().Equal(
   191  					grant.(*feegrant.BasicAllowance).SpendLimit,
   192  					grant1.(*feegrant.BasicAllowance).SpendLimit,
   193  				)
   194  			}
   195  		})
   196  	}
   197  }
   198  
   199  func (s *IntegrationTestSuite) TestCmdGetFeeGrantsByGrantee() {
   200  	val := s.network.Validators[0]
   201  	grantee := s.addedGrantee
   202  	clientCtx := val.ClientCtx
   203  
   204  	testCases := []struct {
   205  		name         string
   206  		args         []string
   207  		expectErr    bool
   208  		resp         *feegrant.QueryAllowancesResponse
   209  		expectLength int
   210  	}{
   211  		{
   212  			"wrong grantee",
   213  			[]string{
   214  				"wrong_grantee",
   215  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   216  			},
   217  			true, nil, 0,
   218  		},
   219  		{
   220  			"non existent grantee",
   221  			[]string{
   222  				"link19lrl5da53xtd2yssw2799y53uyaskadqkzv0ky",
   223  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   224  			},
   225  			false, &feegrant.QueryAllowancesResponse{}, 0,
   226  		},
   227  		{
   228  			"valid req",
   229  			[]string{
   230  				grantee.String(),
   231  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   232  			},
   233  			false, &feegrant.QueryAllowancesResponse{}, 1,
   234  		},
   235  	}
   236  
   237  	for _, tc := range testCases {
   238  		tc := tc
   239  
   240  		s.Run(tc.name, func() {
   241  			cmd := cli.GetCmdQueryFeeGrantsByGrantee()
   242  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   243  
   244  			if tc.expectErr {
   245  				s.Require().Error(err)
   246  			} else {
   247  				s.Require().NoError(err)
   248  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.resp), out.String())
   249  				s.Require().Len(tc.resp.Allowances, tc.expectLength)
   250  			}
   251  		})
   252  	}
   253  }
   254  
   255  func (s *IntegrationTestSuite) TestCmdGetFeeGrantsByGranter() {
   256  	val := s.network.Validators[0]
   257  	granter := s.addedGranter
   258  	clientCtx := val.ClientCtx
   259  
   260  	testCases := []struct {
   261  		name         string
   262  		args         []string
   263  		expectErr    bool
   264  		resp         *feegrant.QueryAllowancesByGranterResponse
   265  		expectLength int
   266  	}{
   267  		{
   268  			"wrong grantee",
   269  			[]string{
   270  				"wrong_grantee",
   271  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   272  			},
   273  			true, nil, 0,
   274  		},
   275  		{
   276  			"non existent grantee",
   277  			[]string{
   278  				"link1nph3cfzk6trsmfxkeu943nvach5qw4vw99nwdh",
   279  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   280  			},
   281  			false, &feegrant.QueryAllowancesByGranterResponse{}, 0,
   282  		},
   283  		{
   284  			"valid req",
   285  			[]string{
   286  				granter.String(),
   287  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   288  			},
   289  			false, &feegrant.QueryAllowancesByGranterResponse{}, 1,
   290  		},
   291  	}
   292  
   293  	for _, tc := range testCases {
   294  		tc := tc
   295  
   296  		s.Run(tc.name, func() {
   297  			cmd := cli.GetCmdQueryFeeGrantsByGranter()
   298  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   299  
   300  			if tc.expectErr {
   301  				s.Require().Error(err)
   302  			} else {
   303  				s.Require().NoError(err)
   304  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.resp), out.String())
   305  				s.Require().Len(tc.resp.Allowances, tc.expectLength)
   306  			}
   307  		})
   308  	}
   309  }
   310  
   311  func (s *IntegrationTestSuite) TestNewCmdFeeGrant() {
   312  	val := s.network.Validators[0]
   313  	granter := val.Address
   314  	alreadyExistedGrantee := s.addedGrantee
   315  	clientCtx := val.ClientCtx
   316  
   317  	fromAddr, fromName, _, err := client.GetFromFields(clientCtx.Keyring, granter.String(), clientCtx.GenerateOnly)
   318  	s.Require().Equal(fromAddr, granter)
   319  	s.Require().NoError(err)
   320  
   321  	commonFlags := []string{
   322  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   323  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   324  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   325  	}
   326  
   327  	testCases := []struct {
   328  		name         string
   329  		args         []string
   330  		expectErr    bool
   331  		expectedCode uint32
   332  		respType     proto.Message
   333  	}{
   334  		{
   335  			"wrong granter address",
   336  			append(
   337  				[]string{
   338  					"wrong_granter",
   339  					"link19lrl5da53xtd2yssw2799y53uyaskadqkzv0ky",
   340  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   341  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   342  				},
   343  				commonFlags...,
   344  			),
   345  			true, 0, nil,
   346  		},
   347  		{
   348  			"wrong grantee address",
   349  			append(
   350  				[]string{
   351  					granter.String(),
   352  					"wrong_grantee",
   353  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   354  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   355  				},
   356  				commonFlags...,
   357  			),
   358  			true, 0, nil,
   359  		},
   360  		{
   361  			"wrong granter key name",
   362  			append(
   363  				[]string{
   364  					"invalid_granter",
   365  					"link1rsx5wakg9kxfa05ueqjpkher9yddy3u4n47f9z",
   366  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   367  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   368  				},
   369  				commonFlags...,
   370  			),
   371  			true, 0, nil,
   372  		},
   373  		{
   374  			"valid basic fee grant",
   375  			append(
   376  				[]string{
   377  					granter.String(),
   378  					"link19lrl5da53xtd2yssw2799y53uyaskadqkzv0ky",
   379  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   380  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   381  				},
   382  				commonFlags...,
   383  			),
   384  			false, 0, &sdk.TxResponse{},
   385  		},
   386  		{
   387  			"valid basic fee grant with granter key name",
   388  			append(
   389  				[]string{
   390  					fromName,
   391  					"link1rsx5wakg9kxfa05ueqjpkher9yddy3u4n47f9z",
   392  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   393  					fmt.Sprintf("--%s=%s", flags.FlagFrom, fromName),
   394  				},
   395  				commonFlags...,
   396  			),
   397  			false, 0, &sdk.TxResponse{},
   398  		},
   399  		{
   400  			"valid basic fee grant with amino",
   401  			append(
   402  				[]string{
   403  					granter.String(),
   404  					"link1yhxv9jv8kwtud80azf674l5yddv2pecfzgxmrw",
   405  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   406  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   407  					fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
   408  				},
   409  				commonFlags...,
   410  			),
   411  			false, 0, &sdk.TxResponse{},
   412  		},
   413  		{
   414  			"valid basic fee grant without spend limit",
   415  			append(
   416  				[]string{
   417  					granter.String(),
   418  					"link1kgj5mx00euxeqjhu5uh0l4lwnt99aadvrzxl6t",
   419  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   420  				},
   421  				commonFlags...,
   422  			),
   423  			false, 0, &sdk.TxResponse{},
   424  		},
   425  		{
   426  			"valid basic fee grant without expiration",
   427  			append(
   428  				[]string{
   429  					granter.String(),
   430  					"link1y4hn2txq7eghuydjrmwvc6sqrr7z9aa3m3zjv2",
   431  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   432  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   433  				},
   434  				commonFlags...,
   435  			),
   436  			false, 0, &sdk.TxResponse{},
   437  		},
   438  		{
   439  			"valid basic fee grant without spend-limit and expiration",
   440  			append(
   441  				[]string{
   442  					granter.String(),
   443  					"link1mp668xdzzdulrc40wwasqqflmagxfyc29zgvav",
   444  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   445  				},
   446  				commonFlags...,
   447  			),
   448  			false, 0, &sdk.TxResponse{},
   449  		},
   450  		{
   451  			"try to add existed grant",
   452  			append(
   453  				[]string{
   454  					granter.String(),
   455  					alreadyExistedGrantee.String(),
   456  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   457  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   458  				},
   459  				commonFlags...,
   460  			),
   461  			false, 18, &sdk.TxResponse{},
   462  		},
   463  		{
   464  			"invalid number of args(periodic fee grant)",
   465  			append(
   466  				[]string{
   467  					granter.String(),
   468  					"link19lrl5da53xtd2yssw2799y53uyaskadqkzv0ky",
   469  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   470  					fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
   471  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   472  					fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(tenHours)),
   473  				},
   474  				commonFlags...,
   475  			),
   476  			true, 0, nil,
   477  		},
   478  		{
   479  			"period mentioned and period limit omitted, invalid periodic grant",
   480  			append(
   481  				[]string{
   482  					granter.String(),
   483  					"link19lrl5da53xtd2yssw2799y53uyaskadqkzv0ky",
   484  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   485  					fmt.Sprintf("--%s=%d", cli.FlagPeriod, tenHours),
   486  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   487  					fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(oneHour)),
   488  				},
   489  				commonFlags...,
   490  			),
   491  			true, 0, nil,
   492  		},
   493  		{
   494  			"period cannot be greater than the actual expiration(periodic fee grant)",
   495  			append(
   496  				[]string{
   497  					granter.String(),
   498  					"link19lrl5da53xtd2yssw2799y53uyaskadqkzv0ky",
   499  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   500  					fmt.Sprintf("--%s=%d", cli.FlagPeriod, tenHours),
   501  					fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
   502  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   503  					fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(oneHour)),
   504  				},
   505  				commonFlags...,
   506  			),
   507  			true, 0, nil,
   508  		},
   509  		{
   510  			"valid periodic fee grant",
   511  			append(
   512  				[]string{
   513  					granter.String(),
   514  					"link1xr0fqfdcen5ayqtch9n5j6rxfvjuul37mev25v",
   515  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   516  					fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
   517  					fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
   518  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   519  					fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(tenHours)),
   520  				},
   521  				commonFlags...,
   522  			),
   523  			false, 0, &sdk.TxResponse{},
   524  		},
   525  		{
   526  			"valid periodic fee grant without spend-limit",
   527  			append(
   528  				[]string{
   529  					granter.String(),
   530  					"link1xjqjff3zde5le2t0u26gutnq3kag76l4jsjaqq",
   531  					fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
   532  					fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
   533  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   534  					fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(tenHours)),
   535  				},
   536  				commonFlags...,
   537  			),
   538  			false, 0, &sdk.TxResponse{},
   539  		},
   540  		{
   541  			"valid periodic fee grant without expiration",
   542  			append(
   543  				[]string{
   544  					granter.String(),
   545  					"link1j583lutp3vz6z43j62wgcjxzfuch0ucmxgepac",
   546  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   547  					fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
   548  					fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
   549  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   550  				},
   551  				commonFlags...,
   552  			),
   553  			false, 0, &sdk.TxResponse{},
   554  		},
   555  		{
   556  			"valid periodic fee grant without spend-limit and expiration",
   557  			append(
   558  				[]string{
   559  					granter.String(),
   560  					"link1dzthj3umpcnapfydrkt2lcv5nxgjk9kkndrfz5",
   561  					fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
   562  					fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
   563  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   564  				},
   565  				commonFlags...,
   566  			),
   567  			false, 0, &sdk.TxResponse{},
   568  		},
   569  		{
   570  			"invalid expiration",
   571  			append(
   572  				[]string{
   573  					granter.String(),
   574  					"link1xjqjff3zde5le2t0u26gutnq3kag76l4jsjaqq",
   575  					fmt.Sprintf("--%s=%d", cli.FlagPeriod, oneHour),
   576  					fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"),
   577  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   578  					fmt.Sprintf("--%s=%s", cli.FlagExpiration, "invalid"),
   579  				},
   580  				commonFlags...,
   581  			),
   582  			true, 0, nil,
   583  		},
   584  	}
   585  
   586  	for _, tc := range testCases {
   587  		tc := tc
   588  
   589  		s.Run(tc.name, func() {
   590  			cmd := cli.NewCmdFeeGrant()
   591  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   592  
   593  			if tc.expectErr {
   594  				s.Require().Error(err)
   595  			} else {
   596  				s.Require().NoError(err)
   597  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   598  
   599  				txResp := tc.respType.(*sdk.TxResponse)
   600  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   601  			}
   602  		})
   603  	}
   604  }
   605  
   606  func (s *IntegrationTestSuite) TestNewCmdRevokeFeegrant() {
   607  	val := s.network.Validators[0]
   608  	granter := s.addedGranter
   609  	grantee := s.addedGrantee
   610  	clientCtx := val.ClientCtx
   611  
   612  	commonFlags := []string{
   613  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   614  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   615  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   616  	}
   617  
   618  	// Create new fee grant specifically to test amino.
   619  	aminoGrantee, err := sdk.AccAddressFromBech32("link1zp4lzwuwzvhq7xhe8xj688vv00dxv2zyue4xuj")
   620  	s.Require().NoError(err)
   621  	s.createGrant(granter, aminoGrantee)
   622  
   623  	testCases := []struct {
   624  		name         string
   625  		args         []string
   626  		expectErr    bool
   627  		expectedCode uint32
   628  		respType     proto.Message
   629  	}{
   630  		{
   631  			"invalid grantee",
   632  			append(
   633  				[]string{
   634  					"wrong_granter",
   635  					grantee.String(),
   636  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   637  				},
   638  				commonFlags...,
   639  			),
   640  			true, 0, nil,
   641  		},
   642  		{
   643  			"invalid grantee",
   644  			append(
   645  				[]string{
   646  					granter.String(),
   647  					"wrong_grantee",
   648  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   649  				},
   650  				commonFlags...,
   651  			),
   652  			true, 0, nil,
   653  		},
   654  		{
   655  			"Non existed grant",
   656  			append(
   657  				[]string{
   658  					granter.String(),
   659  					"link1qwvn8n0cs9lq4q46qjummvfkqah3paxx37etxm",
   660  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   661  				},
   662  				commonFlags...,
   663  			),
   664  			false, 4, &sdk.TxResponse{},
   665  		},
   666  		{
   667  			"Valid revoke",
   668  			append(
   669  				[]string{
   670  					granter.String(),
   671  					grantee.String(),
   672  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   673  				},
   674  				commonFlags...,
   675  			),
   676  			false, 0, &sdk.TxResponse{},
   677  		},
   678  		{
   679  			"Valid revoke with amino",
   680  			append(
   681  				[]string{
   682  					granter.String(),
   683  					aminoGrantee.String(),
   684  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   685  					fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
   686  				},
   687  				commonFlags...,
   688  			),
   689  			false, 0, &sdk.TxResponse{},
   690  		},
   691  	}
   692  
   693  	for _, tc := range testCases {
   694  		tc := tc
   695  
   696  		s.Run(tc.name, func() {
   697  			cmd := cli.NewCmdRevokeFeegrant()
   698  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   699  
   700  			if tc.expectErr {
   701  				s.Require().Error(err)
   702  			} else {
   703  				s.Require().NoError(err)
   704  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   705  
   706  				txResp := tc.respType.(*sdk.TxResponse)
   707  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   708  			}
   709  		})
   710  	}
   711  }
   712  
   713  func (s *IntegrationTestSuite) TestTxWithFeeGrant() {
   714  	val := s.network.Validators[0]
   715  	clientCtx := val.ClientCtx
   716  	granter := val.Address
   717  
   718  	// creating an account manually (This account won't be exist in state)
   719  	info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
   720  	s.Require().NoError(err)
   721  	grantee := sdk.AccAddress(info.GetPubKey().Address())
   722  
   723  	commonFlags := []string{
   724  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   725  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   726  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   727  	}
   728  
   729  	fee := sdk.NewCoin("stake", sdk.NewInt(100))
   730  
   731  	args := append(
   732  		[]string{
   733  			granter.String(),
   734  			grantee.String(),
   735  			fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()),
   736  			fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   737  			fmt.Sprintf("--%s=%s", cli.FlagExpiration, getFormattedExpiration(oneYear)),
   738  		},
   739  		commonFlags...,
   740  	)
   741  
   742  	cmd := cli.NewCmdFeeGrant()
   743  
   744  	_, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
   745  	s.Require().NoError(err)
   746  	_, err = s.network.WaitForHeight(1)
   747  	s.Require().NoError(err)
   748  
   749  	// granted fee allowance for an account which is not in state and creating
   750  	// any tx with it by using --fee-account shouldn't fail
   751  	out, err := govtestutil.MsgSubmitProposal(val.ClientCtx, grantee.String(),
   752  		"Text Proposal", "No desc", govtypes.ProposalTypeText,
   753  		fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter.String()),
   754  	)
   755  
   756  	s.Require().NoError(err)
   757  	var resp sdk.TxResponse
   758  	s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
   759  	s.Require().Equal(uint32(0), resp.Code)
   760  }
   761  
   762  func (s *IntegrationTestSuite) TestFilteredFeeAllowance() {
   763  	val := s.network.Validators[0]
   764  
   765  	granter := val.Address
   766  	info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
   767  	s.Require().NoError(err)
   768  	grantee := sdk.AccAddress(info.GetPubKey().Address())
   769  
   770  	clientCtx := val.ClientCtx
   771  
   772  	commonFlags := []string{
   773  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   774  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   775  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   776  	}
   777  	spendLimit := sdk.NewCoin("stake", sdk.NewInt(1000))
   778  
   779  	allowMsgs := strings.Join([]string{sdk.MsgTypeURL(&govtypes.MsgSubmitProposal{}), sdk.MsgTypeURL(&govtypes.MsgVoteWeighted{})}, ",")
   780  
   781  	testCases := []struct {
   782  		name         string
   783  		args         []string
   784  		expectErr    bool
   785  		respType     proto.Message
   786  		expectedCode uint32
   787  	}{
   788  		{
   789  			"invalid granter address",
   790  			append(
   791  				[]string{
   792  					"not an address",
   793  					"link19lrl5da53xtd2yssw2799y53uyaskadqkzv0ky",
   794  					fmt.Sprintf("--%s=%s", cli.FlagAllowedMsgs, allowMsgs),
   795  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, spendLimit.String()),
   796  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   797  				},
   798  				commonFlags...,
   799  			),
   800  			true, &sdk.TxResponse{}, 0,
   801  		},
   802  		{
   803  			"invalid grantee address",
   804  			append(
   805  				[]string{
   806  					granter.String(),
   807  					"not an address",
   808  					fmt.Sprintf("--%s=%s", cli.FlagAllowedMsgs, allowMsgs),
   809  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, spendLimit.String()),
   810  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   811  				},
   812  				commonFlags...,
   813  			),
   814  			true, &sdk.TxResponse{}, 0,
   815  		},
   816  		{
   817  			"valid filter fee grant",
   818  			append(
   819  				[]string{
   820  					granter.String(),
   821  					grantee.String(),
   822  					fmt.Sprintf("--%s=%s", cli.FlagAllowedMsgs, allowMsgs),
   823  					fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, spendLimit.String()),
   824  					fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
   825  				},
   826  				commonFlags...,
   827  			),
   828  			false, &sdk.TxResponse{}, 0,
   829  		},
   830  	}
   831  
   832  	for _, tc := range testCases {
   833  		tc := tc
   834  
   835  		s.Run(tc.name, func() {
   836  			cmd := cli.NewCmdFeeGrant()
   837  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   838  
   839  			if tc.expectErr {
   840  				s.Require().Error(err)
   841  			} else {
   842  				s.Require().NoError(err)
   843  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   844  
   845  				txResp := tc.respType.(*sdk.TxResponse)
   846  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   847  			}
   848  		})
   849  	}
   850  
   851  	args := []string{
   852  		granter.String(),
   853  		grantee.String(),
   854  		fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   855  	}
   856  
   857  	// get filtered fee allowance and check info
   858  	cmd := cli.GetCmdQueryFeeGrant()
   859  	out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
   860  	s.Require().NoError(err)
   861  
   862  	resp := &feegrant.Grant{}
   863  
   864  	s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), resp), out.String())
   865  	s.Require().Equal(resp.Grantee, resp.Grantee)
   866  	s.Require().Equal(resp.Granter, resp.Granter)
   867  
   868  	grant, err := resp.GetGrant()
   869  	s.Require().NoError(err)
   870  
   871  	filteredFeeGrant, err := grant.(*feegrant.AllowedMsgAllowance).GetAllowance()
   872  	s.Require().NoError(err)
   873  
   874  	s.Require().Equal(
   875  		filteredFeeGrant.(*feegrant.BasicAllowance).SpendLimit.String(),
   876  		spendLimit.String(),
   877  	)
   878  
   879  	// exec filtered fee allowance
   880  	cases := []struct {
   881  		name         string
   882  		malleate     func() (testutil.BufferWriter, error)
   883  		respType     proto.Message
   884  		expectedCode uint32
   885  	}{
   886  		{
   887  			"valid proposal tx",
   888  			func() (testutil.BufferWriter, error) {
   889  				return govtestutil.MsgSubmitProposal(val.ClientCtx, grantee.String(),
   890  					"Text Proposal", "No desc", govtypes.ProposalTypeText,
   891  					fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter.String()),
   892  				)
   893  			},
   894  			&sdk.TxResponse{},
   895  			0,
   896  		},
   897  		{
   898  			"valid weighted_vote tx",
   899  			func() (testutil.BufferWriter, error) {
   900  				return govtestutil.MsgVote(val.ClientCtx, grantee.String(), "0", "yes",
   901  					fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter.String()),
   902  				)
   903  			},
   904  			&sdk.TxResponse{},
   905  			2,
   906  		},
   907  		{
   908  			"should fail with unauthorized msgs",
   909  			func() (testutil.BufferWriter, error) {
   910  				args := append(
   911  					[]string{
   912  						grantee.String(),
   913  						"link1j583lutp3vz6z43j62wgcjxzfuch0ucmxgepac",
   914  						fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
   915  						fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter),
   916  					},
   917  					commonFlags...,
   918  				)
   919  				cmd := cli.NewCmdFeeGrant()
   920  				return clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
   921  			},
   922  			&sdk.TxResponse{},
   923  			7,
   924  		},
   925  	}
   926  
   927  	for _, tc := range cases {
   928  		tc := tc
   929  
   930  		s.Run(tc.name, func() {
   931  			out, err := tc.malleate()
   932  			s.Require().NoError(err)
   933  			s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   934  			txResp := tc.respType.(*sdk.TxResponse)
   935  			s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   936  		})
   937  	}
   938  }
   939  
   940  func getFormattedExpiration(duration int64) string {
   941  	return time.Now().Add(time.Duration(duration) * time.Second).Format(time.RFC3339)
   942  }