Merge PR #2462: Add swagger-ui for gov, stake and slashing

This commit is contained in:
HaoyangLiu 2018-10-24 21:19:48 +08:00 committed by Christopher Goes
parent f756b40a01
commit 9ee9e28439
21 changed files with 1411 additions and 213 deletions

View File

@ -128,7 +128,7 @@ FEATURES
* [gaia-lite] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add support for `generate_only=true` query argument to generate offline unsigned transactions * [gaia-lite] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add support for `generate_only=true` query argument to generate offline unsigned transactions
* [gaia-lite] [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) Add /sign endpoint to sign transactions generated with `generate_only=true`. * [gaia-lite] [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) Add /sign endpoint to sign transactions generated with `generate_only=true`.
* [gaia-lite] [\#1954](https://github.com/cosmos/cosmos-sdk/issues/1954) Add /broadcast endpoint to broadcast transactions signed by the /sign endpoint. * [gaia-lite] [\#1954](https://github.com/cosmos/cosmos-sdk/issues/1954) Add /broadcast endpoint to broadcast transactions signed by the /sign endpoint.
* [gaia-lite] [\#2113](https://github.com/cosmos/cosmos-sdk/issues/2113) Rename `/accounts/{address}/send` to `/bank/accounts/{address}/transfers`, rename `/accounts/{address}` to `/auth/accounts/{address}` * [gaia-lite] [\#2113](https://github.com/cosmos/cosmos-sdk/issues/2113) Rename `/accounts/{address}/send` to `/bank/accounts/{address}/transfers`, rename `/accounts/{address}` to `/auth/accounts/{address}`, replace `proposal-id` with `proposalId` in all gov endpoints
* [gaia-lite] [\#2478](https://github.com/cosmos/cosmos-sdk/issues/2478) Add query gov proposal's deposits endpoint * [gaia-lite] [\#2478](https://github.com/cosmos/cosmos-sdk/issues/2478) Add query gov proposal's deposits endpoint
* [gaia-lite] [\#2477](https://github.com/cosmos/cosmos-sdk/issues/2477) Add query validator's outgoing redelegations and unbonding delegations endpoints * [gaia-lite] [\#2477](https://github.com/cosmos/cosmos-sdk/issues/2477) Add query validator's outgoing redelegations and unbonding delegations endpoints

View File

@ -7,6 +7,7 @@ import (
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
keys "github.com/cosmos/cosmos-sdk/crypto/keys" keys "github.com/cosmos/cosmos-sdk/crypto/keys"
keyerror "github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -80,9 +81,16 @@ func DeleteKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
// TODO handle error if key is not available or pass is wrong
err = kb.Delete(name, m.Password) err = kb.Delete(name, m.Password)
if err != nil { if keyerror.IsErrKeyNotFound(err) {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(err.Error()))
return
} else if keyerror.IsErrWrongPassword(err) {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(err.Error()))
return
} else if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return

View File

@ -9,6 +9,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/cli"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
) )
const ( const (
@ -108,12 +109,14 @@ func GetKeyRequestHandler(indent bool) http.HandlerFunc {
} }
info, err := GetKeyInfo(name) info, err := GetKeyInfo(name)
// TODO: check for the error if key actually does not exist, instead of if keyerror.IsErrKeyNotFound(err) {
// assuming this as the reason
if err != nil {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} else if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
} }
keyOutput, err := bechKeyOut(info) keyOutput, err := bechKeyOut(info)

View File

@ -10,6 +10,7 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
) )
func updateKeyCommand() *cobra.Command { func updateKeyCommand() *cobra.Command {
@ -83,12 +84,19 @@ func UpdateKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
getNewpass := func() (string, error) { return m.NewPassword, nil } getNewpass := func() (string, error) { return m.NewPassword, nil }
// TODO check if account exists and if password is correct
err = kb.Update(name, m.OldPassword, getNewpass) err = kb.Update(name, m.OldPassword, getNewpass)
if err != nil { if keyerror.IsErrKeyNotFound(err) {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(err.Error()))
return
} else if keyerror.IsErrWrongPassword(err) {
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} else if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
} }
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")

View File

