Files
wasmd/x/wasm/client/rest/query.go
2020-02-07 20:31:32 +01:00

198 lines
6.5 KiB
Go

package rest
import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"strconv"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/cosmwasm/wasmd/x/wasm/internal/keeper"
"github.com/cosmwasm/wasmd/x/wasm/internal/types"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/gorilla/mux"
)
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) {
r.HandleFunc("/wasm/code", listCodesHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc("/wasm/code/{codeID}", queryCodeHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc("/wasm/contract", listAllContractsHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc("/wasm/contract/{contractAddr}", queryContractHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc("/wasm/contract/{contractAddr}/state", queryContractStateAllHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc("/wasm/contract/{contractAddr}/smart/{query}", queryContractStateSmartHandlerFn(cliCtx)).Queries("encoding", "{encoding}").Methods("GET")
r.HandleFunc("/wasm/contract/{contractAddr}/raw/{key}", queryContractStateRawHandlerFn(cliCtx)).Queries("encoding", "{encoding}").Methods("GET")
}
func listCodesHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, keeper.QueryListCode)
res, _, err := cliCtx.Query(route)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cliCtx, string(res))
}
}
func queryCodeHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
codeID, err := strconv.ParseUint(mux.Vars(r)["codeID"], 10, 64)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
route := fmt.Sprintf("custom/%s/%s/%d", types.QuerierRoute, keeper.QueryGetCode, codeID)
res, _, err := cliCtx.Query(route)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
if len(res) == 0 {
rest.WriteErrorResponse(w, http.StatusInternalServerError, "contract not found")
return
}
var code keeper.GetCodeResponse
err = json.Unmarshal(res, &code)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
if len(code.Code) == 0 {
rest.WriteErrorResponse(w, http.StatusInternalServerError, "contract not found")
return
}
rest.PostProcessResponse(w, cliCtx, code)
}
}
func listAllContractsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, keeper.QueryListContracts)
res, _, err := cliCtx.Query(route)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cliCtx, string(res))
}
}
func queryContractHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
addr, err := sdk.AccAddressFromBech32(mux.Vars(r)["contractAddr"])
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
route := fmt.Sprintf("custom/%s/%s/%s", types.QuerierRoute, keeper.QueryGetContract, addr.String())
res, _, err := cliCtx.Query(route)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cliCtx, string(res))
}
}
func queryContractStateAllHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
addr, err := sdk.AccAddressFromBech32(mux.Vars(r)["contractAddr"])
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
route := fmt.Sprintf("custom/%s/%s/%s/%s", types.QuerierRoute, keeper.QueryGetContractState, addr.String(), keeper.QueryMethodContractStateAll)
res, _, err := cliCtx.Query(route)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cliCtx, string(res))
}
}
func queryContractStateRawHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
decoder := newArgDecoder(hex.DecodeString)
addr, err := sdk.AccAddressFromBech32(mux.Vars(r)["contractAddr"])
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
decoder.encoding = mux.Vars(r)["encoding"]
queryData, err := decoder.DecodeString(mux.Vars(r)["key"])
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
route := fmt.Sprintf("custom/%s/%s/%s/%s", types.QuerierRoute, keeper.QueryGetContractState, addr.String(), keeper.QueryMethodContractStateRaw)
res, _, err := cliCtx.QueryWithData(route, queryData)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cliCtx, string(res))
}
}
func queryContractStateSmartHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
decoder := newArgDecoder(hex.DecodeString)
addr, err := sdk.AccAddressFromBech32(mux.Vars(r)["contractAddr"])
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
decoder.encoding = mux.Vars(r)["encoding"]
route := fmt.Sprintf("custom/%s/%s/%s/%s", types.QuerierRoute, keeper.QueryGetContractState, addr.String(), keeper.QueryMethodContractStateSmart)
queryData, err := decoder.DecodeString(mux.Vars(r)["query"])
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
res, _, err := cliCtx.QueryWithData(route, queryData)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cliCtx, string(res))
}
}
type argumentDecoder struct {
// dec is the default decoder
dec func(string) ([]byte, error)
encoding string
}
func newArgDecoder(def func(string) ([]byte, error)) *argumentDecoder {
return &argumentDecoder{dec: def}
}
func (a *argumentDecoder) DecodeString(s string) ([]byte, error) {
switch a.encoding {
case "hex":
return hex.DecodeString(s)
case "base64":
return base64.StdEncoding.DecodeString(s)
default:
return a.dec(s)
}
}