diff --git a/CHANGELOG.md b/CHANGELOG.md index ae7735a66c..b04b18a047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ ### Chain - (feat) [\#1873](https://github.com/bandprotocol/bandchain/pull/1873) Add `in-before-resolve` field in `Report` data structure. +- (feat) [\#1875](https://github.com/bandprotocol/bandchain/pull/1875) Add CLI and REST query interface for request. - (chore) [\#1869](https://github.com/bandprotocol/bandchain/pull/1869) Update new schema and source code url for all oracle scripts - (chore) [\#1864](https://github.com/bandprotocol/bandchain/pull/1864) Remove unused query types. - (impv) [\#1792](https://github.com/bandprotocol/bandchain/pull/1792) Request data message handler test diff --git a/chain/x/oracle/client/cli/query.go b/chain/x/oracle/client/cli/query.go index eb904076e8..62d083ea8f 100644 --- a/chain/x/oracle/client/cli/query.go +++ b/chain/x/oracle/client/cli/query.go @@ -23,17 +23,17 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } oracleCmd.AddCommand(flags.GetCommands( - GetCmdParams(storeKey, cdc), - GetCmdCounts(storeKey, cdc), - GetCmdDataSource(storeKey, cdc), - GetCmdOracleScript(storeKey, cdc), + GetQueryCmdParams(storeKey, cdc), + GetQueryCmdCounts(storeKey, cdc), + GetQueryCmdDataSource(storeKey, cdc), + GetQueryCmdOracleScript(storeKey, cdc), + GetQueryCmdRequest(storeKey, cdc), )...) - return oracleCmd } -// GetCmdParams implements the query parameters command. -func GetCmdParams(route string, cdc *codec.Codec) *cobra.Command { +// GetQueryCmdParams implements the query parameters command. +func GetQueryCmdParams(route string, cdc *codec.Codec) *cobra.Command { return &cobra.Command{ Use: "params", Args: cobra.NoArgs, @@ -50,8 +50,8 @@ func GetCmdParams(route string, cdc *codec.Codec) *cobra.Command { } } -// GetCmdCounts implements the query counts command. -func GetCmdCounts(route string, cdc *codec.Codec) *cobra.Command { +// GetQueryCmdCounts implements the query counts command. +func GetQueryCmdCounts(route string, cdc *codec.Codec) *cobra.Command { return &cobra.Command{ Use: "counts", Args: cobra.NoArgs, @@ -68,8 +68,8 @@ func GetCmdCounts(route string, cdc *codec.Codec) *cobra.Command { } } -// GetCmdDataSource implements the query data source command. -func GetCmdDataSource(route string, cdc *codec.Codec) *cobra.Command { +// GetQueryCmdDataSource implements the query data source command. +func GetQueryCmdDataSource(route string, cdc *codec.Codec) *cobra.Command { return &cobra.Command{ Use: "data-source [id]", Args: cobra.ExactArgs(1), @@ -86,8 +86,8 @@ func GetCmdDataSource(route string, cdc *codec.Codec) *cobra.Command { } } -// GetCmdOracleScript implements the query oracle script command. -func GetCmdOracleScript(route string, cdc *codec.Codec) *cobra.Command { +// GetQueryCmdOracleScript implements the query oracle script command. +func GetQueryCmdOracleScript(route string, cdc *codec.Codec) *cobra.Command { return &cobra.Command{ Use: "oracle-script [id]", Args: cobra.ExactArgs(1), @@ -103,3 +103,21 @@ func GetCmdOracleScript(route string, cdc *codec.Codec) *cobra.Command { }, } } + +// GetQueryCmdRequest implements the query request command. +func GetQueryCmdRequest(route string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "request [id]", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx := context.NewCLIContext().WithCodec(cdc) + res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", route, types.QueryRequests, args[0]), nil) + if err != nil { + return err + } + var out types.QueryRequestResult + cdc.MustUnmarshalJSON(res, &out) + return cliCtx.PrintOutput(out) + }, + } +} diff --git a/chain/x/oracle/client/rest/query.go b/chain/x/oracle/client/rest/query.go index 11bba7a713..77b438ced4 100644 --- a/chain/x/oracle/client/rest/query.go +++ b/chain/x/oracle/client/rest/query.go @@ -68,7 +68,7 @@ func getDataSourceByIDHandler(cliCtx context.CLIContext, route string) http.Hand return } vars := mux.Vars(r) - res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", route, types.QueryDataSources, vars[dataSourceIDTag]), nil) + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", route, types.QueryDataSources, vars[idTag]), nil) if err != nil { rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return @@ -85,7 +85,24 @@ func getOracleScriptByIDHandler(cliCtx context.CLIContext, route string) http.Ha return } vars := mux.Vars(r) - res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", route, types.QueryOracleScripts, vars[oracleScriptIDTag]), nil) + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", route, types.QueryOracleScripts, vars[idTag]), nil) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} + +func getRequestByIDHandler(cliCtx context.CLIContext, route string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + vars := mux.Vars(r) + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", route, types.QueryRequests, vars[idTag]), nil) if err != nil { rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return diff --git a/chain/x/oracle/client/rest/rest.go b/chain/x/oracle/client/rest/rest.go index d168df8e6e..2431d89c39 100644 --- a/chain/x/oracle/client/rest/rest.go +++ b/chain/x/oracle/client/rest/rest.go @@ -9,15 +9,15 @@ import ( ) const ( - dataSourceIDTag = "dataSourceIDTag" - oracleScriptIDTag = "oracleScriptIDTag" - dataHashTag = "dataHashTag" + idTag = "idTag" + dataHashTag = "dataHashTag" ) func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, storeName string) { r.HandleFunc(fmt.Sprintf("/%s/params", storeName), getParamsHandler(cliCtx, storeName)).Methods("GET") r.HandleFunc(fmt.Sprintf("/%s/counts", storeName), getCountsHandler(cliCtx, storeName)).Methods("GET") r.HandleFunc(fmt.Sprintf("/%s/data/{%s}", storeName, dataHashTag), getDataByHashHandler(cliCtx, storeName)).Methods("GET") - r.HandleFunc(fmt.Sprintf("/%s/data_sources/{%s}", storeName, dataSourceIDTag), getDataSourceByIDHandler(cliCtx, storeName)).Methods("GET") - r.HandleFunc(fmt.Sprintf("/%s/oracle_scripts/{%s}", storeName, oracleScriptIDTag), getOracleScriptByIDHandler(cliCtx, storeName)).Methods("GET") + r.HandleFunc(fmt.Sprintf("/%s/data_sources/{%s}", storeName, idTag), getDataSourceByIDHandler(cliCtx, storeName)).Methods("GET") + r.HandleFunc(fmt.Sprintf("/%s/oracle_scripts/{%s}", storeName, idTag), getOracleScriptByIDHandler(cliCtx, storeName)).Methods("GET") + r.HandleFunc(fmt.Sprintf("/%s/requests/{%s}", storeName, idTag), getRequestByIDHandler(cliCtx, storeName)).Methods("GET") } diff --git a/chain/x/oracle/handler.go b/chain/x/oracle/handler.go index e253c6688c..3f300fc862 100644 --- a/chain/x/oracle/handler.go +++ b/chain/x/oracle/handler.go @@ -7,7 +7,6 @@ import ( "github.com/bandprotocol/bandchain/chain/x/oracle/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - _ "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" ) // NewHandler creates the msg handler of this module, as required by Cosmos-SDK standard. diff --git a/chain/x/oracle/keeper/querier.go b/chain/x/oracle/keeper/querier.go index 0ffc6bbb27..cdcdd3de74 100644 --- a/chain/x/oracle/keeper/querier.go +++ b/chain/x/oracle/keeper/querier.go @@ -25,6 +25,8 @@ func NewQuerier(keeper Keeper) sdk.Querier { return queryDataSourceByID(ctx, path[1:], keeper) case types.QueryOracleScripts: return queryOracleScriptByID(ctx, path[1:], keeper) + case types.QueryRequests: + return queryRequestByID(ctx, path[1:], keeper) default: return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown oracle query endpoint") } @@ -79,3 +81,22 @@ func queryOracleScriptByID(ctx sdk.Context, path []string, k Keeper) ([]byte, er } return codec.MarshalJSONIndent(types.ModuleCdc, oracleScript) } + +func queryRequestByID(ctx sdk.Context, path []string, k Keeper) ([]byte, error) { + if len(path) != 1 { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "request not specified") + } + id, err := strconv.ParseInt(path[0], 10, 64) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, err.Error()) + } + request, err := k.GetRequest(ctx, types.RequestID(id)) + reports := k.GetReports(ctx, types.RequestID(id)) + if err != nil { + return nil, err + } + return codec.MarshalJSONIndent(types.ModuleCdc, types.QueryRequestResult{ + Request: request, + Reports: reports, + }) +} diff --git a/chain/x/oracle/types/querier.go b/chain/x/oracle/types/querier.go index 6406f6cd50..7bce90c92e 100644 --- a/chain/x/oracle/types/querier.go +++ b/chain/x/oracle/types/querier.go @@ -7,6 +7,7 @@ const ( QueryData = "data" QueryDataSources = "data_sources" QueryOracleScripts = "oracle_scripts" + QueryRequests = "requests" ) // QueryCountsResult is the struct for the result of query counts. @@ -15,3 +16,9 @@ type QueryCountsResult struct { OracleScriptCount int64 `json:"oracle_script_count"` RequestCount int64 `json:"request_count"` } + +// QueryRequestResult is the struct for the result of request query. +type QueryRequestResult struct { + Request Request `json:"request"` + Reports []Report `json:"reports"` +}