@ -959,7 +959,7 @@ func doIBCTransfer(t *testing.T, port, seed, name, password string, addr sdk.Acc
} }
func getSigningInfo(t *testing.T, port string, validatorPubKey string) slashing.ValidatorSigningInfo { func getSigningInfo(t *testing.T, port string, validatorPubKey string) slashing.ValidatorSigningInfo {
res, body := Request(t, port, "GET", fmt.Sprintf("/slashing/signing_info/%s", validatorPubKey), nil) res, body := Request(t, port, "GET", fmt.Sprintf("/slashing/validators/%s/signing_info", validatorPubKey), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
var signingInfo slashing.ValidatorSigningInfo var signingInfo slashing.ValidatorSigningInfo

File diff suppressed because it is too large Load Diff

View File

@ -115,19 +115,19 @@ func BlockRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
vars := mux.Vars(r) vars := mux.Vars(r)
height, err := strconv.ParseInt(vars["height"], 10, 64) height, err := strconv.ParseInt(vars["height"], 10, 64)
if err != nil { if err != nil {
w.WriteHeader(400) w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("ERROR: Couldn't parse block height. Assumed format is '/block/{height}'.")) w.Write([]byte("ERROR: Couldn't parse block height. Assumed format is '/block/{height}'."))
return return
} }
chainHeight, err := GetChainHeight(cliCtx) chainHeight, err := GetChainHeight(cliCtx)
if height > chainHeight { if height > chainHeight {
w.WriteHeader(404) w.WriteHeader(http.StatusNotFound)
w.Write([]byte("ERROR: Requested block height is bigger then the chain length.")) w.Write([]byte("ERROR: Requested block height is bigger then the chain length."))
return return
} }
output, err := getBlock(cliCtx, &height) output, err := getBlock(cliCtx, &height)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
@ -140,13 +140,13 @@ func LatestBlockRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
height, err := GetChainHeight(cliCtx) height, err := GetChainHeight(cliCtx)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
output, err := getBlock(cliCtx, &height) output, err := getBlock(cliCtx, &height)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }

View File

@ -69,7 +69,7 @@ func NodeInfoRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
status, err := getNodeStatus(cliCtx) status, err := getNodeStatus(cliCtx)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
@ -84,14 +84,14 @@ func NodeSyncingRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
status, err := getNodeStatus(cliCtx) status, err := getNodeStatus(cliCtx)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
syncing := status.SyncInfo.CatchingUp syncing := status.SyncInfo.CatchingUp
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }

View File

@ -140,21 +140,21 @@ func ValidatorSetRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
height, err := strconv.ParseInt(vars["height"], 10, 64) height, err := strconv.ParseInt(vars["height"], 10, 64)
if err != nil { if err != nil {
w.WriteHeader(400) w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("ERROR: Couldn't parse block height. Assumed format is '/validatorsets/{height}'.")) w.Write([]byte("ERROR: Couldn't parse block height. Assumed format is '/validatorsets/{height}'."))
return return
} }
chainHeight, err := GetChainHeight(cliCtx) chainHeight, err := GetChainHeight(cliCtx)
if height > chainHeight { if height > chainHeight {
w.WriteHeader(404) w.WriteHeader(http.StatusNotFound)
w.Write([]byte("ERROR: Requested block height is bigger then the chain length.")) w.Write([]byte("ERROR: Requested block height is bigger then the chain length."))
return return
} }
output, err := getValidators(cliCtx, &height) output, err := getValidators(cliCtx, &height)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
@ -167,14 +167,14 @@ func LatestValidatorSetRequestHandlerFn(cliCtx context.CLIContext) http.HandlerF
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
height, err := GetChainHeight(cliCtx) height, err := GetChainHeight(cliCtx)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
output, err := getValidators(cliCtx, &height) output, err := getValidators(cliCtx, &height)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }

View File

@ -11,6 +11,7 @@ import (
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
@ -229,9 +230,15 @@ func CompleteAndBroadcastTxREST(w http.ResponseWriter, r *http.Request, cliCtx c
} }
txBytes, err := txBldr.BuildAndSign(baseReq.Name, baseReq.Password, msgs) txBytes, err := txBldr.BuildAndSign(baseReq.Name, baseReq.Password, msgs)
if err != nil { if keyerror.IsErrKeyNotFound(err) {
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
} else if keyerror.IsErrWrongPassword(err) {
WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
return return
} else if err != nil {
WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
} }
res, err := cliCtx.BroadcastTx(txBytes) res, err := cliCtx.BroadcastTx(txBytes)

