func ReadRESTReq(w http.ResponseWriter, r *http.Request, cdc *codec.Codec, req interface{}) bool {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		WriteErrorResponse(w, http.StatusBadRequest, err.Error())
		return false
	}
	err = cdc.UnmarshalJSON(body, req)
	if err != nil {
		WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to decode JSON payload: %s", err))
		return false
	}
	return true
}
ReadRESTReq reads and unmarshals a Request's body to the the BaseReq stuct.
Writes an error response to ResponseWriter and returns true if errors occurred.
package types
import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"github.com/tendermint/tendermint/types"
	"github.com/cosmos/cosmos-sdk/client/context"
	"github.com/cosmos/cosmos-sdk/codec"
)
const (
	DefaultPage    = 1
	DefaultLimit   = 30              
	TxMinHeightKey = "tx.minheight"  
	TxMaxHeightKey = "tx.maxheight"  
)
type ResponseWithHeight struct {
	Height int64           `json:"height"`
	Result json.RawMessage `json:"result"`
}
func NewResponseWithHeight(height int64, result json.RawMessage) ResponseWithHeight {
	return ResponseWithHeight{
		Height: height,
		Result: result,
	}
}
type GasEstimateResponse struct {
	GasEstimate uint64 `json:"gas_estimate"`
}
type BaseReq struct {
	From          string   `json:"from"`
	Memo          string   `json:"memo"`
	ChainID       string   `json:"chain_id"`
	AccountNumber uint64   `json:"account_number"`
	Sequence      uint64   `json:"sequence"`
	Fees          Coins    `json:"fees"`
	GasPrices     DecCoins `json:"gas_prices"`
	Gas           string   `json:"gas"`
	GasAdjustment string   `json:"gas_adjustment"`
	Simulate      bool     `json:"simulate"`
	Payer         string   `json:"payer"`
}
func NewBaseReq(
	from, memo, chainID string, gas, gasAdjustment string, accNumber, seq uint64,
	fees Coins, gasPrices DecCoins, simulate bool, payer string,
) BaseReq {
	return BaseReq{
		From:          strings.TrimSpace(from),
		Memo:          strings.TrimSpace(memo),
		ChainID:       strings.TrimSpace(chainID),
		Fees:          fees,
		GasPrices:     gasPrices,
		Gas:           strings.TrimSpace(gas),
		GasAdjustment: strings.TrimSpace(gasAdjustment),
		AccountNumber: accNumber,
		Sequence:      seq,
		Simulate:      simulate,
		Payer:         payer,
	}
}
func (br BaseReq) Sanitize() BaseReq {
	return NewBaseReq(
		br.From, br.Memo, br.ChainID, br.Gas, br.GasAdjustment, br.AccountNumber,
		br.Sequence, br.Fees, br.GasPrices, br.Simulate, br.Payer,
	)
}
func (br BaseReq) ValidateBasic(w http.ResponseWriter) bool {
	if !br.Simulate {
		switch {
		case len(br.ChainID) == 0:
			WriteErrorResponse(w, http.StatusUnauthorized, "chain-id required but not specified")
			return false
		case !br.Fees.IsZero() && !br.GasPrices.IsZero():
			WriteErrorResponse(w, http.StatusBadRequest, "cannot provide both fees and gas prices")
			return false
		case !br.Fees.IsValid() && !br.GasPrices.IsValid():
			WriteErrorResponse(w, http.StatusPaymentRequired, "invalid fees or gas prices provided")
			return false
		}
	}
	if _, err := AccAddressFromBech32(br.From); err != nil || len(br.From) == 0 {
		WriteErrorResponse(w, http.StatusUnauthorized, fmt.Sprintf("invalid from address: %s", br.From))
		return false
	}
	return true
}