Files
wasmd/x/wasm/client/cli/gov_tx.go
Orkun Külçe e7f41f2d17 Implement PinCode and UnpinCode proposal client handlers (#707)
* Implement PinCodes proposal cli

* Implement UnpinCodes proposal cli

* Fix descriptions

* Apply suggestions from code review

Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>

Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>
2021-12-23 11:12:45 +01:00

484 lines
16 KiB
Go

package cli
import (
"fmt"
"strconv"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
func ProposalStoreCodeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "wasm-store [wasm file] --title [text] --description [text] --run-as [address]",
Short: "Submit a wasm binary proposal",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
src, err := parseStoreCodeArgs(args[0], clientCtx.FromAddress, cmd.Flags())
if err != nil {
return err
}
runAs, err := cmd.Flags().GetString(flagRunAs)
if err != nil {
return fmt.Errorf("run-as: %s", err)
}
if len(runAs) == 0 {
return errors.New("run-as address is required")
}
proposalTitle, err := cmd.Flags().GetString(cli.FlagTitle)
if err != nil {
return fmt.Errorf("proposal title: %s", err)
}
proposalDescr, err := cmd.Flags().GetString(cli.FlagDescription)
if err != nil {
return fmt.Errorf("proposal description: %s", err)
}
depositArg, err := cmd.Flags().GetString(cli.FlagDeposit)
if err != nil {
return err
}
deposit, err := sdk.ParseCoinsNormalized(depositArg)
if err != nil {
return err
}
content := types.StoreCodeProposal{
Title: proposalTitle,
Description: proposalDescr,
RunAs: runAs,
WASMByteCode: src.WASMByteCode,
InstantiatePermission: src.InstantiatePermission,
}
msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, clientCtx.GetFromAddress())
if err != nil {
return err
}
if err = msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
cmd.Flags().String(flagRunAs, "", "The address that is stored as code creator")
cmd.Flags().String(flagInstantiateByEverybody, "", "Everybody can instantiate a contract from the code, optional")
cmd.Flags().String(flagInstantiateByAddress, "", "Only this address can instantiate a contract instance from the code, optional")
// proposal flags
cmd.Flags().String(cli.FlagTitle, "", "Title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "Description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "Deposit of proposal")
cmd.Flags().String(cli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)")
// type values must match the "ProposalHandler" "routes" in cli
cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade")
return cmd
}
func ProposalInstantiateContractCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "instantiate-contract [code_id_int64] [json_encoded_init_args] --label [text] --title [text] --description [text] --run-as [address] --admin [address,optional] --amount [coins,optional]",
Short: "Submit an instantiate wasm contract proposal",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
src, err := parseInstantiateArgs(args[0], args[1], clientCtx.FromAddress, cmd.Flags())
if err != nil {
return err
}
runAs, err := cmd.Flags().GetString(flagRunAs)
if err != nil {
return fmt.Errorf("run-as: %s", err)
}
if len(runAs) == 0 {
return errors.New("run-as address is required")
}
proposalTitle, err := cmd.Flags().GetString(cli.FlagTitle)
if err != nil {
return fmt.Errorf("proposal title: %s", err)
}
proposalDescr, err := cmd.Flags().GetString(cli.FlagDescription)
if err != nil {
return fmt.Errorf("proposal description: %s", err)
}
depositArg, err := cmd.Flags().GetString(cli.FlagDeposit)
if err != nil {
return err
}
deposit, err := sdk.ParseCoinsNormalized(depositArg)
if err != nil {
return err
}
content := types.InstantiateContractProposal{
Title: proposalTitle,
Description: proposalDescr,
RunAs: runAs,
Admin: src.Admin,
CodeID: src.CodeID,
Label: src.Label,
Msg: src.Msg,
Funds: src.Funds,
}
msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, clientCtx.GetFromAddress())
if err != nil {
return err
}
if err = msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
cmd.Flags().String(flagAmount, "", "Coins to send to the contract during instantiation")
cmd.Flags().String(flagLabel, "", "A human-readable name for this contract in lists")
cmd.Flags().String(flagAdmin, "", "Address of an admin")
cmd.Flags().String(flagRunAs, "", "The address that pays the init funds. It is the creator of the contract and passed to the contract as sender on proposal execution")
// proposal flags
cmd.Flags().String(cli.FlagTitle, "", "Title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "Description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "Deposit of proposal")
cmd.Flags().String(cli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)")
// type values must match the "ProposalHandler" "routes" in cli
cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade")
return cmd
}
func ProposalMigrateContractCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "migrate-contract [contract_addr_bech32] [new_code_id_int64] [json_encoded_migration_args]",
Short: "Submit a migrate wasm contract to a new code version proposal",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
src, err := parseMigrateContractArgs(args, clientCtx)
if err != nil {
return err
}
runAs, err := cmd.Flags().GetString(flagRunAs)
if err != nil {
return fmt.Errorf("run-as: %s", err)
}
if len(runAs) == 0 {
return errors.New("run-as address is required")
}
proposalTitle, err := cmd.Flags().GetString(cli.FlagTitle)
if err != nil {
return fmt.Errorf("proposal title: %s", err)
}
proposalDescr, err := cmd.Flags().GetString(cli.FlagDescription)
if err != nil {
return fmt.Errorf("proposal description: %s", err)
}
depositArg, err := cmd.Flags().GetString(cli.FlagDeposit)
if err != nil {
return err
}
deposit, err := sdk.ParseCoinsNormalized(depositArg)
if err != nil {
return err
}
content := types.MigrateContractProposal{
Title: proposalTitle,
Description: proposalDescr,
Contract: src.Contract,
CodeID: src.CodeID,
Msg: src.Msg,
RunAs: runAs,
}
msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, clientCtx.GetFromAddress())
if err != nil {
return err
}
if err = msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
cmd.Flags().String(flagRunAs, "", "The address that is passed as sender to the contract on proposal execution")
// proposal flags
cmd.Flags().String(cli.FlagTitle, "", "Title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "Description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "Deposit of proposal")
cmd.Flags().String(cli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)")
// type values must match the "ProposalHandler" "routes" in cli
cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade")
return cmd
}
func ProposalUpdateContractAdminCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "set-contract-admin [contract_addr_bech32] [new_admin_addr_bech32]",
Short: "Submit a new admin for a contract proposal",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
src, err := parseUpdateContractAdminArgs(args, clientCtx)
if err != nil {
return err
}
proposalTitle, err := cmd.Flags().GetString(cli.FlagTitle)
if err != nil {
return fmt.Errorf("proposal title: %s", err)
}
proposalDescr, err := cmd.Flags().GetString(cli.FlagDescription)
if err != nil {
return fmt.Errorf("proposal description: %s", err)
}
depositArg, err := cmd.Flags().GetString(cli.FlagDeposit)
if err != nil {
return fmt.Errorf("deposit: %s", err)
}
deposit, err := sdk.ParseCoinsNormalized(depositArg)
if err != nil {
return err
}
content := types.UpdateAdminProposal{
Title: proposalTitle,
Description: proposalDescr,
Contract: src.Contract,
NewAdmin: src.NewAdmin,
}
msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, clientCtx.GetFromAddress())
if err != nil {
return err
}
if err = msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
// proposal flags
cmd.Flags().String(cli.FlagTitle, "", "Title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "Description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "Deposit of proposal")
cmd.Flags().String(cli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)")
// type values must match the "ProposalHandler" "routes" in cli
cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade")
return cmd
}
func ProposalClearContractAdminCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "clear-contract-admin [contract_addr_bech32]",
Short: "Submit a clear admin for a contract to prevent further migrations proposal",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
proposalTitle, err := cmd.Flags().GetString(cli.FlagTitle)
if err != nil {
return fmt.Errorf("proposal title: %s", err)
}
proposalDescr, err := cmd.Flags().GetString(cli.FlagDescription)
if err != nil {
return fmt.Errorf("proposal description: %s", err)
}
depositArg, err := cmd.Flags().GetString(cli.FlagDeposit)
if err != nil {
return fmt.Errorf("deposit: %s", err)
}
deposit, err := sdk.ParseCoinsNormalized(depositArg)
if err != nil {
return err
}
content := types.ClearAdminProposal{
Title: proposalTitle,
Description: proposalDescr,
Contract: args[0],
}
msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, clientCtx.GetFromAddress())
if err != nil {
return err
}
if err = msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
// proposal flags
cmd.Flags().String(cli.FlagTitle, "", "Title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "Description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "Deposit of proposal")
cmd.Flags().String(cli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)")
// type values must match the "ProposalHandler" "routes" in cli
cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade")
return cmd
}
func ProposalPinCodesCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "pin-codes [code-ids]",
Short: "Submit a pin code proposal for pinning a code to cache",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
proposalTitle, err := cmd.Flags().GetString(cli.FlagTitle)
if err != nil {
return fmt.Errorf("proposal title: %s", err)
}
proposalDescr, err := cmd.Flags().GetString(cli.FlagDescription)
if err != nil {
return fmt.Errorf("proposal description: %s", err)
}
depositArg, err := cmd.Flags().GetString(cli.FlagDeposit)
if err != nil {
return fmt.Errorf("deposit: %s", err)
}
deposit, err := sdk.ParseCoinsNormalized(depositArg)
if err != nil {
return err
}
codeIds, err := parsePinCodesArgs(args)
if err != nil {
return err
}
content := types.PinCodesProposal{
Title: proposalTitle,
Description: proposalDescr,
CodeIDs: codeIds,
}
msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, clientCtx.GetFromAddress())
if err != nil {
return err
}
if err = msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
// proposal flags
cmd.Flags().String(cli.FlagTitle, "", "Title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "Description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "Deposit of proposal")
cmd.Flags().String(cli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)")
// type values must match the "ProposalHandler" "routes" in cli
cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade")
return cmd
}
func parsePinCodesArgs(args []string) ([]uint64, error) {
var codeIds []uint64
for _, c := range args {
codeID, err := strconv.ParseUint(c, 10, 64)
if err != nil {
return codeIds, fmt.Errorf("code IDs: %s", err)
}
codeIds = append(codeIds, codeID)
}
return codeIds, nil
}
func ProposalUnpinCodesCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "unpin-codes [code-ids]",
Short: "Submit a unpin code proposal for unpinning a code to cache",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
proposalTitle, err := cmd.Flags().GetString(cli.FlagTitle)
if err != nil {
return fmt.Errorf("proposal title: %s", err)
}
proposalDescr, err := cmd.Flags().GetString(cli.FlagDescription)
if err != nil {
return fmt.Errorf("proposal description: %s", err)
}
depositArg, err := cmd.Flags().GetString(cli.FlagDeposit)
if err != nil {
return fmt.Errorf("deposit: %s", err)
}
deposit, err := sdk.ParseCoinsNormalized(depositArg)
if err != nil {
return err
}
codeIds, err := parsePinCodesArgs(args)
if err != nil {
return err
}
content := types.UnpinCodesProposal{
Title: proposalTitle,
Description: proposalDescr,
CodeIDs: codeIds,
}
msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, clientCtx.GetFromAddress())
if err != nil {
return err
}
if err = msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
// proposal flags
cmd.Flags().String(cli.FlagTitle, "", "Title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "Description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "Deposit of proposal")
cmd.Flags().String(cli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)")
// type values must match the "ProposalHandler" "routes" in cli
cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade")
return cmd
}