diff --git a/client/prompt_validation.go b/client/prompt_validation.go index d3e3e23217..b10ac1e14a 100644 --- a/client/prompt_validation.go +++ b/client/prompt_validation.go @@ -47,7 +47,7 @@ func ValidatePromptAddress(input string) error { return fmt.Errorf("invalid address: %w", err) } -// ValidatePromptYesNo validates that the input is valid sdk.COins +// ValidatePromptCoins validates that the input contains valid sdk.Coins func ValidatePromptCoins(input string) error { if _, err := sdk.ParseCoinsNormalized(input); err != nil { return fmt.Errorf("invalid coins: %w", err) diff --git a/client/v2/CHANGELOG.md b/client/v2/CHANGELOG.md index 86fa06c8e7..5381274968 100644 --- a/client/v2/CHANGELOG.md +++ b/client/v2/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Features + +* [#24359](https://github.com/cosmos/cosmos-sdk/pull/24359) Support governance proposals. + ### Bug Fixes * (cli) [#24330](https://github.com/cosmos/cosmos-sdk/pull/24330) Use the gogoproto merge registry as a file resolver instead of the interface registry. @@ -99,7 +103,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#20083](https://github.com/cosmos/cosmos-sdk/pull/20083) Integrate latest version of cosmos-proto and improve version filtering. * [#19618](https://github.com/cosmos/cosmos-sdk/pull/19618) Marshal enum as string in queries. * [#19060](https://github.com/cosmos/cosmos-sdk/pull/19060) Use client context from root (or enhanced) command in autocli commands. - * Note, the given command must have a `client.Context` in its context. + * Note, the given command must have a `client.Context` in its context. * [#19216](https://github.com/cosmos/cosmos-sdk/pull/19216) Do not overwrite TxConfig, use directly the one provided in context. TxConfig should always be set in the `client.Context` in `root.go` of an app. * [#20266](https://github.com/cosmos/cosmos-sdk/pull/20266) Add ability to override the short description in AutoCLI-generated top-level commands. diff --git a/client/v2/README.md b/client/v2/README.md index 06410452d6..a0c7c21067 100644 --- a/client/v2/README.md +++ b/client/v2/README.md @@ -110,7 +110,7 @@ This field is automatically filled when using the `--from` flag or defining the AutoCLI currently supports only one signer per transaction. ::: -## Module Wiring & Customization +## Module wiring & Customization The `AutoCLIOptions()` method on your module allows to specify custom commands, sub-commands or flags for each service, as it was a `cobra.Command` instance, within the `RpcCommandOptions` struct. Defining such options will customize the behavior of the `autocli` command generation, which by default generates a command for each method in your gRPC service. @@ -126,6 +126,11 @@ The `AutoCLIOptions()` method on your module allows to specify custom commands, } ``` +:::tip +AutoCLI can create a gov proposal of any tx by simply setting the `GovProposal` field to `true` in the `autocli.RpcCommandOptions` struct. +Users can however use the `--no-proposal` flag to disable the proposal creation (which is useful if the authority isn't the gov module on a chain). +::: + ### Specifying Subcommands By default, `autocli` generates a command for each method in your gRPC service. However, you can specify subcommands to group related commands together. To specify subcommands, use the `autocliv1.ServiceCommandDescriptor` struct. diff --git a/client/v2/autocli/flag/builder.go b/client/v2/autocli/flag/builder.go index 1235809608..1284dae863 100644 --- a/client/v2/autocli/flag/builder.go +++ b/client/v2/autocli/flag/builder.go @@ -248,10 +248,10 @@ func (b *Builder) addMessageFlags(ctx *context.Context, flagSet *pflag.FlagSet, flagOpts := commandOptions.FlagOptions[fieldName] name, hasValue, err := b.addFieldFlag(ctx, flagSet, field, flagOpts, options) - flagOptsByFlagName[name] = flagOpts if err != nil { return nil, err } + flagOptsByFlagName[name] = flagOpts messageBinder.flagBindings = append(messageBinder.flagBindings, fieldBinding{ hasValue: hasValue, diff --git a/client/v2/autocli/msg.go b/client/v2/autocli/msg.go index 02f214a90e..16dfeecaa2 100644 --- a/client/v2/autocli/msg.go +++ b/client/v2/autocli/msg.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + gogoproto "github.com/cosmos/gogoproto/proto" "github.com/spf13/cobra" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" @@ -11,10 +12,15 @@ import ( autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" "cosmossdk.io/client/v2/autocli/flag" + "cosmossdk.io/client/v2/internal/flags" "cosmossdk.io/client/v2/internal/util" + addresscodec "cosmossdk.io/core/address" "github.com/cosmos/cosmos-sdk/client" clienttx "github.com/cosmos/cosmos-sdk/client/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) // BuildMsgCommand builds the msg commands for all the provided modules. If a custom command is provided for a @@ -123,6 +129,12 @@ func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor fd := input.Descriptor().Fields().ByName(protoreflect.Name(flag.GetSignerFieldName(input.Descriptor()))) addressCodec := b.AddressCodec + // handle gov proposals commands + skipProposal, _ := cmd.Flags().GetBool(flags.FlagNoProposal) + if options.GovProposal && !skipProposal { + return b.handleGovProposal(cmd, input, clientCtx, addressCodec, fd) + } + // set signer to signer field if empty if addr := input.Get(fd).String(); addr == "" { scalarType, ok := flag.GetScalarType(fd) @@ -166,5 +178,50 @@ func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor // silence usage only for inner txs & queries commands cmd.SilenceUsage = true + // set gov proposal flags if command is a gov proposal + if options.GovProposal { + govcli.AddGovPropFlagsToCmd(cmd) + cmd.Flags().Bool(flags.FlagNoProposal, false, "Skip gov proposal and submit a normal transaction") + } + return cmd, nil } + +// handleGovProposal sets the authority field of the message to the gov module address and creates a gov proposal. +func (b *Builder) handleGovProposal( + cmd *cobra.Command, + input protoreflect.Message, + clientCtx client.Context, + addressCodec addresscodec.Codec, + fd protoreflect.FieldDescriptor, +) error { + govAuthority := authtypes.NewModuleAddress(govtypes.ModuleName) + authority, err := addressCodec.BytesToString(govAuthority.Bytes()) + if err != nil { + return fmt.Errorf("failed to convert gov authority: %w", err) + } + input.Set(fd, protoreflect.ValueOfString(authority)) + + signerFromFlag := clientCtx.GetFromAddress() + signer, err := addressCodec.BytesToString(signerFromFlag.Bytes()) + if err != nil { + return fmt.Errorf("failed to set signer on message, got %q: %w", signerFromFlag, err) + } + + proposal, err := govcli.ReadGovPropCmdFlags(signer, cmd.Flags()) + if err != nil { + return err + } + + // AutoCLI uses protov2 messages, while the SDK only supports proto v1 messages. + // Here we use dynamicpb, to create a proto v1 compatible message. + // The SDK codec will handle protov2 -> protov1 (marshal) + msg := dynamicpb.NewMessage(input.Descriptor()) + proto.Merge(msg, input.Interface()) + + if err := proposal.SetMsgs([]gogoproto.Message{msg}); err != nil { + return fmt.Errorf("failed to set msg in proposal %w", err) + } + + return clienttx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), proposal) +} diff --git a/client/v2/autocli/msg_test.go b/client/v2/autocli/msg_test.go index 612207b6a4..97ba5a73a1 100644 --- a/client/v2/autocli/msg_test.go +++ b/client/v2/autocli/msg_test.go @@ -51,6 +51,7 @@ func TestMsg(t *testing.T) { "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "1foo", "--generate-only", "--output", "json", + "--chain-id", "test-chain", ) assert.NilError(t, err) golden.Assert(t, out.String(), "msg-output.golden") diff --git a/client/v2/go.mod b/client/v2/go.mod index 1dcff76c58..3c97ae0754 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -2,6 +2,8 @@ module cosmossdk.io/client/v2 go 1.23.2 +replace github.com/cosmos/cosmos-sdk => ../.. + require ( cosmossdk.io/api v0.9.0 cosmossdk.io/core v0.11.3 @@ -38,6 +40,7 @@ require ( github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect github.com/cloudwego/base64x v0.1.5 // indirect github.com/cockroachdb/apd/v3 v3.2.1 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect @@ -107,6 +110,7 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/linxGnu/grocksdb v1.8.14 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/minio/highwayhash v1.0.3 // indirect diff --git a/client/v2/go.sum b/client/v2/go.sum index 2fde631ba5..6701f73a8c 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -95,10 +95,14 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= @@ -149,8 +153,6 @@ github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNC github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.53.0-rc.2 h1:KdQRIp6z/hQK9VppPU1exuXobLLwhrrRIrAOlzzaIf0= -github.com/cosmos/cosmos-sdk v0.53.0-rc.2/go.mod h1:GCGPg/EJ9FCygDZ8yHxuq3aM577FC706LpXwl2LbXKQ= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -892,6 +894,7 @@ golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/client/v2/internal/flags/flags.go b/client/v2/internal/flags/flags.go index cd50a96be8..d06cef708c 100644 --- a/client/v2/internal/flags/flags.go +++ b/client/v2/internal/flags/flags.go @@ -10,6 +10,13 @@ const ( // FlagNoIndent is the flag to not indent the output. FlagNoIndent = "no-indent" + + // FlagNoPrompt is the flag to not use a prompt for commands. + FlagNoPrompt = "no-prompt" + + // FlagNoProposal is the flag convert a gov proposal command into a normal command. + // This is used to allow user of chains with custom authority to not use gov submit proposals for usual proposal commands. + FlagNoProposal = "no-proposal" ) // List of supported output formats diff --git a/x/auth/autocli.go b/x/auth/autocli.go index 6d60e1d8be..d80fac0afd 100644 --- a/x/auth/autocli.go +++ b/x/auth/autocli.go @@ -80,8 +80,12 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Service: authv1beta1.Msg_ServiceDesc.ServiceName, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { - RpcMethod: "UpdateParams", - Skip: true, // skipped because authority gated + RpcMethod: "UpdateParams", + Use: "update-params-proposal [params]", + Short: "Submit a proposal to update auth module params. Note: the entire params must be provided.", + Example: fmt.Sprintf(`%s tx auth update-params-proposal '{ "max_memo_characters": 0, "tx_sig_limit": 0, "tx_size_cost_per_byte": 0, "sig_verify_cost_ed25519": 0, "sig_verify_cost_secp256k1": 0 }'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}}, + GovProposal: true, }, }, }, diff --git a/x/bank/autocli.go b/x/bank/autocli.go index 6c421ab0aa..d778d4f2ee 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -1,10 +1,13 @@ package bank import ( + "fmt" "strings" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" + + "github.com/cosmos/cosmos-sdk/version" ) // AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. @@ -88,7 +91,7 @@ To look up all denoms, do not provide any arguments.`, }, Tx: &autocliv1.ServiceCommandDescriptor{ Service: bankv1beta1.Msg_ServiceDesc.ServiceName, - EnhanceCustomCommand: false, // use custom commands only until v0.51 + EnhanceCustomCommand: true, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "Send", @@ -101,16 +104,23 @@ Note: multiple coins can be send by space separated.`, PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "to_address"}, {ProtoField: "amount", Varargs: true}}, }, { - RpcMethod: "UpdateParams", - Skip: true, // skipped because authority gated + RpcMethod: "UpdateParams", + Use: "update-params-proposal [params]", + Short: "Submit a proposal to update bank module params. Note: the entire params must be provided.", + Example: fmt.Sprintf(`%s tx bank update-params-proposal '{ "default_send_enabled": true }'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}}, + GovProposal: true, }, { - RpcMethod: "SetSendEnabled", - Skip: true, // skipped because authority gated - }, - { - RpcMethod: "Burn", - Skip: true, // skipped because available from v0.51 + RpcMethod: "SetSendEnabled", + Use: "set-send-enabled-proposal [send_enabled]", + Short: "Submit a proposal to set/update/delete send enabled entries", + Example: fmt.Sprintf(`%s tx bank set-send-enabled-proposal '{"denom":"stake","enabled":true}'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "send_enabled", Varargs: true}}, + FlagOptions: map[string]*autocliv1.FlagOptions{ + "use_default_for": {Name: "use-default-for", Usage: "Use default for the given denom (delete a send enabled entry)"}, + }, + GovProposal: true, }, }, }, diff --git a/x/consensus/autocli.go b/x/consensus/autocli.go index 5a2e00900c..14784dced7 100644 --- a/x/consensus/autocli.go +++ b/x/consensus/autocli.go @@ -1,10 +1,13 @@ package consensus import ( + "fmt" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" consensusv1 "cosmossdk.io/api/cosmos/consensus/v1" "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" + "github.com/cosmos/cosmos-sdk/version" ) // AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. @@ -28,7 +31,16 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "UpdateParams", - Skip: true, // skipped because authority gated + Use: "update-params-proposal [params]", + Short: "Submit a proposal to update consensus module params. Note: the entire params must be provided.", + Example: fmt.Sprintf(`%s tx consensus update-params-proposal '{ params }'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "block"}, + {ProtoField: "evidence"}, + {ProtoField: "validator"}, + {ProtoField: "abci"}, + }, + GovProposal: true, }, }, }, diff --git a/x/crisis/autocli.go b/x/crisis/autocli.go index 92edd95d0c..99586c26b2 100644 --- a/x/crisis/autocli.go +++ b/x/crisis/autocli.go @@ -1,8 +1,11 @@ package crisis import ( + "fmt" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" crisisv1beta1 "cosmossdk.io/api/cosmos/crisis/v1beta1" + "github.com/cosmos/cosmos-sdk/version" ) // AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. @@ -21,8 +24,12 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, }, { - RpcMethod: "UpdateParams", - Skip: true, // Skipped because UpdateParams is authority gated + RpcMethod: "UpdateParams", + Use: "update-params-proposal [params]", + Short: "Submit a proposal to update crisis module params. Note: the entire params must be provided.", + Example: fmt.Sprintf(`%s tx crisis update-params-proposal '{ "constant_fee": {"denom": "stake", "amount": "1000"} }'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}}, + GovProposal: true, }, }, }, diff --git a/x/distribution/autocli.go b/x/distribution/autocli.go index a8c6c4041b..a74f999f5d 100644 --- a/x/distribution/autocli.go +++ b/x/distribution/autocli.go @@ -4,7 +4,7 @@ import ( "fmt" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" - distirbuitonv1beta1 "cosmossdk.io/api/cosmos/distribution/v1beta1" + distributionv1beta1 "cosmossdk.io/api/cosmos/distribution/v1beta1" "github.com/cosmos/cosmos-sdk/version" ) @@ -13,7 +13,7 @@ import ( func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { return &autocliv1.ModuleOptions{ Query: &autocliv1.ServiceCommandDescriptor{ - Service: distirbuitonv1beta1.Query_ServiceDesc.ServiceName, + Service: distributionv1beta1.Query_ServiceDesc.ServiceName, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "Params", @@ -88,7 +88,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, }, Tx: &autocliv1.ServiceCommandDescriptor{ - Service: distirbuitonv1beta1.Msg_ServiceDesc.ServiceName, + Service: distributionv1beta1.Msg_ServiceDesc.ServiceName, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "SetWithdrawAddress", @@ -135,15 +135,26 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, }, { - RpcMethod: "UpdateParams", - Skip: true, // skipped because authority gated + RpcMethod: "UpdateParams", + Use: "update-params-proposal [params]", + Short: "Submit a proposal to update distribution module params. Note: the entire params must be provided.", + Example: fmt.Sprintf(`%s tx distribution update-params-proposal '{ "community_tax": "20000", "base_proposer_reward": "0", "bonus_proposer_reward": "0", "withdraw_addr_enabled": true }'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}}, + GovProposal: true, }, { RpcMethod: "CommunityPoolSpend", - Skip: true, // skipped because authority gated + Use: "community-pool-spend-proposal [recipient] [amount]", + Example: fmt.Sprintf(`$ %s tx distribution community-pool-spend-proposal [recipient] 100uatom`, version.AppName), + Short: "Submit a proposal to spend from the community pool", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "recipient"}, + {ProtoField: "amount", Varargs: true}, + }, + GovProposal: true, }, }, - EnhanceCustomCommand: false, // use custom commands only until v0.51 + EnhanceCustomCommand: true, }, } } diff --git a/x/gov/autocli.go b/x/gov/autocli.go index 8512a2878c..95079e2467 100644 --- a/x/gov/autocli.go +++ b/x/gov/autocli.go @@ -131,8 +131,13 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, }, { - RpcMethod: "UpdateParams", - Skip: true, // skipped because authority gated + RpcMethod: "UpdateParams", + Use: "update-params-proposal [params]", + Short: "Submit a proposal to update gov module params. Note: the entire params must be provided.", + Long: fmt.Sprintf("Submit a proposal to update gov module params. Note: the entire params must be provided.\n See the fields to fill in by running `%s query gov params --output json`", version.AppName), + Example: fmt.Sprintf(`%s tx gov update-params-proposal '{ params }'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}}, + GovProposal: true, }, }, EnhanceCustomCommand: false, // use custom commands only until v0.51 diff --git a/x/gov/client/cli/prompt.go b/x/gov/client/cli/prompt.go index 10bc8b75b2..600442e0a4 100644 --- a/x/gov/client/cli/prompt.go +++ b/x/gov/client/cli/prompt.go @@ -53,6 +53,8 @@ var suggestedProposalTypes = []proposalType{ // Prompt prompts the user for all values of the given type. // data is the struct to be filled // namePrefix is the name to be displayed as "Enter " +// TODO: when bringing this in autocli, use proto message instead +// this will simplify the get address logic func Prompt[T any](data T, namePrefix string) (T, error) { v := reflect.ValueOf(&data).Elem() if v.Kind() == reflect.Interface { diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 5fe705dba5..d6c4a79d67 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -27,6 +27,8 @@ const ( flagStatus = "status" FlagMetadata = "metadata" FlagSummary = "summary" + FlagExpedited = "expedited" + // Deprecated: only used for v1beta1 legacy proposals. FlagProposal = "proposal" // Deprecated: only used for v1beta1 legacy proposals. diff --git a/x/gov/client/cli/util.go b/x/gov/client/cli/util.go index 63be49dc35..74b48f4625 100644 --- a/x/gov/client/cli/util.go +++ b/x/gov/client/cli/util.go @@ -131,13 +131,14 @@ func AddGovPropFlagsToCmd(cmd *cobra.Command) { cmd.Flags().String(FlagMetadata, "", "The metadata to include with the governance proposal") cmd.Flags().String(FlagTitle, "", "The title to put on the governance proposal") cmd.Flags().String(FlagSummary, "", "The summary to include with the governance proposal") + cmd.Flags().Bool(FlagExpedited, false, "Whether to expedite the governance proposal") } -// ReadGovPropFlags parses a MsgSubmitProposal from the provided context and flags. +// ReadGovPropCmdFlags parses a MsgSubmitProposal from the provided context and flags. // Setting the messages is up to the caller. // // See also AddGovPropFlagsToCmd. -func ReadGovPropFlags(clientCtx client.Context, flagSet *pflag.FlagSet) (*govv1.MsgSubmitProposal, error) { +func ReadGovPropCmdFlags(proposer string, flagSet *pflag.FlagSet) (*govv1.MsgSubmitProposal, error) { rv := &govv1.MsgSubmitProposal{} deposit, err := flagSet.GetString(FlagDeposit) @@ -166,7 +167,21 @@ func ReadGovPropFlags(clientCtx client.Context, flagSet *pflag.FlagSet) (*govv1. return nil, fmt.Errorf("could not read summary: %w", err) } - rv.Proposer = clientCtx.GetFromAddress().String() + rv.Expedited, err = flagSet.GetBool(FlagExpedited) + if err != nil { + return nil, fmt.Errorf("could not read expedited: %w", err) + } + + rv.Proposer = proposer return rv, nil } + +// ReadGovPropFlags parses a MsgSubmitProposal from the provided context and flags. +// Setting the messages is up to the caller. +// +// See also AddGovPropFlagsToCmd. +// Deprecated: use ReadPropCmdFlags instead, as this depends on global bech32 prefixes. +func ReadGovPropFlags(clientCtx client.Context, flagSet *pflag.FlagSet) (*govv1.MsgSubmitProposal, error) { + return ReadGovPropCmdFlags(clientCtx.GetFromAddress().String(), flagSet) +} diff --git a/x/mint/autocli.go b/x/mint/autocli.go index 8ac35d04b6..9b096043b5 100644 --- a/x/mint/autocli.go +++ b/x/mint/autocli.go @@ -1,8 +1,12 @@ package mint import ( + "fmt" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" mintv1beta1 "cosmossdk.io/api/cosmos/mint/v1beta1" + + "github.com/cosmos/cosmos-sdk/version" ) func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { @@ -31,8 +35,13 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Service: mintv1beta1.Msg_ServiceDesc.ServiceName, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { - RpcMethod: "UpdateParams", - Skip: true, // skipped because authority gated + RpcMethod: "UpdateParams", + Use: "update-params-proposal [params]", + Short: "Submit a proposal to update mint module params. Note: the entire params must be provided.", + Long: fmt.Sprintf("Submit a proposal to update mint module params. Note: the entire params must be provided.\n See the fields to fill in by running `%s query mint params --output json`", version.AppName), + Example: fmt.Sprintf(`%s tx mint update-params-proposal '{ "mint_denom": "stake", ... }'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}}, + GovProposal: true, }, }, }, diff --git a/x/slashing/autocli.go b/x/slashing/autocli.go index fede1143e7..2966d33112 100644 --- a/x/slashing/autocli.go +++ b/x/slashing/autocli.go @@ -46,8 +46,13 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Example: fmt.Sprintf("%s tx slashing unjail --from [validator]", version.AppName), }, { - RpcMethod: "UpdateParams", - Skip: true, // skipped because authority gated + RpcMethod: "UpdateParams", + Use: "update-params-proposal [params]", + Short: "Submit a proposal to update slashing module params. Note: the entire params must be provided.", + Long: fmt.Sprintf("Submit a proposal to update slashing module params. Note: the entire params must be provided.\n See the fields to fill in by running `%s query slashing params --output json`", version.AppName), + Example: fmt.Sprintf(`%s tx slashing update-params-proposal '{ "signed_blocks_window": "100", ... }'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}}, + GovProposal: true, }, }, }, diff --git a/x/staking/autocli.go b/x/staking/autocli.go index 7793049bae..886dcf181c 100644 --- a/x/staking/autocli.go +++ b/x/staking/autocli.go @@ -174,8 +174,13 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "validator_address"}, {ProtoField: "amount"}, {ProtoField: "creation_height"}}, }, { - RpcMethod: "UpdateParams", - Skip: true, // skipped because authority gated + RpcMethod: "UpdateParams", + Use: "update-params-proposal [params]", + Short: "Submit a proposal to update staking module params. Note: the entire params must be provided.", + Long: fmt.Sprintf("Submit a proposal to update staking module params. Note: the entire params must be provided.\n See the fields to fill in by running `%s query staking params --output json`", version.AppName), + Example: fmt.Sprintf(`%s tx staking update-params-proposal '{ "unbonding_time": "504h0m0s", ... }'`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}}, + GovProposal: true, }, }, EnhanceCustomCommand: false, // use custom commands only until v0.51 diff --git a/x/upgrade/autocli.go b/x/upgrade/autocli.go index 45d076c75e..36265aea32 100644 --- a/x/upgrade/autocli.go +++ b/x/upgrade/autocli.go @@ -49,15 +49,18 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Tx: &autocliv1.ServiceCommandDescriptor{ Service: upgradev1beta1.Msg_ServiceDesc.ServiceName, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "CancelUpgrade", + Use: "cancel-upgrade-proposal", + Short: "Submit a proposal to cancel a planned chain upgrade.", + GovProposal: true, + }, { RpcMethod: "SoftwareUpgrade", Skip: true, // skipped because authority gated }, - { - RpcMethod: "CancelUpgrade", - Skip: true, // skipped because authority gated - }, }, + EnhanceCustomCommand: true, }, } }