View File

@ -19,6 +19,7 @@ import (
"github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/tendermint/tendermint/crypto/encoding/amino"
"github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/secp256k1"
dbm "github.com/tendermint/tendermint/libs/db" dbm "github.com/tendermint/tendermint/libs/db"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
) )
var _ Keybase = dbKeybase{} var _ Keybase = dbKeybase{}
@ -217,7 +218,7 @@ func (kb dbKeybase) List() ([]Info, error) {
func (kb dbKeybase) Get(name string) (Info, error) { func (kb dbKeybase) Get(name string) (Info, error) {
bs := kb.db.Get(infoKey(name)) bs := kb.db.Get(infoKey(name))
if len(bs) == 0 { if len(bs) == 0 {
return nil, fmt.Errorf("Key %s not found", name) return nil, keyerror.NewErrKeyNotFound(name)
} }
return readInfo(bs) return readInfo(bs)
} }

View File

@ -0,0 +1,81 @@
package keyerror
import (
"fmt"
)
const (
codeKeyNotFound = 1
codeWrongPassword = 2
)
type keybaseError interface {
error
Code() int
}
type errKeyNotFound struct {
code int
name string
}
func (e errKeyNotFound) Code() int {
return e.code
}
func (e errKeyNotFound) Error() string {
return fmt.Sprintf("Key %s not found", e.name)
}
// NewErrKeyNotFound returns a standardized error reflecting that the specified key doesn't exist
func NewErrKeyNotFound(name string) error {
return errKeyNotFound{
code: codeKeyNotFound,
name: name,
}
}
// IsErrKeyNotFound returns true if the given error is errKeyNotFound
func IsErrKeyNotFound(err error) bool {
if err == nil {
return false
}
if keyErr, ok := err.(keybaseError); ok {
if keyErr.Code() == codeKeyNotFound {
return true
}
}
return false
}
type errWrongPassword struct {
code int
}
func (e errWrongPassword) Code() int {
return e.code
}
func (e errWrongPassword) Error() string {
return fmt.Sprintf("Ciphertext decryption failed")
}
// NewErrWrongPassword returns a standardized error reflecting that the specified password is wrong
func NewErrWrongPassword() error {
return errWrongPassword{
code: codeWrongPassword,
}
}
// IsErrWrongPassword returns true if the given error is errWrongPassword
func IsErrWrongPassword(err error) bool {
if err == nil {
return false
}
if keyErr, ok := err.(keybaseError); ok {
if keyErr.Code() == codeWrongPassword {
return true
}
}
return false
}

View File

@ -12,6 +12,7 @@ import (
"github.com/tendermint/tendermint/crypto/xsalsa20symmetric" "github.com/tendermint/tendermint/crypto/xsalsa20symmetric"
cmn "github.com/tendermint/tendermint/libs/common" cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
) )
const ( const (
@ -144,7 +145,9 @@ func decryptPrivKey(saltBytes []byte, encBytes []byte, passphrase string) (privK
} }
key = crypto.Sha256(key) // Get 32 bytes key = crypto.Sha256(key) // Get 32 bytes
privKeyBytes, err := xsalsa20symmetric.DecryptSymmetric(encBytes, key) privKeyBytes, err := xsalsa20symmetric.DecryptSymmetric(encBytes, key)
if err != nil { if err != nil && err.Error() == "Ciphertext decryption failed" {
return privKey, keyerror.NewErrWrongPassword()
} else if err != nil {
return privKey, err return privKey, err
} }
privKey, err = cryptoAmino.PrivKeyFromBytes(privKeyBytes) privKey, err = cryptoAmino.PrivKeyFromBytes(privKeyBytes)

View File

@ -9,6 +9,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
) )
// SignBody defines the properties of a sign request's body. // SignBody defines the properties of a sign request's body.
@ -47,7 +48,13 @@ func SignTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
} }
signedTx, err := txBldr.SignStdTx(m.LocalAccountName, m.Password, m.Tx, m.AppendSig) signedTx, err := txBldr.SignStdTx(m.LocalAccountName, m.Password, m.Tx, m.AppendSig)
if err != nil { if keyerror.IsErrKeyNotFound(err) {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
} else if keyerror.IsErrWrongPassword(err) {
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
return
} else if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
} }

