func PostProcessResponse(w http.ResponseWriter, cliCtx context.CLIContext, resp interface{}) {
	var result []byte
	if cliCtx.Height < 0 {
		WriteErrorResponse(w, http.StatusInternalServerError, fmt.Errorf("negative height in response").Error())
		return
	}
	switch res := resp.(type) {
	case []byte:
		result = res
	default:
		var err error
		if cliCtx.Indent {
			result, err = cliCtx.Codec.MarshalJSONIndent(resp, "", "  ")
		} else {
			result, err = cliCtx.Codec.MarshalJSON(resp)
		}
		if err != nil {
			WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
			return
		}
	}
	wrappedResp := NewResponseWithHeight(cliCtx.Height, result)
	var (
		output []byte
		err    error
	)
	if cliCtx.Indent {
		output, err = cliCtx.Codec.MarshalJSONIndent(wrappedResp, "", "  ")
	} else {
		output, err = cliCtx.Codec.MarshalJSON(wrappedResp)
	}
	if err != nil {
		WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
		return
	}
	w.Header().Set("Content-Type", "application/json")
	_, _ = w.Write(output)
}
PostProcessResponse performs post processing for a REST response. The result
returned to clients will contain two fields, the height at which the resource
was queried at and the original result.
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
}
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
}
type ErrorResponse struct {
	Code  int    `json:"code,omitempty"`
	Error string `json:"error"`
}
func NewErrorResponse(code int, err string) ErrorResponse {
	return ErrorResponse{Code: code, Error: err}
}
func WriteErrorResponse(w http.ResponseWriter, status int, err string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	_, _ = w.Write(codec.Cdc.MustMarshalJSON(NewErrorResponse(0, err)))
}
func WriteSimulationResponse(w http.ResponseWriter, cdc *codec.Codec, gas uint64) {
	gasEst := GasEstimateResponse{GasEstimate: gas}
	resp, err := cdc.MarshalJSON(gasEst)
	if err != nil {
		WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(resp)
}
func ParseUint64OrReturnBadRequest(w http.ResponseWriter, s string) (n uint64, ok bool) {
	var err error
	n, err = strconv.ParseUint(s, 10, 64)
	if err != nil {
		err := fmt.Errorf("'%s' is not a valid uint64", s)
		WriteErrorResponse(w, http.StatusBadRequest, err.Error())
		return n, false
	}
	return n, true
}
func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEmpty float64) (n float64, ok bool) {
	if len(s) == 0 {
		return defaultIfEmpty, true
	}
	n, err := strconv.ParseFloat(s, 64)
	if err != nil {
		WriteErrorResponse(w, http.StatusBadRequest, err.Error())
		return n, false
	}
	return n, true
}
func ParseQueryHeightOrReturnBadRequest(w http.ResponseWriter, cliCtx context.CLIContext, r *http.Request) (context.CLIContext, bool) {
	heightStr := r.FormValue("height")
	if heightStr != "" {
		height, err := strconv.ParseInt(heightStr, 10, 64)
		if err != nil {
			WriteErrorResponse(w, http.StatusBadRequest, err.Error())
			return cliCtx, false
		}
		if height < 0 {
			WriteErrorResponse(w, http.StatusBadRequest, "height must be equal or greater than zero")
			return cliCtx, false
		}
		if height > 0 {
			cliCtx = cliCtx.WithHeight(height)
		}
	} else {
		cliCtx = cliCtx.WithHeight(0)
	}
	return cliCtx, true
}
func PostProcessResponseBare(w http.ResponseWriter, cliCtx context.CLIContext, body interface{}) {
	var (
		resp []byte
		err  error
	)
	switch b := body.(type) {
	case []byte:
		resp = b
	default:
		if cliCtx.Indent {
			resp, err = cliCtx.Codec.MarshalJSONIndent(body, "", "  ")
		} else {
			resp, err = cliCtx.Codec.MarshalJSON(body)
		}
		if err != nil {
			WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
			return
		}
	}
	w.Header().Set("Content-Type", "application/json")
	_, _ = w.Write(resp)
}