Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CreateValidator and EditValidator in REST #5182

Merged
merged 11 commits into from
Oct 16, 2019
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ that error is that the account doesn't exist.
* [\#4843](https://github.com/cosmos/cosmos-sdk/issues/4843) Add RegisterEvidences function in the codec package to register
Tendermint evidence types with a given codec.
* (rest) [\#3867](https://github.com/cosmos/cosmos-sdk/issues/3867) Allow querying for genesis transaction when height query param is set to zero.
* (rest) [\#5113](https://github.com/cosmos/cosmos-sdk/issues/5113) Implement create and edit validator REST endpoints through POST and PUT `/staking/validators/{validatorAddr}` respectively.
* [\#2020](https://github.com/cosmos/cosmos-sdk/issues/2020) New keys export/import command line utilities to export/import private keys in ASCII format
that rely on Keybase's new underlying ExportPrivKey()/ImportPrivKey() API calls.
* [\#3565](https://github.com/cosmos/cosmos-sdk/issues/3565) Implement parameter change proposal support.
Expand Down
12 changes: 11 additions & 1 deletion x/staking/client/rest/swagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package rest

import (
sdk "github.com/cosmos/cosmos-sdk/types"
auth "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)

Expand All @@ -12,6 +12,16 @@ import (
//
//nolint:deadcode,unused
type (
createValidator struct {
auth.StdTx
Msgs []types.MsgCreateValidator `json:"msg"`
}

editValidator struct {
auth.StdTx
Msgs []types.MsgEditValidator `json:"msg"`
}

postDelegation struct {
auth.StdTx
Msgs []types.MsgDelegate `json:"msg"`
Expand Down
121 changes: 121 additions & 0 deletions x/staking/client/rest/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ import (
)

func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) {
r.HandleFunc(
"/staking/validators/{validatorAddr}",
createValidatorHandlerFn(cliCtx),
).Methods("POST")
r.HandleFunc(
"/staking/validators/{validatorAddr}",
editValidatorHandlerFn(cliCtx),
).Methods("PUT")
r.HandleFunc(
"/staking/delegators/{delegatorAddr}/delegations",
postDelegationsHandlerFn(cliCtx),
Expand All @@ -29,6 +37,26 @@ func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) {
}

type (
// CreateValidatorRequest defines the properties of a create validator request's body.
CreateValidatorRequest struct {
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
ValidatorAddress sdk.ValAddress `json:"validator_address" yaml:"validator_address"` // in bech32
Pubkey string `json:"pubkey" yaml:"pubkey"`
Amount sdk.Coin `json:"amount" yaml:"amount"`
Description types.Description `json:"description" yaml:"description"`
Commission types.CommissionRates `json:"commission" yaml:"commission"`
MinSelfDelegation sdk.Int `json:"min_self_delegation" yaml:"min_self_delegation"`
}

// EditValidatorRequest defines the properties of a edit validator request's body.
EditValidatorRequest struct {
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
ValidatorAddress sdk.ValAddress `json:"address" yaml:"address"`
Description types.Description `json:"description" yaml:"description"`
CommissionRate sdk.Dec `json:"commission_rate" yaml:"commission_rate"`
MinSelfDelegation sdk.Int `json:"min_self_delegation" yaml:"min_self_delegation"`
}

// DelegateRequest defines the properties of a delegation request's body.
DelegateRequest struct {
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
Expand All @@ -55,6 +83,99 @@ type (
}
)

// createValidatorHandlerFn implements a create validator handler that is responsible
// for constructing a properly formatted create validator transaction for signing.
//
// @Summary Generate a create validator transaction
// @Description Generate a create validator transaction that is ready for signing
// @Tags staking
// @Accept json
// @Produce json
// @Param validatorAddr path string true "The validator address"
// @Param body body rest.CreateValidatorRequest true "The create validator request payload"
// @Success 200 {object} rest.createValidator "Returns the unsigned transaction"
// @Failure 400 {object} rest.ErrorResponse "Returned if the request is invalid"
// @Failure 401 {object} rest.ErrorResponse "Returned if chain-id required but not present"
// @Failure 402 {object} rest.ErrorResponse "Returned if fees or gas are invalid"
// @Failure 500 {object} rest.ErrorResponse "Returned on server error"
// @Router /staking/validators/{validatorAddr} [post]
func createValidatorHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req CreateValidatorRequest

if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) {
return
}

req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}

pk, err := sdk.GetConsPubKeyBech32(req.Pubkey)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}

msg := types.NewMsgCreateValidator(req.ValidatorAddress, pk, req.Amount, req.Description, req.Commission, req.MinSelfDelegation)
if err := msg.ValidateBasic(); err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}

utils.WriteGenerateStdTxResponse(w, cliCtx, req.BaseReq, []sdk.Msg{msg})
}
}

// editValidatorHandlerFn implements a edit validator handler that is responsible
// for constructing a properly formatted edit validator transaction for signing.
//
// @Summary Generate a edit validator transaction
// @Description Generate a edit validator transaction that is ready for signing
// @Tags staking
// @Accept json
// @Produce json
// @Param validatorAddr path string true "The validator address"
// @Param body body rest.EditValidatorRequest true "The edit validator request payload"
// @Success 200 {object} rest.editValidator "Returns the unsigned transaction"
// @Failure 400 {object} rest.ErrorResponse "Returned if the request is invalid"
// @Failure 401 {object} rest.ErrorResponse "Returned if chain-id required but not present"
// @Failure 402 {object} rest.ErrorResponse "Returned if fees or gas are invalid"
// @Failure 500 {object} rest.ErrorResponse "Returned on server error"
// @Router /staking/validators/{validatorAddr} [put]
func editValidatorHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req EditValidatorRequest

if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) {
return
}

req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}

var newRate *sdk.Dec
if !req.CommissionRate.IsNil() {
newRate = &req.CommissionRate
}
var newMinSelfDelegation *sdk.Int
if !req.MinSelfDelegation.IsZero() {
newMinSelfDelegation = &req.MinSelfDelegation
}

msg := types.NewMsgEditValidator(req.ValidatorAddress, req.Description, newRate, newMinSelfDelegation)
if err := msg.ValidateBasic(); err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}

utils.WriteGenerateStdTxResponse(w, cliCtx, req.BaseReq, []sdk.Msg{msg})
}
}

// postDelegationsHandlerFn implements a delegation handler that is responsible
// for constructing a properly formatted delegation transaction for signing.
//
Expand Down