View File

@ -56,7 +56,7 @@ func SendRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIC
info, err := kb.Get(baseReq.Name) info, err := kb.Get(baseReq.Name)
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return return
} }

View File

@ -17,6 +17,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/x/gov/client"
) )
const ( const (
@ -115,7 +116,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome
cmd.Flags().String(flagTitle, "", "title of proposal") cmd.Flags().String(flagTitle, "", "title of proposal")
cmd.Flags().String(flagDescription, "", "description of proposal") cmd.Flags().String(flagDescription, "", "description of proposal")
cmd.Flags().String(flagProposalType, "", "proposalType of proposal") cmd.Flags().String(flagProposalType, "", "proposalType of proposal, types: text/parameter_change/software_upgrade")
cmd.Flags().String(flagDeposit, "", "deposit of proposal") cmd.Flags().String(flagDeposit, "", "deposit of proposal")
cmd.Flags().String(flagProposal, "", "proposal file path (if this path is given, other proposal flags are ignored)") cmd.Flags().String(flagProposal, "", "proposal file path (if this path is given, other proposal flags are ignored)")
@ -129,7 +130,7 @@ func parseSubmitProposalFlags() (*proposal, error) {
if proposalFile == "" { if proposalFile == "" {
proposal.Title = viper.GetString(flagTitle) proposal.Title = viper.GetString(flagTitle)
proposal.Description = viper.GetString(flagDescription) proposal.Description = viper.GetString(flagDescription)
proposal.Type = viper.GetString(flagProposalType) proposal.Type = client.NormalizeProposalType(viper.GetString(flagProposalType))
proposal.Deposit = viper.GetString(flagDeposit) proposal.Deposit = viper.GetString(flagDeposit)
return proposal, nil return proposal, nil
} }
@ -202,7 +203,7 @@ func GetCmdDeposit(cdc *codec.Codec) *cobra.Command {
func GetCmdVote(cdc *codec.Codec) *cobra.Command { func GetCmdVote(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "vote", Use: "vote",
Short: "Vote for an active proposal, options: Yes/No/NoWithVeto/Abstain", Short: "Vote for an active proposal, options: yes/no/no_with_veto/abstain",
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext(). cliCtx := context.NewCLIContext().
@ -217,7 +218,7 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command {
proposalID := viper.GetInt64(flagProposalID) proposalID := viper.GetInt64(flagProposalID)
option := viper.GetString(flagOption) option := viper.GetString(flagOption)
byteVoteOption, err := gov.VoteOptionFromString(option) byteVoteOption, err := gov.VoteOptionFromString(client.NormalizeVoteOption(option))
if err != nil { if err != nil {
return err return err
} }
@ -243,7 +244,7 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command {
} }
cmd.Flags().String(flagProposalID, "", "proposalID of proposal voting on") cmd.Flags().String(flagProposalID, "", "proposalID of proposal voting on")
cmd.Flags().String(flagOption, "", "vote option {Yes, No, NoWithVeto, Abstain}") cmd.Flags().String(flagOption, "", "vote option {yes, no, no_with_veto, abstain}")
return cmd return cmd
} }
@ -313,7 +314,7 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
} }
if len(strProposalStatus) != 0 { if len(strProposalStatus) != 0 {
proposalStatus, err := gov.ProposalStatusFromString(strProposalStatus) proposalStatus, err := gov.ProposalStatusFromString(client.NormalizeProposalStatus(strProposalStatus))
if err != nil { if err != nil {
return err return err
} }
@ -354,7 +355,7 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd.Flags().String(flagLatestProposalIDs, "", "(optional) limit to latest [number] proposals. Defaults to all proposals") cmd.Flags().String(flagLatestProposalIDs, "", "(optional) limit to latest [number] proposals. Defaults to all proposals")
cmd.Flags().String(flagDepositer, "", "(optional) filter by proposals deposited on by depositer") cmd.Flags().String(flagDepositer, "", "(optional) filter by proposals deposited on by depositer")
cmd.Flags().String(flagVoter, "", "(optional) filter by proposals voted on by voted") cmd.Flags().String(flagVoter, "", "(optional) filter by proposals voted on by voted")
cmd.Flags().String(flagStatus, "", "(optional) filter proposals by proposal status") cmd.Flags().String(flagStatus, "", "(optional) filter proposals by proposal status, status: deposit_period/voting_period/passed/rejected")
return cmd return cmd
} }

View File

@ -12,12 +12,13 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/cosmos/cosmos-sdk/x/gov/client"
) )
// REST Variable names // REST Variable names
// nolint // nolint
const ( const (
RestProposalID = "proposal-id" RestProposalID = "proposalId"
RestDepositer = "depositer" RestDepositer = "depositer"
RestVoter = "voter" RestVoter = "voter"
RestProposalStatus = "status" RestProposalStatus = "status"
@ -43,7 +44,7 @@ type postProposalReq struct {
BaseReq utils.BaseReq `json:"base_req"` BaseReq utils.BaseReq `json:"base_req"`
Title string `json:"title"` // Title of the proposal Title string `json:"title"` // Title of the proposal
Description string `json:"description"` // Description of the proposal Description string `json:"description"` // Description of the proposal
ProposalType gov.ProposalKind `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} ProposalType string `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
Proposer sdk.AccAddress `json:"proposer"` // Address of the proposer Proposer sdk.AccAddress `json:"proposer"` // Address of the proposer
InitialDeposit sdk.Coins `json:"initial_deposit"` // Coins to add to the proposal's deposit InitialDeposit sdk.Coins `json:"initial_deposit"` // Coins to add to the proposal's deposit
} }
@ -57,7 +58,7 @@ type depositReq struct {
type voteReq struct { type voteReq struct {
BaseReq utils.BaseReq `json:"base_req"` BaseReq utils.BaseReq `json:"base_req"`
Voter sdk.AccAddress `json:"voter"` // address of the voter Voter sdk.AccAddress `json:"voter"` // address of the voter
Option gov.VoteOption `json:"option"` // option from OptionSet chosen by the voter Option string `json:"option"` // option from OptionSet chosen by the voter
} }
func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc { func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
@ -65,6 +66,7 @@ func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
var req postProposalReq var req postProposalReq
err := utils.ReadRESTReq(w, r, cdc, &req) err := utils.ReadRESTReq(w, r, cdc, &req)
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return return
} }
@ -73,8 +75,14 @@ func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
return return
} }
proposalType, err := gov.ProposalTypeFromString(client.NormalizeProposalType(req.ProposalType))
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
// create the message // create the message
msg := gov.NewMsgSubmitProposal(req.Title, req.Description, req.ProposalType, req.Proposer, req.InitialDeposit) msg := gov.NewMsgSubmitProposal(req.Title, req.Description, proposalType, req.Proposer, req.InitialDeposit)
err = msg.ValidateBasic() err = msg.ValidateBasic()
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
@ -151,8 +159,14 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc
return return
} }
voteOption, err := gov.VoteOptionFromString(client.NormalizeVoteOption(req.Option))
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
// create the message // create the message
msg := gov.NewMsgVote(req.Voter, proposalID, req.Option) msg := gov.NewMsgVote(req.Voter, proposalID, voteOption)
err = msg.ValidateBasic() err = msg.ValidateBasic()
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
@ -391,6 +405,7 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
} }
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
} }
} }
@ -424,7 +439,7 @@ func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext)
} }
if len(strProposalStatus) != 0 { if len(strProposalStatus) != 0 {
proposalStatus, err := gov.ProposalStatusFromString(strProposalStatus) proposalStatus, err := gov.ProposalStatusFromString(client.NormalizeProposalStatus(strProposalStatus))
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return return
@ -450,6 +465,7 @@ func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext)
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
} }
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
} }
} }
@ -489,6 +505,7 @@ func queryTallyOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent) utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
} }
} }

