package rest import ( "fmt" "net/http" "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/gorilla/mux" ) const storeName = "stake" func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *wire.Codec) { r.HandleFunc( "/stake/{delegator}/delegation/{validator}", delegationHandlerFn(cliCtx, cdc), ).Methods("GET") r.HandleFunc( "/stake/{delegator}/ubd/{validator}", ubdHandlerFn(cliCtx, cdc), ).Methods("GET") r.HandleFunc( "/stake/{delegator}/red/{validator_src}/{validator_dst}", redHandlerFn(cliCtx, cdc), ).Methods("GET") r.HandleFunc( "/stake/validators", validatorsHandlerFn(cliCtx, cdc), ).Methods("GET") } // http request handler to query a delegation func delegationHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bech32delegator := vars["delegator"] bech32validator := vars["validator"] delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } validatorAddr, err := sdk.AccAddressFromBech32(bech32validator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } key := stake.GetDelegationKey(delegatorAddr, validatorAddr) res, err := cliCtx.QueryStore(key, storeName) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("couldn't query delegation. Error: %s", err.Error()))) return } // the query will return empty if there is no data for this record if len(res) == 0 { w.WriteHeader(http.StatusNoContent) return } delegation, err := types.UnmarshalDelegation(cdc, key, res) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } output, err := cdc.MarshalJSON(delegation) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } w.Write(output) } } // http request handler to query an unbonding-delegation func ubdHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bech32delegator := vars["delegator"] bech32validator := vars["validator"] delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } validatorAddr, err := sdk.AccAddressFromBech32(bech32validator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } key := stake.GetUBDKey(delegatorAddr, validatorAddr) res, err := cliCtx.QueryStore(key, storeName) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("couldn't query unbonding-delegation. Error: %s", err.Error()))) return } // the query will return empty if there is no data for this record if len(res) == 0 { w.WriteHeader(http.StatusNoContent) return } ubd, err := types.UnmarshalUBD(cdc, key, res) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("couldn't query unbonding-delegation. Error: %s", err.Error()))) return } output, err := cdc.MarshalJSON(ubd) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } w.Write(output) } } // http request handler to query an redelegation func redHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // read parameters vars := mux.Vars(r) bech32delegator := vars["delegator"] bech32validatorSrc := vars["validator_src"] bech32validatorDst := vars["validator_dst"] delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } validatorSrcAddr, err := sdk.AccAddressFromBech32(bech32validatorSrc) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } validatorDstAddr, err := sdk.AccAddressFromBech32(bech32validatorDst) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } key := stake.GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr) res, err := cliCtx.QueryStore(key, storeName) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("couldn't query redelegation. Error: %s", err.Error()))) return } // the query will return empty if there is no data for this record if len(res) == 0 { w.WriteHeader(http.StatusNoContent) return } red, err := types.UnmarshalRED(cdc, key, res) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("couldn't query unbonding-delegation. Error: %s", err.Error()))) return } output, err := cdc.MarshalJSON(red) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } w.Write(output) } } // TODO bech32 // http request handler to query list of validators func validatorsHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { kvs, err := cliCtx.QuerySubspace(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(kvs) == 0 { w.WriteHeader(http.StatusNoContent) return } // parse out the validators validators := make([]types.BechValidator, len(kvs)) for i, kv := range kvs { addr := kv.Key[1:] validator, err := types.UnmarshalValidator(cdc, addr, kv.Value) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("couldn't query unbonding-delegation. Error: %s", err.Error()))) return } bech32Validator, err := validator.Bech32Validator() if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } validators[i] = bech32Validator } output, err := cdc.MarshalJSON(validators) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } w.Write(output) } }