diff --git a/x/committee/client/cli/query.go b/x/committee/client/cli/query.go index 4dfeea25..abcf6865 100644 --- a/x/committee/client/cli/query.go +++ b/x/committee/client/cli/query.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/version" "github.com/kava-labs/kava/x/committee/client/common" "github.com/kava-labs/kava/x/committee/types" @@ -26,13 +27,14 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { } govQueryCmd.AddCommand(client.GetCommands( - //GetCmdQueryCommittee(queryRoute, cdc), + // GetCmdQueryCommittee(queryRoute, cdc), // TODO is this needed? GetCmdQueryCommittees(queryRoute, cdc), + GetCmdQueryProposal(queryRoute, cdc), GetCmdQueryProposals(queryRoute, cdc), - //GetCmdQueryVote(queryRoute, cdc), + GetCmdQueryVotes(queryRoute, cdc), - //GetCmdQueryParams(queryRoute, cdc), + //TODO GetCmdQueryParams(queryRoute, cdc), GetCmdQueryProposer(queryRoute, cdc), GetCmdQueryTally(queryRoute, cdc))...) @@ -42,9 +44,10 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { // GetCmdQueryProposals implements a query proposals command. func GetCmdQueryCommittees(queryRoute string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "committees", - Short: "Query all committees", - Long: "", // TODO + Use: "committees", + Args: cobra.NoArgs, + Short: "Query all committees", + Example: fmt.Sprintf("%s query %s committees", version.ClientName, types.ModuleName), RunE: func(cmd *cobra.Command, args []string) error { cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -55,7 +58,7 @@ func GetCmdQueryCommittees(queryRoute string, cdc *codec.Codec) *cobra.Command { } // Decode and print result - committees := []types.Committee{} + committees := []types.Committee{} // using empty (not nil) slice so json output returns "[]"" instead of "null" when there's no data if err = cdc.UnmarshalJSON(res, &committees); err != nil { return err } @@ -68,19 +71,10 @@ func GetCmdQueryCommittees(queryRoute string, cdc *codec.Codec) *cobra.Command { // GetCmdQueryProposal implements the query proposal command. func GetCmdQueryProposal(queryRoute string, cdc *codec.Codec) *cobra.Command { return &cobra.Command{ - Use: "proposal [proposal-id]", - Args: cobra.ExactArgs(1), - Short: "Query details of a single proposal", - // Long: strings.TrimSpace( - // fmt.Sprintf(`Query details for a proposal. You can find the - // proposal-id by running "%s query gov proposals". - - // Example: - // $ %s query gov proposal 1 - // `, - // version.ClientName, version.ClientName, - // ), - // ), + Use: "proposal [proposal-id]", + Args: cobra.ExactArgs(1), + Short: "Query details of a single proposal", + Example: fmt.Sprintf("%s query %s proposal 2", version.ClientName, types.ModuleName), RunE: func(cmd *cobra.Command, args []string) error { cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -95,7 +89,6 @@ func GetCmdQueryProposal(queryRoute string, cdc *codec.Codec) *cobra.Command { } // Query - //res, err := gcutils.QueryProposalByID(proposalID, cliCtx, queryRoute) res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryProposal), bz) if err != nil { return err @@ -112,20 +105,10 @@ func GetCmdQueryProposal(queryRoute string, cdc *codec.Codec) *cobra.Command { // GetCmdQueryProposals implements a query proposals command. func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "proposals [committee-id]", - Short: "Query proposals by committee.", - Args: cobra.ExactArgs(1), - // Long: strings.TrimSpace( - // fmt.Sprintf(`Query for a all proposals. You can filter the returns with the following flags. - - // Example: - // $ %s query gov proposals --depositor cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk - // $ %s query gov proposals --voter cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk - // $ %s query gov proposals --status (DepositPeriod|VotingPeriod|Passed|Rejected) - // `, - // version.ClientName, version.ClientName, version.ClientName, - // ), - // ), + Use: "proposals [committee-id]", + Short: "Query all proposals for a committee", + Args: cobra.ExactArgs(1), + Example: fmt.Sprintf("%s query %s proposals 1", version.ClientName, types.ModuleName), RunE: func(cmd *cobra.Command, args []string) error { cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -146,7 +129,7 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command { } // Decode and print results - proposals := []types.Proposal{} // using empty (not nil) slice so json returns [] instead of null when there's no data // TODO check + proposals := []types.Proposal{} err = cdc.UnmarshalJSON(res, &proposals) if err != nil { return err @@ -157,91 +140,13 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command { return cmd } -// // Command to Get a Proposal Information -// // GetCmdQueryVote implements the query proposal vote command. -// func GetCmdQueryVote(queryRoute string, cdc *codec.Codec) *cobra.Command { -// return &cobra.Command{ -// Use: "vote [proposal-id] [voter-addr]", -// Args: cobra.ExactArgs(2), -// Short: "Query details of a single vote", -// Long: strings.TrimSpace( -// fmt.Sprintf(`Query details for a single vote on a proposal given its identifier. - -// Example: -// $ %s query gov vote 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk -// `, -// version.ClientName, -// ), -// ), -// RunE: func(cmd *cobra.Command, args []string) error { -// cliCtx := context.NewCLIContext().WithCodec(cdc) - -// // validate that the proposal id is a uint -// proposalID, err := strconv.ParseUint(args[0], 10, 64) -// if err != nil { -// return fmt.Errorf("proposal-id %s not a valid int, please input a valid proposal-id", args[0]) -// } - -// // check to see if the proposal is in the store -// _, err = gcutils.QueryProposalByID(proposalID, cliCtx, queryRoute) -// if err != nil { -// return fmt.Errorf("failed to fetch proposal-id %d: %s", proposalID, err) -// } - -// voterAddr, err := sdk.AccAddressFromBech32(args[1]) -// if err != nil { -// return err -// } - -// params := types.NewQueryVoteParams(proposalID, voterAddr) -// bz, err := cdc.MarshalJSON(params) -// if err != nil { -// return err -// } - -// res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/vote", queryRoute), bz) -// if err != nil { -// return err -// } - -// var vote types.Vote - -// // XXX: Allow the decoding to potentially fail as the vote may have been -// // pruned from state. If so, decoding will fail and so we need to check the -// // Empty() case. Consider updating Vote JSON decoding to not fail when empty. -// _ = cdc.UnmarshalJSON(res, &vote) - -// if vote.Empty() { -// res, err = gcutils.QueryVoteByTxQuery(cliCtx, params) -// if err != nil { -// return err -// } - -// if err := cdc.UnmarshalJSON(res, &vote); err != nil { -// return err -// } -// } - -// return cliCtx.PrintOutput(vote) -// }, -// } -// } - // GetCmdQueryVotes implements the command to query for proposal votes. func GetCmdQueryVotes(queryRoute string, cdc *codec.Codec) *cobra.Command { return &cobra.Command{ - Use: "votes [proposal-id]", - Args: cobra.ExactArgs(1), - Short: "Query votes on a proposal", - // Long: strings.TrimSpace( - // fmt.Sprintf(`Query vote details for a single proposal by its identifier. - - // Example: - // $ %s query gov votes 1 - // `, - // version.ClientName, - // ), - // ), + Use: "votes [proposal-id]", + Args: cobra.ExactArgs(1), + Short: "Query votes on a proposal", + Example: fmt.Sprintf("%s query %s votes 2", version.ClientName, types.ModuleName), RunE: func(cmd *cobra.Command, args []string) error { cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -272,22 +177,13 @@ func GetCmdQueryVotes(queryRoute string, cdc *codec.Codec) *cobra.Command { } } -// GetCmdQueryTally implements the command to query for proposal tally result. func GetCmdQueryTally(queryRoute string, cdc *codec.Codec) *cobra.Command { return &cobra.Command{ - Use: "tally [proposal-id]", - Args: cobra.ExactArgs(1), - Short: "Get the tally of a proposal vote", - // Long: strings.TrimSpace( - // fmt.Sprintf(`Query tally of votes on a proposal. You can find - // the proposal-id by running "%s query gov proposals". - - // Example: - // $ %s query gov tally 1 - // `, - // version.ClientName, version.ClientName, - // ), - // ), + Use: "tally [proposal-id]", + Args: cobra.ExactArgs(1), + Short: "Get the current tally of votes on a proposal", + Long: "Query the current tally of votes on a proposal to see the progress of the voting.", + Example: fmt.Sprintf("%s query %s tally 2", version.ClientName, types.ModuleName), RunE: func(cmd *cobra.Command, args []string) error { cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -309,69 +205,21 @@ func GetCmdQueryTally(queryRoute string, cdc *codec.Codec) *cobra.Command { // Decode and print results var tally bool - cdc.MustUnmarshalJSON(res, &tally) // TODO must or normal, what's the difference on the cli? + if err = cdc.UnmarshalJSON(res, &tally); err != nil { + return err + } return cliCtx.PrintOutput(tally) }, } } -// // GetCmdQueryProposal implements the query proposal command. -// func GetCmdQueryParams(queryRoute string, cdc *codec.Codec) *cobra.Command { -// return &cobra.Command{ -// Use: "params", -// Short: "Query the parameters of the governance process", -// Long: strings.TrimSpace( -// fmt.Sprintf(`Query the all the parameters for the governance process. - -// Example: -// $ %s query gov params -// `, -// version.ClientName, -// ), -// ), -// Args: cobra.NoArgs, -// RunE: func(cmd *cobra.Command, args []string) error { -// cliCtx := context.NewCLIContext().WithCodec(cdc) -// tp, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/params/tallying", queryRoute), nil) -// if err != nil { -// return err -// } -// dp, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/params/deposit", queryRoute), nil) -// if err != nil { -// return err -// } -// vp, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/params/voting", queryRoute), nil) -// if err != nil { -// return err -// } - -// var tallyParams types.TallyParams -// cdc.MustUnmarshalJSON(tp, &tallyParams) -// var depositParams types.DepositParams -// cdc.MustUnmarshalJSON(dp, &depositParams) -// var votingParams types.VotingParams -// cdc.MustUnmarshalJSON(vp, &votingParams) - -// return cliCtx.PrintOutput(types.NewParams(votingParams, tallyParams, depositParams)) -// }, -// } -// } - -// GetCmdQueryProposer implements the query proposer command. func GetCmdQueryProposer(queryRoute string, cdc *codec.Codec) *cobra.Command { return &cobra.Command{ - Use: "proposer [proposal-id]", - Args: cobra.ExactArgs(1), - Short: "Query the proposer of a governance proposal", - // Long: strings.TrimSpace( - // fmt.Sprintf(`Query which address proposed a proposal with a given ID. - - // Example: - // $ %s query gov proposer 1 - // `, - // version.ClientName, - // ), - // ), + Use: "proposer [proposal-id]", + Args: cobra.ExactArgs(1), + Short: "Query the proposer of a governance proposal", + Long: "Query which address proposed a proposal with a given ID.", + Example: fmt.Sprintf("%s query %s proposer 2", version.ClientName, types.ModuleName), RunE: func(cmd *cobra.Command, args []string) error { cliCtx := context.NewCLIContext().WithCodec(cdc) diff --git a/x/committee/client/cli/tx.go b/x/committee/client/cli/tx.go index 321c4e7e..ce6bed5b 100644 --- a/x/committee/client/cli/tx.go +++ b/x/committee/client/cli/tx.go @@ -11,49 +11,17 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/client/utils" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/tendermint/tendermint/crypto" "github.com/kava-labs/kava/x/committee/types" ) -// // Proposal flags -// const ( -// FlagTitle = "title" -// FlagDescription = "description" -// flagProposalType = "type" -// FlagDeposit = "deposit" -// flagVoter = "voter" -// flagDepositor = "depositor" -// flagStatus = "status" -// flagNumLimit = "limit" -// 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. -// var ProposalFlags = []string{ -// FlagTitle, -// FlagDescription, -// flagProposalType, -// FlagDeposit, -// } - -// GetTxCmd returns the transaction commands for this module -// governance ModuleClient is slightly different from other ModuleClients in that -// it contains a slice of "proposal" child commands. These commands are respective -// to proposal type handlers that are implemented in other modules but are mounted -// under the governance CLI (eg. parameter change proposals). -func GetTxCmd(storeKey string, cdc *codec.Codec /*, pcmds []*cobra.Command*/) *cobra.Command { // TODO why is storeKey here? +func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { txCmd := &cobra.Command{ Use: types.ModuleName, Short: "committee governance transactions subcommands", @@ -62,39 +30,27 @@ func GetTxCmd(storeKey string, cdc *codec.Codec /*, pcmds []*cobra.Command*/) *c RunE: client.ValidateCmd, } - cmdSubmitProp := GetCmdSubmitProposal(cdc) - // for _, pcmd := range pcmds { - // cmdSubmitProp.AddCommand(client.PostCommands(pcmd)[0]) - // } - txCmd.AddCommand(client.PostCommands( GetCmdVote(cdc), - cmdSubmitProp, + GetCmdSubmitProposal(cdc), )...) return txCmd } -// // GetCmdSubmitProposal is the root command on which commands for submitting proposals are registered. -// func GetCmdSubmitProposal(cdc *codec.Codec) *cobra.Command { -// cmd := &cobra.Command{ -// Use: "submit-proposal [committee-id]", -// Short: "Submit a governance proposal to a particular committee.", // TODO -// DisableFlagParsing: true, -// SuggestionsMinimumDistance: 2, -// RunE: client.ValidateCmd, -// } - -// return cmd -// } - -// GetCmdSubmitProposal +// GetCmdSubmitProposal returns the command to submit a proposal to a committee func GetCmdSubmitProposal(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "submit-proposal [committee-id] [proposal-file]", - Short: "Submit a governance proposal to a particular committee.", - Long: "", // TODO - Args: cobra.ExactArgs(2), + Short: "Submit a governance proposal to a particular committee", + Long: fmt.Sprintf(`Submit a proposal to a committee so they can vote on it. + +The proposal file must be the json encoded forms of the proposal type you want to submit. +For example: +%s +`, mustGetExampleParameterChangeProposal(cdc)), + Args: cobra.ExactArgs(2), + Example: fmt.Sprintf("%s tx %s submit-proposal 1 your-proposal.json", version.ClientName, types.ModuleName), RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -136,22 +92,14 @@ func GetCmdSubmitProposal(cdc *codec.Codec) *cobra.Command { return cmd } -// GetCmdVote implements creating a new vote command. +// GetCmdVote returns the command to vote on a proposal. func GetCmdVote(cdc *codec.Codec) *cobra.Command { return &cobra.Command{ - Use: "vote [proposal-id]", - Args: cobra.ExactArgs(1), - Short: "Vote for an active proposal", // TODO - // Long: strings.TrimSpace( - // fmt.Sprintf(`Submit a vote for an active proposal. You can - // find the proposal-id by running "%s query gov proposals". - - // Example: - // $ %s tx gov vote 1 yes --from mykey - // `, - // version.ClientName, version.ClientName, - // ), - // ), + Use: "vote [proposal-id]", + Args: cobra.ExactArgs(1), + Short: "Vote for an active proposal", + Long: "Submit a yes vote for the proposal with id [proposal-id].", + Example: fmt.Sprintf("%s tx %s vote 2", version.ClientName, types.ModuleName), RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -177,14 +125,23 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command { } } -// TODO this could replace the whole gov submit-proposal cmd, remove and replace the gov cmd in kvcli main.go -// would want the documentation/examples though +// TODO This could replace the whole gov submit-proposal cmd. It would align how it works with how submiting proposal to committees works. +// Requires removing and replacing the gov cmd in kvcli main.go +// GetGovCmdSubmitProposal returns a command to submit a proposal to the gov module. It is passed to the gov module for use on its command subtree. func GetGovCmdSubmitProposal(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "committee [proposal-file] [deposit]", Short: "Submit a governance proposal to change a committee.", - Long: "This command will work with either CommitteeChange proposals or CommitteeDelete proposals.", // TODO - Args: cobra.ExactArgs(2), + Long: fmt.Sprintf(`Submit a governance proposal to create, alter, or delete a committee. + +The proposal file must be the json encoded form of the proposal type you want to submit. +For example, to create or update a committee: +%s + +and to delete a committee: +%s +`, mustGetExampleCommitteeChangeProposal(cdc), mustGetExampleCommitteeDeleteProposal(cdc)), + Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -193,7 +150,7 @@ func GetGovCmdSubmitProposal(cdc *codec.Codec) *cobra.Command { proposer := cliCtx.GetFromAddress() // Get the deposit - deposit, err := sdk.ParseCoins(args[0]) + deposit, err := sdk.ParseCoins(args[1]) if err != nil { return err } @@ -224,3 +181,49 @@ func GetGovCmdSubmitProposal(cdc *codec.Codec) *cobra.Command { } return cmd } + +// mustGetExampleCommitteeChangeProposal is a helper function to return an example json proposal +func mustGetExampleCommitteeChangeProposal(cdc *codec.Codec) string { + exampleChangeProposal := types.NewCommitteeChangeProposal( + "A Title", + "A description of this proposal.", + types.NewCommittee( + 1, + []sdk.AccAddress{sdk.AccAddress(crypto.AddressHash([]byte("exampleAddres")))}, + []types.Permission{}, // TODO permissions + ), + ) + exampleChangeProposalBz, err := cdc.MarshalJSONIndent(exampleChangeProposal, "", " ") + if err != nil { + panic(err) + } + return string(exampleChangeProposalBz) +} + +// mustGetExampleCommitteeDeleteProposal is a helper function to return an example json proposal +func mustGetExampleCommitteeDeleteProposal(cdc *codec.Codec) string { + exampleDeleteProposal := types.NewCommitteeDeleteProposal( + "A Title", + "A description of this proposal.", + 1, + ) + exampleDeleteProposalBz, err := cdc.MarshalJSONIndent(exampleDeleteProposal, "", " ") + if err != nil { + panic(err) + } + return string(exampleDeleteProposalBz) +} + +// mustGetExampleParameterChangeProposal is a helper function to return an example json proposal +func mustGetExampleParameterChangeProposal(cdc *codec.Codec) string { + exampleParameterChangeProposal := params.NewParameterChangeProposal( + "A Title", + "A description of this proposal.", + []params.ParamChange{params.NewParamChange("cdp", "SurplusAuctionThreshold", "1000000000")}, + ) + exampleParameterChangeProposalBz, err := cdc.MarshalJSONIndent(exampleParameterChangeProposal, "", " ") + if err != nil { + panic(err) + } + return string(exampleParameterChangeProposalBz) +} diff --git a/x/committee/client/rest/query.go b/x/committee/client/rest/query.go index 4ec04e7d..07ec7478 100644 --- a/x/committee/client/rest/query.go +++ b/x/committee/client/rest/query.go @@ -22,8 +22,7 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) { r.HandleFunc(fmt.Sprintf("/%s/proposals/{%s}/proposer", types.ModuleName, RestProposalID), queryProposerHandlerFn(cliCtx)).Methods("GET") r.HandleFunc(fmt.Sprintf("/%s/proposals/{%s}/tally", types.ModuleName, RestProposalID), queryTallyOnProposalHandlerFn(cliCtx)).Methods("GET") r.HandleFunc(fmt.Sprintf("/%s/proposals/{%s}/votes", types.ModuleName, RestProposalID), queryVotesOnProposalHandlerFn(cliCtx)).Methods("GET") - //r.HandleFunc(fmt.Sprintf("/%s/proposals/{%s}/votes/{%s}", types.ModuleName, RestProposalID, RestVoter), queryVoteHandlerFn(cliCtx)).Methods("GET") - //r.HandleFunc(fmt.Sprintf("/%s/parameters/{%s}", types.ModuleName, RestParamsType), queryParamsHandlerFn(cliCtx)).Methods("GET") + // TODO r.HandleFunc(fmt.Sprintf("/%s/parameters/{%s}", types.ModuleName, RestParamsType), queryParamsHandlerFn(cliCtx)).Methods("GET") } // ---------- Committees ---------- @@ -68,7 +67,7 @@ func queryCommitteeHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { if !ok { return } - bz, err := cliCtx.Codec.MarshalJSON(types.NewQueryProposalParams(committeeID)) + bz, err := cliCtx.Codec.MarshalJSON(types.NewQueryCommitteeParams(committeeID)) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return @@ -108,7 +107,7 @@ func queryProposalsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { if !ok { return } - bz, err := cliCtx.Codec.MarshalJSON(types.NewQueryProposalParams(committeeID)) + bz, err := cliCtx.Codec.MarshalJSON(types.NewQueryCommitteeParams(committeeID)) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return @@ -153,7 +152,7 @@ func queryProposalHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { } // Query - res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QueryProposals), bz) + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QueryProposal), bz) if err != nil { rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return @@ -253,88 +252,6 @@ func queryVotesOnProposalHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { } } -// func queryVoteHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { -// return func(w http.ResponseWriter, r *http.Request) { -// vars := mux.Vars(r) -// strProposalID := vars[RestProposalID] -// bechVoterAddr := vars[RestVoter] - -// if len(strProposalID) == 0 { -// err := errors.New("proposalId required but not specified") -// rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) -// return -// } - -// proposalID, ok := rest.ParseUint64OrReturnBadRequest(w, strProposalID) -// if !ok { -// return -// } - -// if len(bechVoterAddr) == 0 { -// err := errors.New("voter address required but not specified") -// rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) -// return -// } - -// voterAddr, err := sdk.AccAddressFromBech32(bechVoterAddr) -// if err != nil { -// rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) -// return -// } - -// cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) -// if !ok { -// return -// } - -// params := types.NewQueryVoteParams(proposalID, voterAddr) - -// bz, err := cliCtx.Codec.MarshalJSON(params) -// if err != nil { -// rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) -// return -// } - -// res, _, err := cliCtx.QueryWithData("custom/gov/vote", bz) -// if err != nil { -// rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) -// return -// } - -// var vote types.Vote -// if err := cliCtx.Codec.UnmarshalJSON(res, &vote); err != nil { -// rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) -// return -// } - -// // For an empty vote, either the proposal does not exist or is inactive in -// // which case the vote would be removed from state and should be queried for -// // directly via a txs query. -// if vote.Empty() { -// bz, err := cliCtx.Codec.MarshalJSON(types.NewQueryProposalParams(proposalID)) -// if err != nil { -// rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) -// return -// } - -// res, _, err = cliCtx.QueryWithData("custom/gov/proposal", bz) -// if err != nil || len(res) == 0 { -// err := fmt.Errorf("proposalID %d does not exist", proposalID) -// rest.WriteErrorResponse(w, http.StatusNotFound, err.Error()) -// return -// } - -// res, err = gcutils.QueryVoteByTxQuery(cliCtx, params) -// if err != nil { -// rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) -// return -// } -// } - -// rest.PostProcessResponse(w, cliCtx, res) -// } -// } - func queryTallyOnProposalHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // Parse the query height @@ -375,6 +292,7 @@ func queryTallyOnProposalHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { // ---------- Params ---------- +// TODO // func queryParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { // return func(w http.ResponseWriter, r *http.Request) { // vars := mux.Vars(r) diff --git a/x/committee/client/rest/rest.go b/x/committee/client/rest/rest.go index 8ff0a7b5..a172adba 100644 --- a/x/committee/client/rest/rest.go +++ b/x/committee/client/rest/rest.go @@ -11,19 +11,10 @@ const ( RestProposalID = "proposal-id" RestCommitteeID = "committee-id" RestVoter = "voter" - //RestProposalStatus = "status" - //RestNumLimit = "limit" ) -// // ProposalRESTHandler defines a REST handler implemented in another module. The -// // sub-route is mounted on the governance REST handler. -// type ProposalRESTHandler struct { -// SubRoute string -// Handler func(http.ResponseWriter, *http.Request) -// } - // RegisterRoutes - Central function to define routes that get registered by the main application -func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router /*, phs []ProposalRESTHandler*/) { +func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { registerQueryRoutes(cliCtx, r) - registerTxRoutes(cliCtx, r /* , phs*/) + registerTxRoutes(cliCtx, r) } diff --git a/x/committee/client/rest/tx.go b/x/committee/client/rest/tx.go index 983e3a55..01e1b7c4 100644 --- a/x/committee/client/rest/tx.go +++ b/x/committee/client/rest/tx.go @@ -16,12 +16,7 @@ import ( "github.com/kava-labs/kava/x/committee/types" ) -func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router /*, phs []ProposalRESTHandler*/) { - // propSubRtr := r.PathPrefix("/gov/proposals").Subrouter() - // for _, ph := range phs { - // propSubRtr.HandleFunc(fmt.Sprintf("/%s", ph.SubRoute), ph.Handler).Methods("POST") - // } - +func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { r.HandleFunc(fmt.Sprintf("/%s/committees/{%s}/proposals", types.ModuleName, RestCommitteeID), postProposalHandlerFn(cliCtx)).Methods("POST") r.HandleFunc(fmt.Sprintf("/%s/proposals/{%s}/votes", types.ModuleName, RestProposalID), postVoteHandlerFn(cliCtx)).Methods("POST") } diff --git a/x/committee/types/gov_proposal.go b/x/committee/types/gov_proposal.go index ed7dfe86..f80b5047 100644 --- a/x/committee/types/gov_proposal.go +++ b/x/committee/types/gov_proposal.go @@ -22,8 +22,14 @@ type CommitteeChangeProposal struct { var _ govtypes.Content = CommitteeChangeProposal{} func init() { + // Gov proposals need to be registered on gov's ModuleCdc so MsgSubmitProposal can be encoded. govtypes.RegisterProposalType(ProposalTypeCommitteeChange) govtypes.RegisterProposalTypeCodec(CommitteeChangeProposal{}, "kava/CommitteeChangeProposal") + // Since these proposals include Permissions that needs to be registered as well (including the interface and concrete types) + govtypes.ModuleCdc.RegisterInterface((*Permission)(nil), nil) + govtypes.RegisterProposalTypeCodec(GodPermission{}, "kava/GodPermission") + // TODO register other permissions here + // TODO write these //RegisterProposalType(ProposalTypeCommitteeChange) //RegisterProposalTypeCodec(CommitteeChangeProposal{}, "kava/CommitteeChangeProposal") diff --git a/x/committee/types/types.go b/x/committee/types/types.go index 391d3b69..37c412fa 100644 --- a/x/committee/types/types.go +++ b/x/committee/types/types.go @@ -24,6 +24,14 @@ type Committee struct { Permissions []Permission `json:"permissions" yaml:"permissions"` } +func NewCommittee(id uint64, members []sdk.AccAddress, permissions []Permission) Committee { + return Committee{ + ID: id, + Members: members, + Permissions: permissions, + } +} + func (c Committee) HasMember(addr sdk.AccAddress) bool { for _, m := range c.Members { if m.Equals(addr) {