45
x/gov/client/utils.go Normal file
View File

@ -0,0 +1,45 @@
package client
// NormalizeVoteOption - normalize user specified vote option
func NormalizeVoteOption(option string) string {
switch option {
case "Yes", "yes":
return "Yes"
case "Abstain", "abstain":
return "Abstain"
case "No", "no":
return "No"
case "NoWithVeto", "no_with_veto":
return "NoWithVeto"
}
return ""
}
//NormalizeProposalType - normalize user specified proposal type
func NormalizeProposalType(proposalType string) string {
switch proposalType {
case "Text", "text":
return "Text"
case "ParameterChange", "parameter_change":
return "ParameterChange"
case "SoftwareUpgrade", "software_upgrade":
return "SoftwareUpgrade"
}
return ""
}
//NormalizeProposalStatus - normalize user specified proposal status
func NormalizeProposalStatus(status string) string {
switch status {
case "DepositPeriod", "deposit_period":
return "DepositPeriod"
case "VotingPeriod", "voting_period":
return "VotingPeriod"
case "Passed", "passed":
return "Passed"
case "Rejected", "rejected":
return "Rejected"
}
return ""
}

View File

@ -4,16 +4,16 @@ import (
"net/http" "net/http"
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/slashing" "github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/cosmos/cosmos-sdk/client/utils"
) )
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) { func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) {
r.HandleFunc( r.HandleFunc(
"/slashing/signing_info/{validator}", "/slashing/validators/{validatorPubKey}/signing_info",
signingInfoHandlerFn(cliCtx, "slashing", cdc), signingInfoHandlerFn(cliCtx, "slashing", cdc),
).Methods("GET") ).Methods("GET")
} }
@ -24,7 +24,7 @@ func signingInfoHandlerFn(cliCtx context.CLIContext, storeName string, cdc *code
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
pk, err := sdk.GetConsPubKeyBech32(vars["validator"]) pk, err := sdk.GetConsPubKeyBech32(vars["validatorPubKey"])
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return return
@ -38,6 +38,11 @@ func signingInfoHandlerFn(cliCtx context.CLIContext, storeName string, cdc *code
return return
} }
if len(res) == 0 {
w.WriteHeader(http.StatusNoContent)
return
}
var signingInfo slashing.ValidatorSigningInfo var signingInfo slashing.ValidatorSigningInfo
err = cdc.UnmarshalBinary(res, &signingInfo) err = cdc.UnmarshalBinary(res, &signingInfo)
@ -46,13 +51,6 @@ func signingInfoHandlerFn(cliCtx context.CLIContext, storeName string, cdc *code
return return
} }
output, err := cdc.MarshalJSON(signingInfo) utils.PostProcessResponse(w, cdc, signingInfo, cliCtx.Indent)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(output)
} }
} }

