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 }