cosmos-sdk/x/gov/client/rest/tx.go

248 lines
6.8 KiB
Go

package rest
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
"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/types/rest"
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
gcutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
func registerTxHandlers(clientCtx client.Context, 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")
}
r.HandleFunc("/gov/proposals", newPostProposalHandlerFn(clientCtx)).Methods("POST")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), newDepositHandlerFn(clientCtx)).Methods("POST")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), newVoteHandlerFn(clientCtx)).Methods("POST")
}
func newPostProposalHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req PostProposalReq
if !rest.ReadRESTReq(w, r, clientCtx.Codec, &req) {
return
}
req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}
proposalType := gcutils.NormalizeProposalType(req.ProposalType)
content := types.ContentFromProposalType(req.Title, req.Description, proposalType)
msg, err := types.NewMsgSubmitProposal(content, req.InitialDeposit, req.Proposer)
if rest.CheckBadRequestError(w, err) {
return
}
if rest.CheckBadRequestError(w, msg.ValidateBasic()) {
return
}
tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg)
}
}
func newDepositHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
strProposalID := vars[RestProposalID]
if len(strProposalID) == 0 {
rest.WriteErrorResponse(w, http.StatusBadRequest, "proposalId required but not specified")
return
}
proposalID, ok := rest.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
var req DepositReq
if !rest.ReadRESTReq(w, r, clientCtx.Codec, &req) {
return
}
req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}
// create the message
msg := types.NewMsgDeposit(req.Depositor, proposalID, req.Amount)
if rest.CheckBadRequestError(w, msg.ValidateBasic()) {
return
}
tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg)
}
}
func newVoteHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
strProposalID := vars[RestProposalID]
if len(strProposalID) == 0 {
rest.WriteErrorResponse(w, http.StatusBadRequest, "proposalId required but not specified")
return
}
proposalID, ok := rest.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
var req VoteReq
if !rest.ReadRESTReq(w, r, clientCtx.Codec, &req) {
return
}
req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}
voteOption, err := types.VoteOptionFromString(gcutils.NormalizeVoteOption(req.Option))
if rest.CheckBadRequestError(w, err) {
return
}
// create the message
msg := types.NewMsgVote(req.Voter, proposalID, voteOption)
if rest.CheckBadRequestError(w, msg.ValidateBasic()) {
return
}
tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg)
}
}
// ---------------------------------------------------------------------------
// Deprecated
//
// TODO: Remove once client-side Protobuf migration has been completed.
// ---------------------------------------------------------------------------
func registerTxRoutes(clientCtx client.Context, 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")
}
r.HandleFunc("/gov/proposals", postProposalHandlerFn(clientCtx)).Methods("POST")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), depositHandlerFn(clientCtx)).Methods("POST")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), voteHandlerFn(clientCtx)).Methods("POST")
}
func postProposalHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req PostProposalReq
if !rest.ReadRESTReq(w, r, clientCtx.Codec, &req) {
return
}
req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}
proposalType := gcutils.NormalizeProposalType(req.ProposalType)
content := types.ContentFromProposalType(req.Title, req.Description, proposalType)
msg, err := types.NewMsgSubmitProposal(content, req.InitialDeposit, req.Proposer)
if rest.CheckBadRequestError(w, err) {
return
}
if rest.CheckBadRequestError(w, msg.ValidateBasic()) {
return
}
authclient.WriteGenerateStdTxResponse(w, clientCtx, req.BaseReq, []sdk.Msg{msg})
}
}
func depositHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
strProposalID := vars[RestProposalID]
if len(strProposalID) == 0 {
rest.WriteErrorResponse(w, http.StatusBadRequest, "proposalId required but not specified")
return
}
proposalID, ok := rest.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
var req DepositReq
if !rest.ReadRESTReq(w, r, clientCtx.Codec, &req) {
return
}
req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}
// create the message
msg := types.NewMsgDeposit(req.Depositor, proposalID, req.Amount)
if rest.CheckBadRequestError(w, msg.ValidateBasic()) {
return
}
authclient.WriteGenerateStdTxResponse(w, clientCtx, req.BaseReq, []sdk.Msg{msg})
}
}
func voteHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
strProposalID := vars[RestProposalID]
if len(strProposalID) == 0 {
rest.WriteErrorResponse(w, http.StatusBadRequest, "proposalId required but not specified")
return
}
proposalID, ok := rest.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
var req VoteReq
if !rest.ReadRESTReq(w, r, clientCtx.Codec, &req) {
return
}
req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}
voteOption, err := types.VoteOptionFromString(gcutils.NormalizeVoteOption(req.Option))
if rest.CheckBadRequestError(w, err) {
return
}
// create the message
msg := types.NewMsgVote(req.Voter, proposalID, voteOption)
if rest.CheckBadRequestError(w, msg.ValidateBasic()) {
return
}
authclient.WriteGenerateStdTxResponse(w, clientCtx, req.BaseReq, []sdk.Msg{msg})
}
}