From 98685e530095b470796a19e55f44c0780320fd16 Mon Sep 17 00:00:00 2001 From: Cosmic Vagabond <121588426+cosmic-vagabond@users.noreply.github.com> Date: Fri, 1 Sep 2023 12:07:55 +0200 Subject: [PATCH] Feat/oracle query proto wrap (#180) * feat: add query proto wrap * feat: add wasm bindings * feat: support PriceAll for CW querier * feat: remove total field * feat: call of price all from custom querier * fix: remove uneccessary code --- app/app.go | 3 ++ app/wasm.go | 96 ++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- x/amm/types/query.pb.gw.go | 19 +++++++- 4 files changed, 118 insertions(+), 2 deletions(-) diff --git a/app/app.go b/app/app.go index 6380d5bec..137c51458 100644 --- a/app/app.go +++ b/app/app.go @@ -754,6 +754,9 @@ func NewElysApp( // The last arguments can contain custom message handlers, and custom query handlers, // if we want to allow any custom callbacks availableCapabilities := strings.Join(AllCapabilities(), ",") + + wasmOpts = append(RegisterCustomPlugins(&app.OracleKeeper), wasmOpts...) + app.WasmKeeper = wasm.NewKeeper( appCodec, keys[wasm.StoreKey], diff --git a/app/wasm.go b/app/wasm.go index a01074f9e..a7a25343c 100644 --- a/app/wasm.go +++ b/app/wasm.go @@ -1,5 +1,18 @@ package app +import ( + "encoding/json" + + errorsmod "cosmossdk.io/errors" + "github.com/CosmWasm/wasmd/x/wasm" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdk "github.com/cosmos/cosmos-sdk/types" + query "github.com/cosmos/cosmos-sdk/types/query" + oraclekeeper "github.com/elys-network/elys/x/oracle/keeper" + oracletypes "github.com/elys-network/elys/x/oracle/types" +) + // AllCapabilities returns all capabilities available with the current wasmvm // See https://github.com/CosmWasm/cosmwasm/blob/main/docs/CAPABILITIES-BUILT-IN.md // This functionality is going to be moved upstream: https://github.com/CosmWasm/wasmvm/issues/425 @@ -12,3 +25,86 @@ func AllCapabilities() []string { "cosmwasm_1_2", } } + +type QueryPlugin struct { + oracleKeeper *oraclekeeper.Keeper +} + +// NewQueryPlugin returns a reference to a new QueryPlugin. +func NewQueryPlugin( + oracle *oraclekeeper.Keeper, +) *QueryPlugin { + return &QueryPlugin{ + oracleKeeper: oracle, + } +} + +func RegisterCustomPlugins( + oracle *oraclekeeper.Keeper, +) []wasmkeeper.Option { + wasmQueryPlugin := NewQueryPlugin(oracle) + + queryPluginOpt := wasmkeeper.WithQueryPlugins(&wasmkeeper.QueryPlugins{ + Custom: CustomQuerier(wasmQueryPlugin), + }) + + return []wasm.Option{ + queryPluginOpt, + } +} + +// CustomQuerier dispatches custom CosmWasm bindings queries. +func CustomQuerier(qp *QueryPlugin) func(ctx sdk.Context, request json.RawMessage) ([]byte, error) { + return func(ctx sdk.Context, request json.RawMessage) ([]byte, error) { + var contractQuery ElysQuery + if err := json.Unmarshal(request, &contractQuery); err != nil { + return nil, errorsmod.Wrap(err, "elys query") + } + + switch { + case contractQuery.PriceAll != nil: + pagination := contractQuery.PriceAll.Pagination + + // Calling the PriceAll function and handling its response + priceResponse, err := qp.oracleKeeper.PriceAll(ctx, &oracletypes.QueryAllPriceRequest{Pagination: pagination}) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to get all prices") + } + + // copy array priceResponse.Price + price := make([]oracletypes.Price, len(priceResponse.Price)) + copy(price, priceResponse.Price) + + res := AllPriceResponse{ + Price: price, + Pagination: &query.PageResponse{ + NextKey: priceResponse.Pagination.NextKey, + }, + } + + // Serializing the response to a JSON byte array + responseBytes, err := json.Marshal(res) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to serialize price response") + } + + return responseBytes, nil + + default: + return nil, wasmvmtypes.UnsupportedRequest{Kind: "unknown elys query variant"} + } + } +} + +type ElysQuery struct { + PriceAll *PriceAll `json:"price_all,omitempty"` +} + +type PriceAll struct { + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +type AllPriceResponse struct { + Price []oracletypes.Price `protobuf:"bytes,1,rep,name=price,proto3" json:"price"` + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} diff --git a/go.mod b/go.mod index 0edc0a171..b094c372c 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( cosmossdk.io/math v1.0.1 cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff github.com/CosmWasm/wasmd v0.41.0 + github.com/CosmWasm/wasmvm v1.3.0 github.com/bandprotocol/bandchain-packet v0.0.2 github.com/cometbft/cometbft v0.37.2 github.com/cometbft/cometbft-db v0.8.0 @@ -33,7 +34,6 @@ require ( cosmossdk.io/depinject v1.0.0-alpha.3 // indirect cosmossdk.io/log v1.1.1-0.20230704160919-88f2c830b0ca // indirect cosmossdk.io/tools/rosetta v0.2.1 // indirect - github.com/CosmWasm/wasmvm v1.3.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect diff --git a/x/amm/types/query.pb.gw.go b/x/amm/types/query.pb.gw.go index 2babba22a..3b891ece9 100644 --- a/x/amm/types/query.pb.gw.go +++ b/x/amm/types/query.pb.gw.go @@ -20,6 +20,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) @@ -30,6 +31,7 @@ var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray var _ = descriptor.ForMessage +var _ = metadata.Join func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest @@ -232,12 +234,14 @@ func local_request_Query_DenomLiquidityAll_0(ctx context.Context, marshaler runt // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) if err != nil { @@ -245,6 +249,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv return } resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -258,6 +263,8 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv mux.Handle("GET", pattern_Query_Pool_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) if err != nil { @@ -265,6 +272,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv return } resp, md, err := local_request_Query_Pool_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -278,6 +286,8 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv mux.Handle("GET", pattern_Query_PoolAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) if err != nil { @@ -285,6 +295,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv return } resp, md, err := local_request_Query_PoolAll_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -298,6 +309,8 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv mux.Handle("GET", pattern_Query_DenomLiquidity_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) if err != nil { @@ -305,6 +318,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv return } resp, md, err := local_request_Query_DenomLiquidity_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -318,6 +332,8 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv mux.Handle("GET", pattern_Query_DenomLiquidityAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) if err != nil { @@ -325,6 +341,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv return } resp, md, err := local_request_Query_DenomLiquidityAll_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)