View File

@ -16,7 +16,7 @@ import (
func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec, kb keys.Keybase) { func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec, kb keys.Keybase) {
r.HandleFunc( r.HandleFunc(
"/slashing/unjail", "/slashing/validators/{validatorAddr}/unjail",
unjailRequestHandlerFn(cdc, kb, cliCtx), unjailRequestHandlerFn(cdc, kb, cliCtx),
).Methods("POST") ).Methods("POST")
} }
@ -24,11 +24,14 @@ func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec
// Unjail TX body // Unjail TX body
type UnjailReq struct { type UnjailReq struct {
BaseReq utils.BaseReq `json:"base_req"` BaseReq utils.BaseReq `json:"base_req"`
ValidatorAddr string `json:"validator_addr"`
} }
func unjailRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIContext) http.HandlerFunc { func unjailRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
bech32validator := vars["validatorAddr"]
var req UnjailReq var req UnjailReq
err := utils.ReadRESTReq(w, r, cdc, &req) err := utils.ReadRESTReq(w, r, cdc, &req)
if err != nil { if err != nil {
@ -46,7 +49,7 @@ func unjailRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CL
return return
} }
valAddr, err := sdk.ValAddressFromBech32(req.ValidatorAddr) valAddr, err := sdk.ValAddressFromBech32(bech32validator)
if err != nil { if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return

View File

@ -262,12 +262,6 @@ func delegationsRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx conte
results[i] = res results[i] = res
} }
res, err := codec.MarshalJSONIndent(cdc, results[:]) utils.PostProcessResponse(w, cdc, results, cliCtx.Indent)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
} }
} }