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

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