Merge PR #4505: Support height queries in REST client

This commit is contained in:
colin axner
2019-06-07 09:02:07 -04:00
committed by Alexander Bezobchuk
parent 3862b74899
commit c777fb9108
12 changed files with 238 additions and 0 deletions
@@ -0,0 +1 @@
#4501 Support height queriers in rest client
+6
View File
@@ -212,6 +212,12 @@ func (ctx CLIContext) WithNodeURI(nodeURI string) CLIContext {
return ctx
}
// WithHeight returns a copy of the context with an updated height.
func (ctx CLIContext) WithHeight(height int64) CLIContext {
ctx.Height = height
return ctx
}
// WithClient returns a copy of the context with an updated RPC client
// instance.
func (ctx CLIContext) WithClient(client rpcclient.Client) CLIContext {
+10
View File
@@ -156,6 +156,11 @@ func QueryTxsByTagsRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
if len(r.Form) == 0 {
rest.PostProcessResponse(w, cliCtx, txs)
return
@@ -184,6 +189,11 @@ func QueryTxRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
vars := mux.Vars(r)
hashHexStr := vars["hash"]
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
output, err := queryTx(cliCtx, hashHexStr)
if err != nil {
if strings.Contains(err.Error(), hashHexStr) {
+19
View File
@@ -197,6 +197,25 @@ func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEm
return n, true
}
// ParseQueryHeightOrReturnBadRequest sets the height to execute a query if set by the http request.
// It returns false if there was an error parsing the height.
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 {
cliCtx = cliCtx.WithHeight(height)
}
}
return cliCtx, true
}
// PostProcessResponse performs post processing for a REST response.
func PostProcessResponse(w http.ResponseWriter, cliCtx context.CLIContext, response interface{}) {
var output []byte
+37
View File
@@ -8,6 +8,7 @@ import (
"net/http/httptest"
"testing"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/types"
@@ -101,6 +102,42 @@ func TestParseHTTPArgs(t *testing.T) {
}
}
func TestParseQueryHeight(t *testing.T) {
var emptyHeight int64
height := int64(1256756)
req0 := mustNewRequest(t, "", "/", nil)
req1 := mustNewRequest(t, "", "/?height=1256756", nil)
req2 := mustNewRequest(t, "", "/?height=456yui4567", nil)
req3 := mustNewRequest(t, "", "/?height=-1", nil)
tests := []struct {
name string
req *http.Request
w http.ResponseWriter
cliCtx context.CLIContext
expectedHeight int64
expectedOk bool
}{
{"no height", req0, httptest.NewRecorder(), context.CLIContext{}, emptyHeight, true},
{"height", req1, httptest.NewRecorder(), context.CLIContext{}, height, true},
{"invalid height", req2, httptest.NewRecorder(), context.CLIContext{}, emptyHeight, false},
{"negative height", req3, httptest.NewRecorder(), context.CLIContext{}, emptyHeight, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cliCtx, ok := ParseQueryHeightOrReturnBadRequest(tt.w, tt.cliCtx, tt.req)
if tt.expectedOk {
require.True(t, ok)
require.Equal(t, tt.expectedHeight, cliCtx.Height)
} else {
require.False(t, ok)
require.Empty(t, tt.expectedHeight, cliCtx.Height)
}
})
}
}
func mustNewRequest(t *testing.T, method, url string, body io.Reader) *http.Request {
req, err := http.NewRequest(method, url, body)
require.NoError(t, err)
+10
View File
@@ -40,6 +40,11 @@ func QueryAccountRequestHandlerFn(
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := cliCtx.QueryStore(types.AddressStoreKey(addr), storeName)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
@@ -79,6 +84,11 @@ func QueryBalancesRequestHandlerFn(
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := cliCtx.QueryStore(types.AddressStoreKey(addr), storeName)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
+40
View File
@@ -68,6 +68,11 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute st
// HTTP request handler to query the total rewards balance from all delegations
func delegatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
// query for rewards from a particular delegator
res, ok := checkResponseQueryDelegatorTotalRewards(w, cliCtx, queryRoute, mux.Vars(r)["delegatorAddr"])
if !ok {
@@ -81,6 +86,11 @@ func delegatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) htt
// HTTP request handler to query a delegation rewards
func delegationRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
// query for rewards from a particular delegation
res, ok := checkResponseQueryDelegationRewards(w, cliCtx, queryRoute, mux.Vars(r)["delegatorAddr"], mux.Vars(r)["validatorAddr"])
if !ok {
@@ -99,6 +109,11 @@ func delegatorWithdrawalAddrHandlerFn(cliCtx context.CLIContext, queryRoute stri
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
bz := cliCtx.Codec.MustMarshalJSON(types.NewQueryDelegatorWithdrawAddrParams(delegatorAddr))
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/withdraw_addr", queryRoute), bz)
if err != nil {
@@ -137,6 +152,11 @@ func validatorInfoHandlerFn(cliCtx context.CLIContext, queryRoute string) http.H
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
// query commission
commissionRes, err := common.QueryValidatorCommission(cliCtx, queryRoute, validatorAddr)
if err != nil {
@@ -172,6 +192,11 @@ func validatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) htt
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
delAddr := sdk.AccAddress(validatorAddr).String()
res, ok := checkResponseQueryDelegationRewards(w, cliCtx, queryRoute, delAddr, valAddr)
if !ok {
@@ -185,6 +210,11 @@ func validatorRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) htt
// HTTP request handler to query the distribution params values
func paramsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params, err := common.QueryParams(cliCtx, queryRoute)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
@@ -197,6 +227,11 @@ func paramsHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerF
func communityPoolHandler(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/community_pool", queryRoute), nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
@@ -221,6 +256,11 @@ func outstandingRewardsHandlerFn(cliCtx context.CLIContext, queryRoute string) h
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
bin := cliCtx.Codec.MustMarshalJSON(types.NewQueryValidatorOutstandingRewardsParams(validatorAddr))
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/validator_outstanding_rewards", queryRoute), bin)
if err != nil {
+45
View File
@@ -196,6 +196,11 @@ func queryParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
vars := mux.Vars(r)
paramType := vars[RestParamsType]
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/gov/%s/%s", types.QueryParams, paramType), nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusNotFound, err.Error())
@@ -222,6 +227,11 @@ func queryProposalHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryProposalParams(proposalID)
bz, err := cliCtx.Codec.MarshalJSON(params)
@@ -250,6 +260,11 @@ func queryDepositsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryProposalParams(proposalID)
bz, err := cliCtx.Codec.MarshalJSON(params)
@@ -298,6 +313,11 @@ func queryProposerHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := gcutils.QueryProposerByTxQuery(cliCtx, proposalID)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
@@ -337,6 +357,11 @@ func queryDepositHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryDepositParams(proposalID, depositorAddr)
bz, err := cliCtx.Codec.MarshalJSON(params)
@@ -414,6 +439,11 @@ func queryVoteHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryVoteParams(proposalID, voterAddr)
bz, err := cliCtx.Codec.MarshalJSON(params)
@@ -479,6 +509,11 @@ func queryVotesOnProposalHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryProposalParams(proposalID)
bz, err := cliCtx.Codec.MarshalJSON(params)
@@ -561,6 +596,11 @@ func queryProposalsWithParameterFn(cliCtx context.CLIContext) http.HandlerFunc {
params.Limit = numLimit
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
@@ -594,6 +634,11 @@ func queryTallyOnProposalHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok = rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryProposalParams(proposalID)
bz, err := cliCtx.Codec.MarshalJSON(params)
+15
View File
@@ -32,6 +32,11 @@ func queryParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryParameters)
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := cliCtx.QueryWithData(route, nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
@@ -46,6 +51,11 @@ func queryInflationHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryInflation)
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := cliCtx.QueryWithData(route, nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
@@ -60,6 +70,11 @@ func queryAnnualProvisionsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc
return func(w http.ResponseWriter, r *http.Request) {
route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryAnnualProvisions)
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := cliCtx.QueryWithData(route, nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
+15
View File
@@ -39,6 +39,11 @@ func signingInfoHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQuerySigningInfoParams(sdk.ConsAddress(pk.Address()))
bz, err := cliCtx.Codec.MarshalJSON(params)
@@ -67,6 +72,11 @@ func signingInfoHandlerListFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQuerySigningInfosParams(page, limit)
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
@@ -87,6 +97,11 @@ func signingInfoHandlerListFn(cliCtx context.CLIContext) http.HandlerFunc {
func queryParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
route := fmt.Sprintf("custom/%s/parameters", types.QuerierRoute)
res, err := cliCtx.QueryWithData(route, nil)
+25
View File
@@ -123,6 +123,11 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
typesQuery := r.URL.Query().Get("type")
trimmedQuery := strings.TrimSpace(typesQuery)
if len(trimmedQuery) != 0 {
@@ -180,6 +185,11 @@ func redelegationsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var params types.QueryRedelegationParams
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
bechDelegatorAddr := r.URL.Query().Get("delegator")
bechSrcValidatorAddr := r.URL.Query().Get("validator_from")
bechDstValidatorAddr := r.URL.Query().Get("validator_to")
@@ -251,6 +261,11 @@ func validatorsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
status := r.FormValue("status")
if status == "" {
status = sdk.BondStatusBonded
@@ -291,6 +306,11 @@ func validatorUnbondingDelegationsHandlerFn(cliCtx context.CLIContext) http.Hand
// HTTP request handler to query the pool information
func poolHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := cliCtx.QueryWithData("custom/staking/pool", nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
@@ -304,6 +324,11 @@ func poolHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
// HTTP request handler to query the staking params values
func paramsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, err := cliCtx.QueryWithData("custom/staking/parameters", nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
+15
View File
@@ -49,6 +49,11 @@ func queryBonds(cliCtx context.CLIContext, endpoint string) http.HandlerFunc {
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryBondsParams(delegatorAddr, validatorAddr)
bz, err := cliCtx.Codec.MarshalJSON(params)
@@ -77,6 +82,11 @@ func queryDelegator(cliCtx context.CLIContext, endpoint string) http.HandlerFunc
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryDelegatorParams(delegatorAddr)
bz, err := cliCtx.Codec.MarshalJSON(params)
@@ -105,6 +115,11 @@ func queryValidator(cliCtx context.CLIContext, endpoint string) http.HandlerFunc
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryValidatorParams(validatorAddr)
bz, err := cliCtx.Codec.MarshalJSON(params)