diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 0959a29c7..6c5bcfd71 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -313,6 +313,13 @@ func TestTxs(t *testing.T) { // assert.NotEqual(t, "[]", body) } +func TestValidatorsQuery(t *testing.T) { + validators := getValidators(t) + assert.Equal(t, len(validators), 2) + assert.Equal(t, hex.EncodeToString(validators[0].Owner), validatorAddr1) + assert.Equal(t, hex.EncodeToString(validators[1].Owner), validatorAddr2) +} + func TestBond(t *testing.T) { // create bond TX @@ -631,42 +638,12 @@ func doUnbond(t *testing.T, port, seed string) (resultTx ctypes.ResultBroadcastT return results[0] } -func doMultiBond(t *testing.T, port, seed string) (resultTx ctypes.ResultBroadcastTxCommit) { +func getValidators(t *testing.T) []stake.Validator { // get the account to get the sequence - acc := getAccount(t, sendAddr) - sequence := acc.GetSequence() - - // send - jsonStr := []byte(fmt.Sprintf(`{ - "name": "%s", - "password": "%s", - "sequence": %d, - "bond": [ - { - "delegator_addr": "%x", - "validator_addr": "%s", - "bond": { "denom": "%s", "amount": 1 } - }, - { - "delegator_addr": "%x", - "validator_addr": "%s", - "bond": { "denom": "%s", "amount": 1 } - }, - ], - "unbond": [ - { - "delegator_addr": "%x", - "validator_addr": "%s", - "shares": "1" - } - ] - }`, name, password, sequence, acc.GetAddress(), validatorAddr1, coinDenom, acc.GetAddress(), validatorAddr2, coinDenom, acc.GetAddress(), validatorAddr1)) - res, body := request(t, port, "POST", "/stake/delegations", jsonStr) + res, body := request(t, port, "GET", "/stake/validators", nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - - var results []ctypes.ResultBroadcastTxCommit - err := cdc.UnmarshalJSON([]byte(body), &results) + var validators stake.Validators + err := cdc.UnmarshalJSON([]byte(body), &validators) require.Nil(t, err) - - return results[0] + return validators } diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index cbcf5f5e8..0388467c4 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -18,6 +18,10 @@ func registerQueryRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec "/stake/{delegator}/bonding_status/{validator}", bondingStatusHandlerFn("stake", cdc, ctx), ).Methods("GET") + r.HandleFunc( + "/stake/validators", + validatorsHandlerFn("stake", cdc, ctx), + ).Methods("GET") } // http request handler to query delegator bonding status @@ -77,3 +81,42 @@ func bondingStatusHandlerFn(storeName string, cdc *wire.Codec, ctx context.CoreC w.Write(output) } } + +// http request handler to query list of validators +func validatorsHandlerFn(storeName string, cdc *wire.Codec, ctx context.CoreContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + res, err := ctx.QuerySubspace(cdc, stake.ValidatorsKey, storeName) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(fmt.Sprintf("Couldn't query validators. Error: %s", err.Error()))) + return + } + + // the query will return empty if there are no validators + if len(res) == 0 { + w.WriteHeader(http.StatusNoContent) + return + } + + validators := make(stake.Validators, 0, len(res)) + for _, kv := range res { + var validator stake.Validator + err = cdc.UnmarshalBinary(kv.Value, &validator) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error()))) + return + } + validators = append(validators, validator) + } + + output, err := cdc.MarshalJSON(validators) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + w.Write(output) + } +}