From 3e4619a713c4d4699e8de6093eba655b63d8b001 Mon Sep 17 00:00:00 2001 From: jhernandezb Date: Thu, 5 May 2022 13:04:31 -0600 Subject: [PATCH] Add handlers --- x/wasm/client/cli/gov_tx.go | 108 ++++++++++++++++++++++++++++++ x/wasm/client/proposal_handler.go | 1 + x/wasm/client/rest/gov.go | 45 ++++++++++++- 3 files changed, 153 insertions(+), 1 deletion(-) diff --git a/x/wasm/client/cli/gov_tx.go b/x/wasm/client/cli/gov_tx.go index 94150de28e..5e26317a64 100644 --- a/x/wasm/client/cli/gov_tx.go +++ b/x/wasm/client/cli/gov_tx.go @@ -3,10 +3,12 @@ package cli import ( "fmt" "strconv" + "strings" "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/version" "github.com/cosmos/cosmos-sdk/x/gov/client/cli" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/pkg/errors" @@ -614,3 +616,109 @@ func ProposalUnpinCodesCmd() *cobra.Command { cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade") return cmd } + +func parseAccessConfig(config string) (types.AccessConfig, error) { + switch config { + case "nobody": + return types.AllowNobody, nil + case "everybody": + return types.AllowEverybody, nil + default: + address, err := sdk.AccAddressFromBech32(config) + if err != nil { + return types.AccessConfig{}, fmt.Errorf("unable to parse address %s", config) + } + return types.AccessTypeOnlyAddress.With(address), nil + } +} + +func parseCodeUpdateArgs(args []string) ([]types.CodeAccessConfigUpdate, error) { + updates := make([]types.CodeAccessConfigUpdate, len(args)) + for i, c := range args { + // format: code_id,access_config + // access_config: nobody|everybody|address + parts := strings.Split(c, ",") + if len(parts) != 2 { + return nil, fmt.Errorf("invalid ") + } + + codeID, err := strconv.ParseUint(parts[0], 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid code ID: %s", err) + } + + accessConfig, err := parseAccessConfig(parts[1]) + if err != nil { + return nil, err + } + updates[i] = types.CodeAccessConfigUpdate{ + CodeID: codeID, + InstantiatePermission: accessConfig, + } + } + return updates, nil +} +func ProposalUpdateInstantiateConfigCmd() *cobra.Command { + bech32Prefix := sdk.GetConfig().GetBech32AccountAddrPrefix() + cmd := &cobra.Command{ + Use: "update-instantiate-config [code-id,permission]...", + Short: "Submit an update instantiate config proposal.", + Args: cobra.MinimumNArgs(1), + Long: strings.TrimSpace( + fmt.Sprintf(`Submit an update instantiate config proposal for multiple code ids. + +Example: +$ %s tx gov submit-proposal update-instantiate-config 1,nobody 2,everybody 3,%s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm +`, version.AppName, bech32Prefix)), + 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 + } + updates, err := parseCodeUpdateArgs(args) + if err != nil { + return err + } + + content := types.UpdateInstantiateConfigProposal{ + Title: proposalTitle, + Description: proposalDescr, + CodeUpdates: updates, + } + 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 +} diff --git a/x/wasm/client/proposal_handler.go b/x/wasm/client/proposal_handler.go index ad3363ac7a..6d4735180e 100644 --- a/x/wasm/client/proposal_handler.go +++ b/x/wasm/client/proposal_handler.go @@ -18,4 +18,5 @@ var ProposalHandlers = []govclient.ProposalHandler{ govclient.NewProposalHandler(cli.ProposalClearContractAdminCmd, rest.ClearContractAdminProposalHandler), govclient.NewProposalHandler(cli.ProposalPinCodesCmd, rest.PinCodeProposalHandler), govclient.NewProposalHandler(cli.ProposalUnpinCodesCmd, rest.UnpinCodeProposalHandler), + govclient.NewProposalHandler(cli.ProposalUpdateInstantiateConfigCmd, rest.UpdateInstantiateConfigProposalHandler), } diff --git a/x/wasm/client/rest/gov.go b/x/wasm/client/rest/gov.go index 5178b29852..ee4b5b1631 100644 --- a/x/wasm/client/rest/gov.go +++ b/x/wasm/client/rest/gov.go @@ -407,7 +407,50 @@ func (s UnpinCodeJSONReq) GetBaseReq() rest.BaseReq { func UnpinCodeProposalHandler(cliCtx client.Context) govrest.ProposalRESTHandler { return govrest.ProposalRESTHandler{ - SubRoute: "pin_code", + SubRoute: "unpin_code", + Handler: func(w http.ResponseWriter, r *http.Request) { + var req UnpinCodeJSONReq + if !rest.ReadRESTReq(w, r, cliCtx.LegacyAmino, &req) { + return + } + toStdTxResponse(cliCtx, w, req) + }, + } +} + +type UpdateInstantiateConfigProposalJSONReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + + Title string `json:"title" yaml:"title"` + Description string `json:"description" yaml:"description"` + Proposer string `json:"proposer" yaml:"proposer"` + Deposit sdk.Coins `json:"deposit" yaml:"deposit"` + + CodeUpdates []types.CodeAccessConfigUpdate `json:"code_updates" yaml:"code_updates"` + // InstantiatePermission to apply on contract creation, optional + InstantiatePermission *types.AccessConfig `json:"instantiate_permission" yaml:"instantiate_permission"` +} + +func (s UpdateInstantiateConfigProposalJSONReq) Content() govtypes.Content { + return &types.UpdateInstantiateConfigProposal{ + Title: s.Title, + Description: s.Description, + CodeUpdates: s.CodeUpdates, + } +} +func (s UpdateInstantiateConfigProposalJSONReq) GetProposer() string { + return s.Proposer +} +func (s UpdateInstantiateConfigProposalJSONReq) GetDeposit() sdk.Coins { + return s.Deposit +} +func (s UpdateInstantiateConfigProposalJSONReq) GetBaseReq() rest.BaseReq { + return s.BaseReq +} + +func UpdateInstantiateConfigProposalHandler(cliCtx client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: "update_instatiate_config", Handler: func(w http.ResponseWriter, r *http.Request) { var req UnpinCodeJSONReq if !rest.ReadRESTReq(w, r, cliCtx.LegacyAmino, &req) {