diff --git a/CHANGELOG.md b/CHANGELOG.md index 268b51aec..3749ef3c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -124,6 +124,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#9594](https://github.com/cosmos/cosmos-sdk/pull/9594) Remove legacy REST API. Please see the [REST Endpoints Migration guide](https://docs.cosmos.network/master/migrations/rest.html) to migrate to the new REST endpoints. * [\#9995](https://github.com/cosmos/cosmos-sdk/pull/9995) Increased gas cost for creating proposals. +* [\#11013](https://github.com/cosmos/cosmos-sdk/pull/) The `tx gov submit-proposal` command has changed syntax to support the new Msg-based gov proposals. To access the old CLI command, please use `tx gov submit-legacy-proposal`. ### CLI Breaking Changes diff --git a/x/auth/client/testutil/suite.go b/x/auth/client/testutil/suite.go index 9120e21a5..4c9d7da5d 100644 --- a/x/auth/client/testutil/suite.go +++ b/x/auth/client/testutil/suite.go @@ -1503,7 +1503,7 @@ func (s *IntegrationTestSuite) TestAuxSigner() { for _, tc := range testCases { tc := tc s.Run(tc.name, func() { - _, err := govtestutil.MsgSubmitProposal( + _, err := govtestutil.MsgSubmitLegacyProposal( val.ClientCtx, val.Address.String(), "test", @@ -1747,7 +1747,7 @@ func (s *IntegrationTestSuite) TestAuxToFee() { for _, tc := range testCases { tc := tc s.Run(tc.name, func() { - res, err := govtestutil.MsgSubmitProposal( + res, err := govtestutil.MsgSubmitLegacyProposal( val.ClientCtx, tipper.String(), "test", diff --git a/x/authz/client/testutil/tx.go b/x/authz/client/testutil/tx.go index e883aa6fe..e9c0f3881 100644 --- a/x/authz/client/testutil/tx.go +++ b/x/authz/client/testutil/tx.go @@ -54,7 +54,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) // create a proposal with deposit - _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), + _, err = govtestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(), "Text Proposal 1", "Where is the title!?", govv1beta1.ProposalTypeText, fmt.Sprintf("--%s=%s", govcli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, govv1beta2.DefaultMinDepositTokens).String())) s.Require().NoError(err) diff --git a/x/feegrant/client/testutil/suite.go b/x/feegrant/client/testutil/suite.go index df6defaa1..38d01577b 100644 --- a/x/feegrant/client/testutil/suite.go +++ b/x/feegrant/client/testutil/suite.go @@ -752,7 +752,7 @@ func (s *IntegrationTestSuite) TestTxWithFeeGrant() { // granted fee allowance for an account which is not in state and creating // any tx with it by using --fee-account shouldn't fail - out, err := govtestutil.MsgSubmitProposal(val.ClientCtx, grantee.String(), + out, err := govtestutil.MsgSubmitLegacyProposal(val.ClientCtx, grantee.String(), "Text Proposal", "No desc", govv1beta1.ProposalTypeText, fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granter.String()), ) @@ -892,7 +892,7 @@ func (s *IntegrationTestSuite) TestFilteredFeeAllowance() { { "valid proposal tx", func() (testutil.BufferWriter, error) { - return govtestutil.MsgSubmitProposal(val.ClientCtx, grantee.String(), + return govtestutil.MsgSubmitLegacyProposal(val.ClientCtx, grantee.String(), "Text Proposal", "No desc", govv1beta1.ProposalTypeText, fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granter.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(100))).String()), diff --git a/x/gov/client/cli/parse.go b/x/gov/client/cli/parse.go index eeb814eb9..306b4b10d 100644 --- a/x/gov/client/cli/parse.go +++ b/x/gov/client/cli/parse.go @@ -7,11 +7,20 @@ import ( "github.com/spf13/pflag" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" govutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils" ) -func parseSubmitProposalFlags(fs *pflag.FlagSet) (*proposal, error) { - proposal := &proposal{} +type legacyProposal struct { + Title string + Description string + Type string + Deposit string +} + +func parseSubmitLegacyProposalFlags(fs *pflag.FlagSet) (*legacyProposal, error) { + proposal := &legacyProposal{} proposalFile, _ := fs.GetString(FlagProposal) if proposalFile == "" { @@ -42,3 +51,43 @@ func parseSubmitProposalFlags(fs *pflag.FlagSet) (*proposal, error) { return proposal, nil } + +// proposal defines the new Msg-based proposal. +type proposal struct { + // Msgs defines an array of sdk.Msgs proto-JSON-encoded as Anys. + Messages []json.RawMessage + Metadata []byte + Deposit string +} + +func parseSubmitProposal(cdc codec.Codec, path string) ([]sdk.Msg, []byte, sdk.Coins, error) { + var proposal proposal + + contents, err := os.ReadFile(path) + if err != nil { + return nil, nil, nil, err + } + + err = json.Unmarshal(contents, &proposal) + if err != nil { + return nil, nil, nil, err + } + + msgs := make([]sdk.Msg, len(proposal.Messages)) + for i, anyJSON := range proposal.Messages { + var msg sdk.Msg + err := cdc.UnmarshalInterfaceJSON(anyJSON, &msg) + if err != nil { + return nil, nil, nil, err + } + + msgs[i] = msg + } + + deposit, err := sdk.ParseCoinsNormalized(proposal.Deposit) + if err != nil { + return nil, nil, nil, err + } + + return msgs, proposal.Metadata, deposit, nil +} diff --git a/x/gov/client/cli/parse_test.go b/x/gov/client/cli/parse_test.go index da6aeea71..12946b68c 100644 --- a/x/gov/client/cli/parse_test.go +++ b/x/gov/client/cli/parse_test.go @@ -1,14 +1,24 @@ package cli import ( + "encoding/base64" + "fmt" "testing" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/testutil" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta2" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) -func TestParseSubmitProposalFlags(t *testing.T) { +func TestParseSubmitLegacyProposalFlags(t *testing.T) { okJSON := testutil.WriteToNewTempFile(t, ` { "title": "Test Proposal", @@ -19,21 +29,21 @@ func TestParseSubmitProposalFlags(t *testing.T) { `) badJSON := testutil.WriteToNewTempFile(t, "bad json") - fs := NewCmdSubmitProposal().Flags() + fs := NewCmdSubmitLegacyProposal().Flags() // nonexistent json fs.Set(FlagProposal, "fileDoesNotExist") - _, err := parseSubmitProposalFlags(fs) + _, err := parseSubmitLegacyProposalFlags(fs) require.Error(t, err) // invalid json fs.Set(FlagProposal, badJSON.Name()) - _, err = parseSubmitProposalFlags(fs) + _, err = parseSubmitLegacyProposalFlags(fs) require.Error(t, err) // ok json fs.Set(FlagProposal, okJSON.Name()) - proposal1, err := parseSubmitProposalFlags(fs) + proposal1, err := parseSubmitLegacyProposalFlags(fs) require.Nil(t, err, "unexpected error") require.Equal(t, "Test Proposal", proposal1.Title) require.Equal(t, "My awesome proposal", proposal1.Description) @@ -43,7 +53,7 @@ func TestParseSubmitProposalFlags(t *testing.T) { // flags that can't be used with --proposal for _, incompatibleFlag := range ProposalFlags { fs.Set(incompatibleFlag, "some value") - _, err := parseSubmitProposalFlags(fs) + _, err := parseSubmitLegacyProposalFlags(fs) require.Error(t, err) fs.Set(incompatibleFlag, "") } @@ -54,7 +64,7 @@ func TestParseSubmitProposalFlags(t *testing.T) { fs.Set(FlagDescription, proposal1.Description) fs.Set(FlagProposalType, proposal1.Type) fs.Set(FlagDeposit, proposal1.Deposit) - proposal2, err := parseSubmitProposalFlags(fs) + proposal2, err := parseSubmitLegacyProposalFlags(fs) require.Nil(t, err, "unexpected error") require.Equal(t, proposal1.Title, proposal2.Title) @@ -67,3 +77,83 @@ func TestParseSubmitProposalFlags(t *testing.T) { err = badJSON.Close() require.Nil(t, err, "unexpected error") } + +func TestParseSubmitProposal(t *testing.T) { + _, _, addr := testdata.KeyTestPubAddr() + interfaceRegistry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + banktypes.RegisterInterfaces(interfaceRegistry) + stakingtypes.RegisterInterfaces(interfaceRegistry) + v1beta1.RegisterInterfaces(interfaceRegistry) + v1beta2.RegisterInterfaces(interfaceRegistry) + expectedMetadata := []byte{42} + + okJSON := testutil.WriteToNewTempFile(t, fmt.Sprintf(` +{ + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "%s", + "to_address": "%s", + "amount":[{"denom": "stake","amount": "10"}] + }, + { + "@type": "/cosmos.staking.v1beta1.MsgDelegate", + "delegator_address": "%s", + "validator_address": "%s", + "amount":{"denom": "stake","amount": "10"} + }, + { + "@type": "/cosmos.gov.v1beta2.MsgExecLegacyContent", + "authority": "%s", + "content": { + "@type": "/cosmos.gov.v1beta1.TextProposal", + "title": "My awesome title", + "description": "My awesome description" + } + } + ], + "metadata": "%s", + "deposit": "1000test" +} +`, addr, addr, addr, addr, addr, base64.StdEncoding.EncodeToString(expectedMetadata))) + + badJSON := testutil.WriteToNewTempFile(t, "bad json") + + // nonexistent json + _, _, _, err := parseSubmitProposal(cdc, "fileDoesNotExist") + require.Error(t, err) + + // invalid json + _, _, _, err = parseSubmitProposal(cdc, badJSON.Name()) + require.Error(t, err) + + // ok json + msgs, metadata, deposit, err := parseSubmitProposal(cdc, okJSON.Name()) + require.NoError(t, err, "unexpected error") + require.Equal(t, sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(1000))), deposit) + require.Equal(t, expectedMetadata, metadata) + require.Len(t, msgs, 3) + msg1, ok := msgs[0].(*banktypes.MsgSend) + require.True(t, ok) + require.Equal(t, addr.String(), msg1.FromAddress) + require.Equal(t, addr.String(), msg1.ToAddress) + require.Equal(t, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(10))), msg1.Amount) + msg2, ok := msgs[1].(*stakingtypes.MsgDelegate) + require.True(t, ok) + require.Equal(t, addr.String(), msg2.DelegatorAddress) + require.Equal(t, addr.String(), msg2.ValidatorAddress) + require.Equal(t, sdk.NewCoin("stake", sdk.NewInt(10)), msg2.Amount) + msg3, ok := msgs[2].(*v1beta2.MsgExecLegacyContent) + require.True(t, ok) + require.Equal(t, addr.String(), msg3.Authority) + textProp, ok := msg3.Content.GetCachedValue().(*v1beta1.TextProposal) + require.True(t, ok) + require.Equal(t, "My awesome title", textProp.Title) + require.Equal(t, "My awesome description", textProp.Description) + + err = okJSON.Close() + require.Nil(t, err, "unexpected error") + err = badJSON.Close() + require.Nil(t, err, "unexpected error") +} diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index ecec13bd6..17c3db75e 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -20,23 +20,21 @@ import ( // Proposal flags const ( - FlagTitle = "title" - FlagDescription = "description" + // Deprecated: only used for v1beta1 legacy proposals. + FlagTitle = "title" + // Deprecated: only used for v1beta1 legacy proposals. + FlagDescription = "description" + // Deprecated: only used for v1beta1 legacy proposals. FlagProposalType = "type" + // Deprecated: only used for v1beta1 legacy proposals. FlagDeposit = "deposit" flagVoter = "voter" flagDepositor = "depositor" flagStatus = "status" - FlagProposal = "proposal" + // Deprecated: only used for v1beta1 legacy proposals. + FlagProposal = "proposal" ) -type proposal struct { - Title string - Description string - Type string - Deposit string -} - // ProposalFlags defines the core required fields of a proposal. It is used to // verify that these values are not provided in conjunction with a JSON proposal // file. @@ -61,19 +59,18 @@ func NewTxCmd(propCmds []*cobra.Command) *cobra.Command { RunE: client.ValidateCmd, } - // TODO Add CLI for new submit proposal - // https://github.com/cosmos/cosmos-sdk/issues/10952 - cmdSubmitProp := NewCmdSubmitProposal() + cmdSubmitLegacyProp := NewCmdSubmitLegacyProposal() for _, propCmd := range propCmds { flags.AddTxFlagsToCmd(propCmd) - cmdSubmitProp.AddCommand(propCmd) + cmdSubmitLegacyProp.AddCommand(propCmd) } govTxCmd.AddCommand( NewCmdDeposit(), NewCmdVote(), NewCmdWeightedVote(), - cmdSubmitProp, + NewCmdSubmitProposal(), + cmdSubmitLegacyProp, ) return govTxCmd @@ -83,13 +80,71 @@ func NewTxCmd(propCmds []*cobra.Command) *cobra.Command { func NewCmdSubmitProposal() *cobra.Command { cmd := &cobra.Command{ Use: "submit-proposal", - Short: "Submit a proposal along with an initial deposit", + Short: "Submit a proposal along with some messages and metadata", + Args: cobra.ExactArgs(1), Long: strings.TrimSpace( - fmt.Sprintf(`Submit a proposal along with an initial deposit. + fmt.Sprintf(`Submit a proposal along with some messages and metadata. +Messages, metadata and deposit are defined in a JSON file. + +Example: +$ %s tx gov submit-proposal path/to/proposal.json + +Where proposal.json contains: + +{ + // array of proto-JSON-encoded sdk.Msgs + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "cosmos1...", + "to_address": "cosmos1...", + "amount":[{"denom": "stake","amount": "10"}] + } + ], + "metadata: "4pIMOgIGx1vZGU=", // base64-encoded metadata + "deposit": "10stake" +} +`, + version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msgs, metadata, deposit, err := parseSubmitProposal(clientCtx.Codec, args[0]) + if err != nil { + return err + } + + msg, err := v1beta2.NewMsgSubmitProposal(msgs, deposit, clientCtx.GetFromAddress().String(), metadata) + if err != nil { + return fmt.Errorf("invalid message: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// NewCmdSubmitLegacyProposal implements submitting a proposal transaction command. +// Deprecated: please use NewCmdSubmitProposal instead. +func NewCmdSubmitLegacyProposal() *cobra.Command { + cmd := &cobra.Command{ + Use: "submit-legacy-proposal", + Short: "Submit a legacy proposal along with an initial deposit", + Long: strings.TrimSpace( + fmt.Sprintf(`Submit a legacy proposal along with an initial deposit. Proposal title, description, type and deposit can be given directly or through a proposal JSON file. Example: -$ %s tx gov submit-proposal --proposal="path/to/proposal.json" --from mykey +$ %s tx gov submit-legacy-proposal --proposal="path/to/proposal.json" --from mykey Where proposal.json contains: @@ -102,7 +157,7 @@ Where proposal.json contains: Which is equivalent to: -$ %s tx gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --deposit="10test" --from mykey +$ %s tx gov submit-legacy-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --deposit="10test" --from mykey `, version.AppName, version.AppName, ), @@ -113,7 +168,7 @@ $ %s tx gov submit-proposal --title="Test Proposal" --description="My awesome pr return err } - proposal, err := parseSubmitProposalFlags(cmd.Flags()) + proposal, err := parseSubmitLegacyProposalFlags(cmd.Flags()) if err != nil { return fmt.Errorf("failed to parse proposal: %w", err) } diff --git a/x/gov/client/testutil/deposits.go b/x/gov/client/testutil/deposits.go index d45aa13f3..eb2d5b1a8 100644 --- a/x/gov/client/testutil/deposits.go +++ b/x/gov/client/testutil/deposits.go @@ -74,7 +74,7 @@ func (s *DepositTestSuite) createProposal(val *network.Validator, initialDeposit exactArgs = append(exactArgs, fmt.Sprintf("--%s=%s", cli.FlagDeposit, initialDeposit.String())) } - _, err := MsgSubmitProposal( + _, err := MsgSubmitLegacyProposal( val.ClientCtx, val.Address.String(), fmt.Sprintf("Text Proposal %d", id), diff --git a/x/gov/client/testutil/helpers.go b/x/gov/client/testutil/helpers.go index e16ac0e98..0e17ead4a 100644 --- a/x/gov/client/testutil/helpers.go +++ b/x/gov/client/testutil/helpers.go @@ -31,6 +31,20 @@ func MsgSubmitProposal(clientCtx client.Context, from, title, description, propo return clitestutil.ExecTestCLICmd(clientCtx, govcli.NewCmdSubmitProposal(), args) } +// MsgSubmitLegacyProposal creates a tx for submit legacy proposal +func MsgSubmitLegacyProposal(clientCtx client.Context, from, title, description, proposalType string, extraArgs ...string) (testutil.BufferWriter, error) { + args := append([]string{ + fmt.Sprintf("--%s=%s", govcli.FlagTitle, title), + fmt.Sprintf("--%s=%s", govcli.FlagDescription, description), + fmt.Sprintf("--%s=%s", govcli.FlagProposalType, proposalType), + fmt.Sprintf("--%s=%s", flags.FlagFrom, from), + }, commonArgs...) + + args = append(args, extraArgs...) + + return clitestutil.ExecTestCLICmd(clientCtx, govcli.NewCmdSubmitLegacyProposal(), args) +} + // MsgVote votes for a proposal func MsgVote(clientCtx client.Context, from, id, vote string, extraArgs ...string) (testutil.BufferWriter, error) { args := append([]string{ diff --git a/x/gov/client/testutil/suite.go b/x/gov/client/testutil/suite.go index 420c7125c..cb88db9a1 100644 --- a/x/gov/client/testutil/suite.go +++ b/x/gov/client/testutil/suite.go @@ -1,6 +1,7 @@ package testutil import ( + "encoding/base64" "fmt" "strings" @@ -15,7 +16,9 @@ import ( clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta2" ) @@ -44,7 +47,7 @@ func (s *IntegrationTestSuite) SetupSuite() { val := s.network.Validators[0] // create a proposal with deposit - _, err = MsgSubmitProposal(val.ClientCtx, val.Address.String(), + _, err = MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(), "Text Proposal 1", "Where is the title!?", v1beta1.ProposalTypeText, fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1beta2.DefaultMinDepositTokens).String())) s.Require().NoError(err) @@ -56,14 +59,14 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) // create a proposal without deposit - _, err = MsgSubmitProposal(val.ClientCtx, val.Address.String(), + _, err = MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(), "Text Proposal 2", "Where is the title!?", v1beta1.ProposalTypeText) s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) // create a proposal3 with deposit - _, err = MsgSubmitProposal(val.ClientCtx, val.Address.String(), + _, err = MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(), "Text Proposal 3", "Where is the title!?", v1beta1.ProposalTypeText, fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1beta2.DefaultMinDepositTokens).String())) s.Require().NoError(err) @@ -278,6 +281,88 @@ func (s *IntegrationTestSuite) TestCmdTally() { func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() { val := s.network.Validators[0] + + // Create an legacy proposal JSON, make sure it doesn't pass this new CLI + // command. + invalidProp := `{ + "title": "", + "description": "Where is the title!?", + "type": "Text", + "deposit": "-324foocoin" +}` + invalidPropFile := testutil.WriteToNewTempFile(s.T(), invalidProp) + + // Create a valid new proposal JSON. + propMetadata := []byte{42} + validProp := fmt.Sprintf(` +{ + "messages": [ + { + "@type": "/cosmos.gov.v1beta2.MsgExecLegacyContent", + "authority": "%s", + "content": { + "@type": "/cosmos.gov.v1beta1.TextProposal", + "title": "My awesome title", + "description": "My awesome description" + } + } + ], + "metadata": "%s", + "deposit": "%s" +}`, authtypes.NewModuleAddress(types.ModuleName), base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(5431))) + validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) + + testCases := []struct { + name string + args []string + expectErr bool + expectedCode uint32 + respType proto.Message + }{ + { + "invalid proposal", + []string{ + invalidPropFile.Name(), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + true, 0, nil, + }, + { + "valid proposal", + []string{ + validPropFile.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + false, 0, &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.NewCmdSubmitProposal() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestNewCmdSubmitLegacyProposal() { + val := s.network.Validators[0] invalidProp := `{ "title": "", "description": "Where is the title!?", @@ -352,7 +437,7 @@ func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() { tc := tc s.Run(tc.name, func() { - cmd := cli.NewCmdSubmitProposal() + cmd := cli.NewCmdSubmitLegacyProposal() clientCtx := val.ClientCtx out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)