Skip to content

Commit

Permalink
Support Estimate Swap queries via grpc gateway (#5810)
Browse files Browse the repository at this point in the history
* Add estimate queries

* Fix bug

---------

Co-authored-by: Adam Tucker <[email protected]>
  • Loading branch information
mattverse and czarcas7ic authored Aug 2, 2023
1 parent 7331689 commit 11d4797
Show file tree
Hide file tree
Showing 6 changed files with 1,338 additions and 107 deletions.
44 changes: 44 additions & 0 deletions proto/osmosis/poolmanager/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,24 @@ service Query {
"/osmosis/poolmanager/v1beta1/{pool_id}/estimate/swap_exact_amount_in";
}

// EstimateSwapExactAmountInWithPrimitiveTypes is an alternative query for
// EstimateSwapExactAmountIn. Supports query via GRPC-Gateway by using
// primitive types instead of repeated structs. Each index in the
// routes_pool_id field corresponds to the respective routes_token_out_denom
// value, thus they are required to have the same length and are grouped
// together as pairs.
// example usage:
// http://0.0.0.0:1317/osmosis/poolmanager/v1beta1/1/estimate/
// swap_exact_amount_in_with_primitive_types?token_in=100000stake&routes_token_out_denom=uatom
// &routes_token_out_denom=uion&routes_pool_id=1&routes_pool_id=2
rpc EstimateSwapExactAmountInWithPrimitiveTypes(
EstimateSwapExactAmountInWithPrimitiveTypesRequest)
returns (EstimateSwapExactAmountInResponse) {
option (google.api.http).get =
"/osmosis/poolmanager/v1beta1/{pool_id}/estimate/"
"swap_exact_amount_in_with_primitive_types";
}

rpc EstimateSinglePoolSwapExactAmountIn(
EstimateSinglePoolSwapExactAmountInRequest)
returns (EstimateSwapExactAmountInResponse) {
Expand All @@ -41,6 +59,15 @@ service Query {
"/osmosis/poolmanager/v1beta1/{pool_id}/estimate/swap_exact_amount_out";
}

// Estimates swap amount in given out.
rpc EstimateSwapExactAmountOutWithPrimitiveTypes(
EstimateSwapExactAmountOutWithPrimitiveTypesRequest)
returns (EstimateSwapExactAmountOutResponse) {
option (google.api.http).get =
"/osmosis/poolmanager/v1beta1/{pool_id}/estimate/"
"swap_exact_amount_out_with_primitive_types";
}

rpc EstimateSinglePoolSwapExactAmountOut(
EstimateSinglePoolSwapExactAmountOutRequest)
returns (EstimateSwapExactAmountOutResponse) {
Expand Down Expand Up @@ -101,6 +128,14 @@ message EstimateSwapExactAmountInRequest {
(gogoproto.nullable) = false
];
}
message EstimateSwapExactAmountInWithPrimitiveTypesRequest {
uint64 pool_id = 1 [ (gogoproto.moretags) = "yaml:\"pool_id\"" ];
string token_in = 2 [ (gogoproto.moretags) = "yaml:\"token_in\"" ];
repeated uint64 routes_pool_id = 3
[ (gogoproto.moretags) = "yaml:\"routes_pool_id\"" ];
repeated string routes_token_out_denom = 4
[ (gogoproto.moretags) = "yaml:\"routes_token_out_denom\"" ];
}

message EstimateSinglePoolSwapExactAmountInRequest {
uint64 pool_id = 1 [ (gogoproto.moretags) = "yaml:\"pool_id\"" ];
Expand Down Expand Up @@ -129,6 +164,15 @@ message EstimateSwapExactAmountOutRequest {
string token_out = 4 [ (gogoproto.moretags) = "yaml:\"token_out\"" ];
}

message EstimateSwapExactAmountOutWithPrimitiveTypesRequest {
uint64 pool_id = 1 [ (gogoproto.moretags) = "yaml:\"pool_id\"" ];
repeated uint64 routes_pool_id = 2
[ (gogoproto.moretags) = "yaml:\"routes_pool_id\"" ];
repeated string routes_token_in_denom = 3
[ (gogoproto.moretags) = "yaml:\"routes_token_in_denom\"" ];
string token_out = 4 [ (gogoproto.moretags) = "yaml:\"token_out\"" ];
}

message EstimateSinglePoolSwapExactAmountOutRequest {
uint64 pool_id = 1 [ (gogoproto.moretags) = "yaml:\"pool_id\"" ];
string token_in_denom = 2
Expand Down
12 changes: 12 additions & 0 deletions proto/osmosis/poolmanager/v1beta1/query.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,23 @@ queries:
query_func: "k.EstimateSwapExactAmountIn"
cli:
cmd: "EstimateSwapExactAmountIn"
EstimateSwapExactAmountInWithPrimitiveTypes:
proto_wrapper:
query_func: "k.EstimateSwapExactAmountInWithPrimitiveTypes"
response: "*queryproto.EstimateSwapExactAmountInResponse"
cli:
cmd: "EstimateSwapExactAmountInWithPrimitiveTypes"
EstimateSwapExactAmountOut:
proto_wrapper:
query_func: "k.EstimateSwapExactAmountOut"
cli:
cmd: "EstimateSwapExactAmountOut"
EstimateSwapExactAmountOutWithPrimitiveTypes:
proto_wrapper:
query_func: "k.EstimateSwapExactAmountOutWithPrimitiveTypes"
response: "*queryproto.EstimateSwapExactAmountOutResponse"
cli:
cmd: "EstimateSwapExactAmountOutWithPrimitiveTypes"
EstimateSinglePoolSwapExactAmountIn:
proto_wrapper:
query_func: "k.EstimateSinglePoolSwapExactAmountIn"
Expand Down
20 changes: 20 additions & 0 deletions x/poolmanager/client/grpc/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ func (q Querier) NumPools(grpcCtx context.Context,
return q.Q.NumPools(ctx, *req)
}

func (q Querier) EstimateSwapExactAmountOutWithPrimitiveTypes(grpcCtx context.Context,
req *queryproto.EstimateSwapExactAmountOutWithPrimitiveTypesRequest,
) (*queryproto.EstimateSwapExactAmountOutResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
ctx := sdk.UnwrapSDKContext(grpcCtx)
return q.Q.EstimateSwapExactAmountOutWithPrimitiveTypes(ctx, *req)
}

func (q Querier) EstimateSwapExactAmountOut(grpcCtx context.Context,
req *queryproto.EstimateSwapExactAmountOutRequest,
) (*queryproto.EstimateSwapExactAmountOutResponse, error) {
Expand All @@ -90,6 +100,16 @@ func (q Querier) EstimateSwapExactAmountOut(grpcCtx context.Context,
return q.Q.EstimateSwapExactAmountOut(ctx, *req)
}

func (q Querier) EstimateSwapExactAmountInWithPrimitiveTypes(grpcCtx context.Context,
req *queryproto.EstimateSwapExactAmountInWithPrimitiveTypesRequest,
) (*queryproto.EstimateSwapExactAmountInResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
ctx := sdk.UnwrapSDKContext(grpcCtx)
return q.Q.EstimateSwapExactAmountInWithPrimitiveTypes(ctx, *req)
}

func (q Querier) EstimateSwapExactAmountIn(grpcCtx context.Context,
req *queryproto.EstimateSwapExactAmountInRequest,
) (*queryproto.EstimateSwapExactAmountInResponse, error) {
Expand Down
65 changes: 65 additions & 0 deletions x/poolmanager/client/query_proto_wrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,38 @@ func (q Querier) EstimateSwapExactAmountIn(ctx sdk.Context, req queryproto.Estim
}, nil
}

// EstimateSwapExactAmountInWithPrimitiveTypes runs same logic with EstimateSwapExactAmountIn
// but instead takes array of primitive types in the request to support query through grpc-gateway.
func (q Querier) EstimateSwapExactAmountInWithPrimitiveTypes(ctx sdk.Context, req queryproto.EstimateSwapExactAmountInWithPrimitiveTypesRequest) (*queryproto.EstimateSwapExactAmountInResponse, error) {
if req.TokenIn == "" {
return nil, status.Error(codes.InvalidArgument, "invalid token")
}

tokenIn, err := sdk.ParseCoinNormalized(req.TokenIn)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid token: %s", err.Error())
}

var routes []types.SwapAmountInRoute

for idx, poolId := range req.RoutesPoolId {
var route types.SwapAmountInRoute
route.PoolId = poolId
route.TokenOutDenom = req.RoutesTokenOutDenom[idx]

routes = append(routes, route)
}

tokenOutAmount, err := q.K.MultihopEstimateOutGivenExactAmountIn(ctx, routes, tokenIn)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

return &queryproto.EstimateSwapExactAmountInResponse{
TokenOutAmount: tokenOutAmount,
}, nil
}

// EstimateSwapExactAmountOut estimates token output amount for a swap.
func (q Querier) EstimateSwapExactAmountOut(ctx sdk.Context, req queryproto.EstimateSwapExactAmountOutRequest) (*queryproto.EstimateSwapExactAmountOutResponse, error) {
if req.TokenOut == "" {
Expand All @@ -75,6 +107,39 @@ func (q Querier) EstimateSwapExactAmountOut(ctx sdk.Context, req queryproto.Esti
}, nil
}

// EstimateSwapExactAmountOut estimates token output amount for a swap.
func (q Querier) EstimateSwapExactAmountOutWithPrimitiveTypes(ctx sdk.Context, req queryproto.EstimateSwapExactAmountOutWithPrimitiveTypesRequest) (*queryproto.EstimateSwapExactAmountOutResponse, error) {
if req.TokenOut == "" {
return nil, status.Error(codes.InvalidArgument, "invalid token")
}

var routes []types.SwapAmountOutRoute

for idx, poolId := range req.RoutesPoolId {
var route types.SwapAmountOutRoute
route.PoolId = poolId
route.TokenInDenom = req.RoutesTokenInDenom[idx]
}

if err := types.SwapAmountOutRoutes(routes).Validate(); err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

tokenOut, err := sdk.ParseCoinNormalized(req.TokenOut)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid token: %s", err.Error())
}

tokenInAmount, err := q.K.MultihopEstimateInGivenExactAmountOut(ctx, routes, tokenOut)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

return &queryproto.EstimateSwapExactAmountOutResponse{
TokenInAmount: tokenInAmount,
}, nil
}

func (q Querier) EstimateSinglePoolSwapExactAmountOut(ctx sdk.Context, req queryproto.EstimateSinglePoolSwapExactAmountOutRequest) (*queryproto.EstimateSwapExactAmountOutResponse, error) {
routeReq := &queryproto.EstimateSwapExactAmountOutRequest{
PoolId: req.PoolId,
Expand Down
Loading

0 comments on commit 11d4797

Please sign in to comment.