From 3e7d3f2948676464d09feae017114ab759b69ba4 Mon Sep 17 00:00:00 2001 From: Cosmic Vagabond <121588426+cosmic-vagabond@users.noreply.github.com> Date: Wed, 22 Nov 2023 08:58:09 +0100 Subject: [PATCH] feat: swap estimation by denom --- proto/elys/amm/query.proto | 19 + testutil/keeper/amm.go | 13 +- wasmbindings/types/types.go | 23 +- x/amm/client/cli/query.go | 4 +- .../cli/query_swap_estimation_by_denom.go | 55 ++ x/amm/client/wasm/querier.go | 2 + .../wasm/query_swap_estimation_by_denom.go | 22 + x/amm/genesis_test.go | 2 +- x/amm/keeper/calc_in_route_by_denom_test.go | 38 +- x/amm/keeper/calc_in_route_spot_price.go | 55 ++ x/amm/keeper/calc_in_route_spot_price_test.go | 50 ++ x/amm/keeper/calc_out_route_by_denom_test.go | 4 +- x/amm/keeper/calc_out_route_spot_price.go | 55 ++ .../keeper/calc_out_route_spot_price_test.go | 49 ++ x/amm/keeper/calc_swap_estimation_by_denom.go | 50 ++ .../calc_swap_estimation_by_denom_test.go | 41 + x/amm/keeper/denom_liquidity_test.go | 6 +- x/amm/keeper/keeper_test.go | 45 + x/amm/keeper/msg_server_test.go | 2 +- x/amm/keeper/pool_test.go | 8 +- x/amm/keeper/query_denom_liquidity_test.go | 4 +- x/amm/keeper/query_pool_test.go | 4 +- x/amm/keeper/query_swap_estimation.go | 35 +- .../keeper/query_swap_estimation_by_denom.go | 41 + x/amm/types/errors.go | 5 +- x/amm/types/expected_keepers.go | 4 + x/amm/types/mocks/accounted_pool_keeper.go | 80 ++ x/amm/types/mocks/oracle_keeper.go | 187 ++++ x/amm/types/query.pb.go | 816 ++++++++++++++++-- x/amm/types/query.pb.gw.go | 83 ++ 30 files changed, 1625 insertions(+), 177 deletions(-) create mode 100644 x/amm/client/cli/query_swap_estimation_by_denom.go create mode 100644 x/amm/client/wasm/query_swap_estimation_by_denom.go create mode 100644 x/amm/keeper/calc_in_route_spot_price.go create mode 100644 x/amm/keeper/calc_in_route_spot_price_test.go create mode 100644 x/amm/keeper/calc_out_route_spot_price.go create mode 100644 x/amm/keeper/calc_out_route_spot_price_test.go create mode 100644 x/amm/keeper/calc_swap_estimation_by_denom.go create mode 100644 x/amm/keeper/calc_swap_estimation_by_denom_test.go create mode 100644 x/amm/keeper/query_swap_estimation_by_denom.go create mode 100644 x/amm/types/mocks/accounted_pool_keeper.go create mode 100644 x/amm/types/mocks/oracle_keeper.go diff --git a/proto/elys/amm/query.proto b/proto/elys/amm/query.proto index a1cece600..c4820a211 100644 --- a/proto/elys/amm/query.proto +++ b/proto/elys/amm/query.proto @@ -79,6 +79,12 @@ service Query { option (google.api.http).get = "/elys-network/elys/amm/out_route_by_denom/{denom_out}/{denom_in}"; } + + // Queries a list of SwapEstimationByDenom items. + rpc SwapEstimationByDenom (QuerySwapEstimationByDenomRequest) returns (QuerySwapEstimationByDenomResponse) { + option (google.api.http).get = "/elys-network/elys/amm/swap_estimation_by_denom"; + + } } // QueryParamsRequest is request type for the Query/Params RPC method. message QueryParamsRequest {} @@ -175,3 +181,16 @@ message QueryOutRouteByDenomResponse { repeated SwapAmountOutRoute out_route = 1; } +message QuerySwapEstimationByDenomRequest { + cosmos.base.v1beta1.Coin amount = 1 [(gogoproto.nullable) = false]; + string denom_in = 2; + string denom_out = 3; +} + +message QuerySwapEstimationByDenomResponse { + repeated SwapAmountInRoute in_route = 1; + repeated SwapAmountOutRoute out_route = 2; + string spot_price = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; + cosmos.base.v1beta1.Coin amount = 4 [(gogoproto.nullable) = false]; +} + diff --git a/testutil/keeper/amm.go b/testutil/keeper/amm.go index 3c076f7b3..c7479a974 100644 --- a/testutil/keeper/amm.go +++ b/testutil/keeper/amm.go @@ -14,10 +14,11 @@ import ( typesparams "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/elys-network/elys/x/amm/keeper" "github.com/elys-network/elys/x/amm/types" + "github.com/elys-network/elys/x/amm/types/mocks" "github.com/stretchr/testify/require" ) -func AmmKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { +func AmmKeeper(t testing.TB) (*keeper.Keeper, sdk.Context, *mocks.AccountedPoolKeeper, *mocks.OracleKeeper) { storeKey := sdk.NewKVStoreKey(types.StoreKey) transientStoreKey := storetypes.NewTransientStoreKey(types.TStoreKey) @@ -36,6 +37,10 @@ func AmmKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { transientStoreKey, "AmmParams", ) + + accountedPoolKeeper := mocks.NewAccountedPoolKeeper(t) + oracleKeeper := mocks.NewOracleKeeper(t) + k := keeper.NewKeeper( cdc, storeKey, @@ -43,10 +48,10 @@ func AmmKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { paramsSubspace, nil, nil, + oracleKeeper, nil, nil, - nil, - nil, + accountedPoolKeeper, ) ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) @@ -54,5 +59,5 @@ func AmmKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { // Initialize params k.SetParams(ctx, types.DefaultParams()) - return k, ctx + return k, ctx, accountedPoolKeeper, oracleKeeper } diff --git a/wasmbindings/types/types.go b/wasmbindings/types/types.go index 7971b94ad..c918ce4c9 100644 --- a/wasmbindings/types/types.go +++ b/wasmbindings/types/types.go @@ -102,17 +102,18 @@ type ElysQuery struct { AccountedPoolAccountedPoolAll *accountedpooltypes.QueryAllAccountedPoolRequest `json:"accounted_pool_accounted_pool_all,omitempty"` // amm queriers - AmmParams *ammtypes.QueryParamsRequest `json:"amm_params,omitempty"` - AmmPool *ammtypes.QueryGetPoolRequest `json:"amm_pool,omitempty"` - AmmPoolAll *ammtypes.QueryAllPoolRequest `json:"amm_pool_all,omitempty"` - AmmDenomLiquidity *ammtypes.QueryGetDenomLiquidityRequest `json:"amm_denom_liquidity,omitempty"` - AmmDenomLiquidityAll *ammtypes.QueryAllDenomLiquidityRequest `json:"amm_denom_liquidity_all,omitempty"` - AmmSwapEstimation *ammtypes.QuerySwapEstimationRequest `json:"amm_swap_estimation,omitempty"` - AmmSlippageTrack *ammtypes.QuerySlippageTrackRequest `json:"amm_slippage_track,omitempty"` - AmmSlippageTrackAll *ammtypes.QuerySlippageTrackAllRequest `json:"amm_slippage_track_all,omitempty"` - AmmBalance *ammtypes.QueryBalanceRequest `json:"amm_balance,omitempty"` - AmmInRouteByDenom *ammtypes.QueryInRouteByDenomRequest `json:"amm_in_route_by_denom,omitempty"` - AmmOutRouteByDenom *ammtypes.QueryOutRouteByDenomRequest `json:"amm_out_route_by_denom,omitempty"` + AmmParams *ammtypes.QueryParamsRequest `json:"amm_params,omitempty"` + AmmPool *ammtypes.QueryGetPoolRequest `json:"amm_pool,omitempty"` + AmmPoolAll *ammtypes.QueryAllPoolRequest `json:"amm_pool_all,omitempty"` + AmmDenomLiquidity *ammtypes.QueryGetDenomLiquidityRequest `json:"amm_denom_liquidity,omitempty"` + AmmDenomLiquidityAll *ammtypes.QueryAllDenomLiquidityRequest `json:"amm_denom_liquidity_all,omitempty"` + AmmSwapEstimation *ammtypes.QuerySwapEstimationRequest `json:"amm_swap_estimation,omitempty"` + AmmSwapEstimationByDenom *ammtypes.QuerySwapEstimationByDenomRequest `json:"amm_swap_estimation_by_denom,omitempty"` + AmmSlippageTrack *ammtypes.QuerySlippageTrackRequest `json:"amm_slippage_track,omitempty"` + AmmSlippageTrackAll *ammtypes.QuerySlippageTrackAllRequest `json:"amm_slippage_track_all,omitempty"` + AmmBalance *ammtypes.QueryBalanceRequest `json:"amm_balance,omitempty"` + AmmInRouteByDenom *ammtypes.QueryInRouteByDenomRequest `json:"amm_in_route_by_denom,omitempty"` + AmmOutRouteByDenom *ammtypes.QueryOutRouteByDenomRequest `json:"amm_out_route_by_denom,omitempty"` // assetprofile queriers AssetProfileParams *assetprofiletypes.QueryParamsRequest `json:"asset_profile_params,omitempty"` diff --git a/x/amm/client/cli/query.go b/x/amm/client/cli/query.go index a111712d0..b8437db60 100644 --- a/x/amm/client/cli/query.go +++ b/x/amm/client/cli/query.go @@ -30,7 +30,9 @@ func GetQueryCmd(queryRoute string) *cobra.Command { cmd.AddCommand(CmdOutRouteByDenom()) - // this line is used by starport scaffolding # 1 + cmd.AddCommand(CmdSwapEstimationByDenom()) + +// this line is used by starport scaffolding # 1 return cmd } diff --git a/x/amm/client/cli/query_swap_estimation_by_denom.go b/x/amm/client/cli/query_swap_estimation_by_denom.go new file mode 100644 index 000000000..f4f0bfe6e --- /dev/null +++ b/x/amm/client/cli/query_swap_estimation_by_denom.go @@ -0,0 +1,55 @@ +package cli + +import ( + "strconv" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/elys-network/elys/x/amm/types" + "github.com/spf13/cobra" +) + +var _ = strconv.Itoa(0) + +func CmdSwapEstimationByDenom() *cobra.Command { + cmd := &cobra.Command{ + Use: "swap-estimation-by-denom [amount] [denom-in] [denom-out]", + Short: "Query swap-estimation-by-denom", + Example: "elysd q amm swap-estimation-by-denom 100uatom uatom uosmo", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) (err error) { + reqAmount, err := sdk.ParseCoinNormalized(args[0]) + if err != nil { + return err + } + reqDenomIn := args[1] + reqDenomOut := args[2] + + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + params := &types.QuerySwapEstimationByDenomRequest{ + + Amount: reqAmount, + DenomIn: reqDenomIn, + DenomOut: reqDenomOut, + } + + res, err := queryClient.SwapEstimationByDenom(cmd.Context(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/amm/client/wasm/querier.go b/x/amm/client/wasm/querier.go index 6deb0302a..8e54b0cc4 100644 --- a/x/amm/client/wasm/querier.go +++ b/x/amm/client/wasm/querier.go @@ -37,6 +37,8 @@ func (oq *Querier) HandleQuery(ctx sdk.Context, query wasmbindingstypes.ElysQuer return oq.queryDenomLiquidityAll(ctx, query.AmmDenomLiquidityAll) case query.AmmSwapEstimation != nil: return oq.querySwapEstimation(ctx, query.AmmSwapEstimation) + case query.AmmSwapEstimationByDenom != nil: + return oq.querySwapEstimationByDenom(ctx, query.AmmSwapEstimationByDenom) case query.AmmSlippageTrack != nil: return oq.querySlippageTrack(ctx, query.AmmSlippageTrack) case query.AmmSlippageTrackAll != nil: diff --git a/x/amm/client/wasm/query_swap_estimation_by_denom.go b/x/amm/client/wasm/query_swap_estimation_by_denom.go new file mode 100644 index 000000000..dd943eccb --- /dev/null +++ b/x/amm/client/wasm/query_swap_estimation_by_denom.go @@ -0,0 +1,22 @@ +package wasm + +import ( + "encoding/json" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + ammtypes "github.com/elys-network/elys/x/amm/types" +) + +func (oq *Querier) querySwapEstimationByDenom(ctx sdk.Context, query *ammtypes.QuerySwapEstimationByDenomRequest) ([]byte, error) { + res, err := oq.keeper.SwapEstimationByDenom(sdk.WrapSDKContext(ctx), query) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to get swap estimation by denom") + } + + responseBytes, err := json.Marshal(res) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to serialize swap estimation by denom response") + } + return responseBytes, nil +} diff --git a/x/amm/genesis_test.go b/x/amm/genesis_test.go index 91c2b511e..e1b4d4989 100644 --- a/x/amm/genesis_test.go +++ b/x/amm/genesis_test.go @@ -33,7 +33,7 @@ func TestGenesis(t *testing.T) { // this line is used by starport scaffolding # genesis/test/state } - k, ctx := keepertest.AmmKeeper(t) + k, ctx, _, _ := keepertest.AmmKeeper(t) amm.InitGenesis(ctx, *k, genesisState) got := amm.ExportGenesis(ctx, *k) require.NotNil(t, got) diff --git a/x/amm/keeper/calc_in_route_by_denom_test.go b/x/amm/keeper/calc_in_route_by_denom_test.go index 624be48ca..34d3170a9 100644 --- a/x/amm/keeper/calc_in_route_by_denom_test.go +++ b/x/amm/keeper/calc_in_route_by_denom_test.go @@ -3,18 +3,15 @@ package keeper_test import ( "testing" - sdk "github.com/cosmos/cosmos-sdk/types" keepertest "github.com/elys-network/elys/testutil/keeper" - "github.com/elys-network/elys/x/amm/keeper" - "github.com/elys-network/elys/x/amm/types" "github.com/stretchr/testify/require" ) func TestCalcInRouteByDenom(t *testing.T) { - k, ctx := keepertest.AmmKeeper(t) + k, ctx, _, _ := keepertest.AmmKeeper(t) // Setup mock pools and assets - setupMockPools(k, ctx) + SetupMockPools(k, ctx) // Test direct pool route route, err := k.CalcInRouteByDenom(ctx, "denom1", "denom2", "baseCurrency") @@ -37,34 +34,3 @@ func TestCalcInRouteByDenom(t *testing.T) { _, err = k.CalcInRouteByDenom(ctx, "denom1", "denom1", "baseCurrency") require.Error(t, err) } - -func setupMockPools(k *keeper.Keeper, ctx sdk.Context) { - // Create and set mock pools - pools := []types.Pool{ - { - PoolId: 1, - PoolAssets: []types.PoolAsset{ - {Token: sdk.Coin{Denom: "denom1", Amount: sdk.NewInt(1000)}}, - {Token: sdk.Coin{Denom: "denom2", Amount: sdk.NewInt(1000)}}, - }, - }, - { - PoolId: 2, - PoolAssets: []types.PoolAsset{ - {Token: sdk.Coin{Denom: "denom1", Amount: sdk.NewInt(1000)}}, - {Token: sdk.Coin{Denom: "baseCurrency", Amount: sdk.NewInt(1000)}}, - }, - }, - { - PoolId: 3, - PoolAssets: []types.PoolAsset{ - {Token: sdk.Coin{Denom: "baseCurrency", Amount: sdk.NewInt(1000)}}, - {Token: sdk.Coin{Denom: "denom3", Amount: sdk.NewInt(1000)}}, - }, - }, - } - - for _, pool := range pools { - k.SetPool(ctx, pool) - } -} diff --git a/x/amm/keeper/calc_in_route_spot_price.go b/x/amm/keeper/calc_in_route_spot_price.go new file mode 100644 index 000000000..32a758108 --- /dev/null +++ b/x/amm/keeper/calc_in_route_spot_price.go @@ -0,0 +1,55 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/elys-network/elys/x/amm/types" +) + +// CalcInRouteSpotPrice calculates the spot price of the given token and in route +func (k Keeper) CalcInRouteSpotPrice(ctx sdk.Context, tokenIn sdk.Coin, routes []*types.SwapAmountInRoute) (sdk.Dec, sdk.Coin, error) { + if routes == nil || len(routes) == 0 { + return sdk.ZeroDec(), sdk.Coin{}, types.ErrEmptyRoutes + } + + // Start with the initial token input + tokensIn := sdk.Coins{tokenIn} + + // The final token out denom + var tokenOutDenom string + + for _, route := range routes { + poolId := route.PoolId + tokenOutDenom = route.TokenOutDenom + + pool, found := k.GetPool(ctx, poolId) + if !found { + return sdk.ZeroDec(), sdk.Coin{}, types.ErrPoolNotFound + } + + // Estimate swap + snapshot := k.GetPoolSnapshotOrSet(ctx, pool) + swapResult, err := k.CalcOutAmtGivenIn(ctx, pool.PoolId, k.oracleKeeper, &snapshot, tokensIn, tokenOutDenom, sdk.ZeroDec()) + + if err != nil { + return sdk.ZeroDec(), sdk.Coin{}, err + } + + if swapResult.IsZero() { + return sdk.ZeroDec(), sdk.Coin{}, types.ErrAmountTooLow + } + + // Use the current swap result as the input for the next iteration + tokensIn = sdk.Coins{swapResult} + } + + // Calculate the spot price given the initial token in and the final token out + spotPrice := sdk.NewDecFromInt(tokensIn[0].Amount).Quo(sdk.NewDecFromInt(tokenIn.Amount)) + + // Calculate the token out amount + tokenOutAmt := sdk.NewDecFromInt(tokenIn.Amount).Mul(spotPrice) + + // Construct the token out coin + tokenOut := sdk.NewCoin(tokenOutDenom, tokenOutAmt.TruncateInt()) + + return spotPrice, tokenOut, nil +} diff --git a/x/amm/keeper/calc_in_route_spot_price_test.go b/x/amm/keeper/calc_in_route_spot_price_test.go new file mode 100644 index 000000000..0624ce351 --- /dev/null +++ b/x/amm/keeper/calc_in_route_spot_price_test.go @@ -0,0 +1,50 @@ +package keeper_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + keepertest "github.com/elys-network/elys/testutil/keeper" + "github.com/elys-network/elys/x/amm/types" + "github.com/stretchr/testify/require" +) + +func TestCalcInRouteSpotPrice(t *testing.T) { + k, ctx, accountedPoolKeeper, _ := keepertest.AmmKeeper(t) + SetupMockPools(k, ctx) + + // Use token in for all tests + tokenIn := sdk.NewCoin("denom1", sdk.NewInt(100)) + + // Test single route + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(1), "denom1").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(1), "denom2").Return(sdk.NewInt(1000)) + routes := []*types.SwapAmountInRoute{{PoolId: 1, TokenOutDenom: "denom2"}} + spotPrice, _, err := k.CalcInRouteSpotPrice(ctx, tokenIn, routes) + require.NoError(t, err) + require.NotZero(t, spotPrice) + accountedPoolKeeper.AssertExpectations(t) + + // Test multiple routes + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(2), "denom1").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(2), "baseCurrency").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(3), "baseCurrency").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(3), "denom3").Return(sdk.NewInt(1000)) + routes = []*types.SwapAmountInRoute{ + {PoolId: 2, TokenOutDenom: "baseCurrency"}, + {PoolId: 3, TokenOutDenom: "denom3"}, + } + spotPrice, _, err = k.CalcInRouteSpotPrice(ctx, tokenIn, routes) + require.NoError(t, err) + require.NotZero(t, spotPrice) + accountedPoolKeeper.AssertExpectations(t) + + // Test no routes + _, _, err = k.CalcInRouteSpotPrice(ctx, tokenIn, nil) + require.Error(t, err) + + // Test invalid pool + routes = []*types.SwapAmountInRoute{{PoolId: 9999, TokenOutDenom: "denom2"}} + _, _, err = k.CalcInRouteSpotPrice(ctx, tokenIn, routes) + require.Error(t, err) +} diff --git a/x/amm/keeper/calc_out_route_by_denom_test.go b/x/amm/keeper/calc_out_route_by_denom_test.go index 4a9d5de7c..20a54185a 100644 --- a/x/amm/keeper/calc_out_route_by_denom_test.go +++ b/x/amm/keeper/calc_out_route_by_denom_test.go @@ -8,10 +8,10 @@ import ( ) func TestCalcOutRouteByDenom(t *testing.T) { - k, ctx := keepertest.AmmKeeper(t) + k, ctx, _, _ := keepertest.AmmKeeper(t) // Setup mock pools and assets - setupMockPools(k, ctx) + SetupMockPools(k, ctx) // Test direct pool route route, err := k.CalcOutRouteByDenom(ctx, "denom2", "denom1", "baseCurrency") diff --git a/x/amm/keeper/calc_out_route_spot_price.go b/x/amm/keeper/calc_out_route_spot_price.go new file mode 100644 index 000000000..c56a5e7e9 --- /dev/null +++ b/x/amm/keeper/calc_out_route_spot_price.go @@ -0,0 +1,55 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/elys-network/elys/x/amm/types" +) + +// CalcOutRouteSpotPrice calculates the spot price of the given token and out route +func (k Keeper) CalcOutRouteSpotPrice(ctx sdk.Context, tokenOut sdk.Coin, routes []*types.SwapAmountOutRoute) (sdk.Dec, sdk.Coin, error) { + if routes == nil || len(routes) == 0 { + return sdk.ZeroDec(), sdk.Coin{}, types.ErrEmptyRoutes + } + + // Start with the initial token input + tokensOut := sdk.Coins{tokenOut} + + // The final token in denom + var tokenInDenom string + + for _, route := range routes { + poolId := route.PoolId + tokenInDenom = route.TokenInDenom + + pool, found := k.GetPool(ctx, poolId) + if !found { + return sdk.ZeroDec(), sdk.Coin{}, types.ErrPoolNotFound + } + + // Estimate swap + snapshot := k.GetPoolSnapshotOrSet(ctx, pool) + swapResult, err := k.CalcInAmtGivenOut(ctx, pool.PoolId, k.oracleKeeper, &snapshot, tokensOut, tokenInDenom, sdk.ZeroDec()) + + if err != nil { + return sdk.ZeroDec(), sdk.Coin{}, err + } + + if swapResult.IsZero() { + return sdk.ZeroDec(), sdk.Coin{}, types.ErrAmountTooLow + } + + // Use the current swap result as the input for the next iteration + tokensOut = sdk.Coins{swapResult} + } + + // Calculate the spot price given the initial token in and the final token in + spotPrice := sdk.NewDecFromInt(tokensOut[0].Amount).Quo(sdk.NewDecFromInt(tokenOut.Amount)) + + // Calculate the token in amount + tokenInAmt := sdk.NewDecFromInt(tokenOut.Amount).Mul(spotPrice) + + // Construct the token out coin + tokenIn := sdk.NewCoin(tokenInDenom, tokenInAmt.TruncateInt()) + + return spotPrice, tokenIn, nil +} diff --git a/x/amm/keeper/calc_out_route_spot_price_test.go b/x/amm/keeper/calc_out_route_spot_price_test.go new file mode 100644 index 000000000..b2896904b --- /dev/null +++ b/x/amm/keeper/calc_out_route_spot_price_test.go @@ -0,0 +1,49 @@ +package keeper_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + keepertest "github.com/elys-network/elys/testutil/keeper" + "github.com/elys-network/elys/x/amm/types" + "github.com/stretchr/testify/require" +) + +func TestCalcOutRouteSpotPrice(t *testing.T) { + k, ctx, accountedPoolKeeper, _ := keepertest.AmmKeeper(t) + SetupMockPools(k, ctx) + + // Test single route + tokenOut := sdk.NewCoin("denom2", sdk.NewInt(100)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(1), "denom2").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(1), "denom1").Return(sdk.NewInt(1000)) + routes := []*types.SwapAmountOutRoute{{PoolId: 1, TokenInDenom: "denom1"}} + spotPrice, _, err := k.CalcOutRouteSpotPrice(ctx, tokenOut, routes) + require.NoError(t, err) + require.NotZero(t, spotPrice) + accountedPoolKeeper.AssertExpectations(t) + + // Test multiple routes + tokenOut = sdk.NewCoin("denom3", sdk.NewInt(100)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(3), "denom3").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(3), "baseCurrency").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(2), "baseCurrency").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(2), "denom1").Return(sdk.NewInt(1000)) + routes = []*types.SwapAmountOutRoute{ + {PoolId: 3, TokenInDenom: "baseCurrency"}, + {PoolId: 2, TokenInDenom: "denom1"}, + } + spotPrice, _, err = k.CalcOutRouteSpotPrice(ctx, tokenOut, routes) + require.NoError(t, err) + require.NotZero(t, spotPrice) + accountedPoolKeeper.AssertExpectations(t) + + // Test no routes + _, _, err = k.CalcOutRouteSpotPrice(ctx, tokenOut, nil) + require.Error(t, err) + + // Test invalid pool + routes = []*types.SwapAmountOutRoute{{PoolId: 9999, TokenInDenom: "denom2"}} + _, _, err = k.CalcOutRouteSpotPrice(ctx, tokenOut, routes) + require.Error(t, err) +} diff --git a/x/amm/keeper/calc_swap_estimation_by_denom.go b/x/amm/keeper/calc_swap_estimation_by_denom.go new file mode 100644 index 000000000..55f2d365c --- /dev/null +++ b/x/amm/keeper/calc_swap_estimation_by_denom.go @@ -0,0 +1,50 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/elys-network/elys/x/amm/types" +) + +// CalcSwapEstimationByDenom calculates the swap estimation by denom +func (k Keeper) CalcSwapEstimationByDenom( + ctx sdk.Context, + amount sdk.Coin, + denomIn string, + denomOut string, + baseCurrency string, +) ( + inRoute []*types.SwapAmountInRoute, + outRoute []*types.SwapAmountOutRoute, + outAmount sdk.Coin, + spotPrice sdk.Dec, + err error, +) { + // if amount denom is equal to denomIn, calculate swap estimation by denomIn + if amount.Denom == denomIn { + inRoute, err := k.CalcInRouteByDenom(ctx, denomIn, denomOut, baseCurrency) + if err != nil { + return nil, nil, sdk.Coin{}, sdk.ZeroDec(), err + } + spotPrice, tokenOut, err := k.CalcInRouteSpotPrice(ctx, amount, inRoute) + if err != nil { + return nil, nil, sdk.Coin{}, sdk.ZeroDec(), err + } + return inRoute, nil, tokenOut, spotPrice, nil + } + + // if amount denom is equal to denomOut, calculate swap estimation by denomOut + if amount.Denom == denomOut { + outRoute, err := k.CalcOutRouteByDenom(ctx, denomIn, denomOut, baseCurrency) + if err != nil { + return nil, nil, sdk.Coin{}, sdk.ZeroDec(), err + } + spotPrice, tokenOut, err := k.CalcOutRouteSpotPrice(ctx, amount, outRoute) + if err != nil { + return nil, nil, sdk.Coin{}, sdk.ZeroDec(), err + } + return nil, outRoute, tokenOut, spotPrice, nil + } + + // if amount denom is neither equal to denomIn nor denomOut, return error + return nil, nil, sdk.Coin{}, sdk.ZeroDec(), types.ErrInvalidDenom +} diff --git a/x/amm/keeper/calc_swap_estimation_by_denom_test.go b/x/amm/keeper/calc_swap_estimation_by_denom_test.go new file mode 100644 index 000000000..8875a7e74 --- /dev/null +++ b/x/amm/keeper/calc_swap_estimation_by_denom_test.go @@ -0,0 +1,41 @@ +package keeper_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + keepertest "github.com/elys-network/elys/testutil/keeper" + "github.com/stretchr/testify/require" +) + +func TestCalcSwapEstimationByDenom(t *testing.T) { + k, ctx, accountedPoolKeeper, _ := keepertest.AmmKeeper(t) + SetupMockPools(k, ctx) + + // Test with amount denom equal to denomIn + amount := sdk.NewCoin("denom1", sdk.NewInt(100)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(1), "denom1").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(1), "denom2").Return(sdk.NewInt(1000)) + inRoute, outRoute, tokenOut, spotPrice, err := k.CalcSwapEstimationByDenom(ctx, amount, "denom1", "denom2", "baseCurrency") + require.NoError(t, err) + require.NotNil(t, inRoute) + require.Nil(t, outRoute) + require.NotZero(t, tokenOut) + require.NotZero(t, spotPrice) + + // Test with amount denom equal to denomOut + amount = sdk.NewCoin("denom2", sdk.NewInt(100)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(1), "denom2").Return(sdk.NewInt(1000)) + accountedPoolKeeper.On("GetAccountedBalance", ctx, uint64(1), "denom1").Return(sdk.NewInt(1000)) + inRoute, outRoute, tokenOut, spotPrice, err = k.CalcSwapEstimationByDenom(ctx, amount, "denom1", "denom2", "baseCurrency") + require.NoError(t, err) + require.Nil(t, inRoute) + require.NotNil(t, outRoute) + require.NotZero(t, tokenOut) + require.NotZero(t, spotPrice) + + // Test with invalid amount denom + amount = sdk.NewCoin("invalid", sdk.NewInt(1000)) + _, _, _, _, err = k.CalcSwapEstimationByDenom(ctx, amount, "denom1", "denom2", "baseCurrency") + require.Error(t, err) +} diff --git a/x/amm/keeper/denom_liquidity_test.go b/x/amm/keeper/denom_liquidity_test.go index a243511c6..decf2e582 100644 --- a/x/amm/keeper/denom_liquidity_test.go +++ b/x/amm/keeper/denom_liquidity_test.go @@ -27,7 +27,7 @@ func createNDenomLiquidity(keeper *keeper.Keeper, ctx sdk.Context, n int) []type } func TestDenomLiquidityGet(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) items := createNDenomLiquidity(keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetDenomLiquidity(ctx, @@ -41,7 +41,7 @@ func TestDenomLiquidityGet(t *testing.T) { } } func TestDenomLiquidityRemove(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) items := createNDenomLiquidity(keeper, ctx, 10) for _, item := range items { keeper.RemoveDenomLiquidity(ctx, @@ -55,7 +55,7 @@ func TestDenomLiquidityRemove(t *testing.T) { } func TestDenomLiquidityGetAll(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) items := createNDenomLiquidity(keeper, ctx, 10) require.ElementsMatch(t, nullify.Fill(items), diff --git a/x/amm/keeper/keeper_test.go b/x/amm/keeper/keeper_test.go index ce6fa19a5..9d3902af7 100644 --- a/x/amm/keeper/keeper_test.go +++ b/x/amm/keeper/keeper_test.go @@ -8,6 +8,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" simapp "github.com/elys-network/elys/app" + "github.com/elys-network/elys/x/amm/keeper" + "github.com/elys-network/elys/x/amm/types" oracletypes "github.com/elys-network/elys/x/oracle/types" ptypes "github.com/elys-network/elys/x/parameter/types" "github.com/stretchr/testify/suite" @@ -77,3 +79,46 @@ func (suite *KeeperTestSuite) SetupStableCoinPrices() { Timestamp: uint64(suite.ctx.BlockTime().Unix()), }) } + +func SetupMockPools(k *keeper.Keeper, ctx sdk.Context) { + // Create and set mock pools + pools := []types.Pool{ + { + PoolId: 1, + PoolAssets: []types.PoolAsset{ + {Token: sdk.NewCoin("denom1", sdk.NewInt(1000)), Weight: sdk.OneInt()}, + {Token: sdk.NewCoin("denom2", sdk.NewInt(1000)), Weight: sdk.OneInt()}, + }, + TotalWeight: sdk.NewInt(2), + PoolParams: types.PoolParams{ + UseOracle: false, + }, + }, + { + PoolId: 2, + PoolAssets: []types.PoolAsset{ + {Token: sdk.NewCoin("denom1", sdk.NewInt(1000)), Weight: sdk.OneInt()}, + {Token: sdk.NewCoin("baseCurrency", sdk.NewInt(1000)), Weight: sdk.OneInt()}, + }, + TotalWeight: sdk.NewInt(2), + PoolParams: types.PoolParams{ + UseOracle: false, + }, + }, + { + PoolId: 3, + PoolAssets: []types.PoolAsset{ + {Token: sdk.NewCoin("baseCurrency", sdk.NewInt(1000)), Weight: sdk.OneInt()}, + {Token: sdk.NewCoin("denom3", sdk.NewInt(1000)), Weight: sdk.OneInt()}, + }, + TotalWeight: sdk.NewInt(2), + PoolParams: types.PoolParams{ + UseOracle: false, + }, + }, + } + + for _, pool := range pools { + k.SetPool(ctx, pool) + } +} diff --git a/x/amm/keeper/msg_server_test.go b/x/amm/keeper/msg_server_test.go index 2dfae363c..40569d963 100644 --- a/x/amm/keeper/msg_server_test.go +++ b/x/amm/keeper/msg_server_test.go @@ -11,6 +11,6 @@ import ( ) func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) { - k, ctx := keepertest.AmmKeeper(t) + k, ctx, _, _ := keepertest.AmmKeeper(t) return keeper.NewMsgServerImpl(*k), sdk.WrapSDKContext(ctx) } diff --git a/x/amm/keeper/pool_test.go b/x/amm/keeper/pool_test.go index d114c0016..c0df7b6f8 100644 --- a/x/amm/keeper/pool_test.go +++ b/x/amm/keeper/pool_test.go @@ -40,7 +40,7 @@ func createNPool(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Pool { } func TestPoolGet(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) items := createNPool(keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetPool(ctx, @@ -54,7 +54,7 @@ func TestPoolGet(t *testing.T) { } } func TestPoolRemove(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) items := createNPool(keeper, ctx, 10) for _, item := range items { keeper.RemovePool(ctx, @@ -68,7 +68,7 @@ func TestPoolRemove(t *testing.T) { } func TestPoolGetAll(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) items := createNPool(keeper, ctx, 10) require.ElementsMatch(t, nullify.Fill(items), @@ -77,7 +77,7 @@ func TestPoolGetAll(t *testing.T) { } func TestGetPoolIdWithAllDenoms(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) items := createNPool(keeper, ctx, 10) // Add assets to some pools for testing diff --git a/x/amm/keeper/query_denom_liquidity_test.go b/x/amm/keeper/query_denom_liquidity_test.go index 8ea5f4b3c..e520b11dd 100644 --- a/x/amm/keeper/query_denom_liquidity_test.go +++ b/x/amm/keeper/query_denom_liquidity_test.go @@ -19,7 +19,7 @@ import ( var _ = strconv.IntSize func TestDenomLiquidityQuerySingle(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) wctx := sdk.WrapSDKContext(ctx) msgs := createNDenomLiquidity(keeper, ctx, 2) for _, tc := range []struct { @@ -70,7 +70,7 @@ func TestDenomLiquidityQuerySingle(t *testing.T) { } func TestDenomLiquidityQueryPaginated(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) wctx := sdk.WrapSDKContext(ctx) msgs := createNDenomLiquidity(keeper, ctx, 5) diff --git a/x/amm/keeper/query_pool_test.go b/x/amm/keeper/query_pool_test.go index 11df3610f..f0bd9efc3 100644 --- a/x/amm/keeper/query_pool_test.go +++ b/x/amm/keeper/query_pool_test.go @@ -19,7 +19,7 @@ import ( var _ = strconv.IntSize func TestPoolQuerySingle(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) wctx := sdk.WrapSDKContext(ctx) msgs := createNPool(keeper, ctx, 2) for _, tc := range []struct { @@ -70,7 +70,7 @@ func TestPoolQuerySingle(t *testing.T) { } func TestPoolQueryPaginated(t *testing.T) { - keeper, ctx := keepertest.AmmKeeper(t) + keeper, ctx, _, _ := keepertest.AmmKeeper(t) wctx := sdk.WrapSDKContext(ctx) msgs := createNPool(keeper, ctx, 5) diff --git a/x/amm/keeper/query_swap_estimation.go b/x/amm/keeper/query_swap_estimation.go index 721eba0f8..0893d7594 100644 --- a/x/amm/keeper/query_swap_estimation.go +++ b/x/amm/keeper/query_swap_estimation.go @@ -3,7 +3,6 @@ package keeper import ( "context" - "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/elys-network/elys/x/amm/types" "google.golang.org/grpc/codes" @@ -17,39 +16,13 @@ func (k Keeper) SwapEstimation(goCtx context.Context, req *types.QuerySwapEstima ctx := sdk.UnwrapSDKContext(goCtx) - // Start with the initial token input - tokensIn := sdk.Coins{req.TokenIn} - - for _, route := range req.Routes { - poolId := route.PoolId - tokenOutDenom := route.TokenOutDenom - - pool, found := k.GetPool(ctx, poolId) - if !found { - return nil, status.Error(codes.NotFound, "pool not found") - } - - // Estimate swap - snapshot := k.GetPoolSnapshotOrSet(ctx, pool) - swapResult, err := k.CalcOutAmtGivenIn(ctx, pool.PoolId, k.oracleKeeper, &snapshot, tokensIn, tokenOutDenom, sdk.ZeroDec()) - - if err != nil { - return nil, err - } - - if swapResult.IsZero() { - return nil, status.Error(codes.InvalidArgument, "amount too low") - } - - // Use the current swap result as the input for the next iteration - tokensIn = sdk.Coins{swapResult} + spotPrice, tokenOut, err := k.CalcInRouteSpotPrice(ctx, req.TokenIn, req.Routes) + if err != nil { + return nil, err } - // Calculate the spot price given the initial token in and the final token out - spotPrice := math.LegacyNewDecFromInt(tokensIn[0].Amount).Quo(math.LegacyNewDecFromInt(req.TokenIn.Amount)) - return &types.QuerySwapEstimationResponse{ SpotPrice: spotPrice, - TokenOut: tokensIn[0], + TokenOut: tokenOut, }, nil } diff --git a/x/amm/keeper/query_swap_estimation_by_denom.go b/x/amm/keeper/query_swap_estimation_by_denom.go new file mode 100644 index 000000000..bf797a898 --- /dev/null +++ b/x/amm/keeper/query_swap_estimation_by_denom.go @@ -0,0 +1,41 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/elys-network/elys/x/amm/types" + assetprofiletypes "github.com/elys-network/elys/x/assetprofile/types" + ptypes "github.com/elys-network/elys/x/parameter/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (k Keeper) SwapEstimationByDenom(goCtx context.Context, req *types.QuerySwapEstimationByDenomRequest) (*types.QuerySwapEstimationByDenomResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + + entry, found := k.apKeeper.GetEntry(ctx, ptypes.BaseCurrency) + if !found { + return nil, sdkerrors.Wrapf(assetprofiletypes.ErrAssetProfileNotFound, "asset %s not found", ptypes.BaseCurrency) + } + baseCurrency := entry.Denom + + _ = baseCurrency + + inRoute, outRoute, amount, spotPrice, err := k.CalcSwapEstimationByDenom(ctx, req.Amount, req.DenomIn, req.DenomOut, baseCurrency) + if err != nil { + return nil, err + } + + return &types.QuerySwapEstimationByDenomResponse{ + InRoute: inRoute, + OutRoute: outRoute, + Amount: amount, + SpotPrice: spotPrice, + }, nil +} diff --git a/x/amm/types/errors.go b/x/amm/types/errors.go index 1302948e4..e5bf16045 100644 --- a/x/amm/types/errors.go +++ b/x/amm/types/errors.go @@ -25,7 +25,10 @@ var ( ErrInvalidPoolId = sdkerrors.Register(ModuleName, 91, "invalid pool id") ErrInvalidSwapMsgType = sdkerrors.Register(ModuleName, 92, "unexpected swap message type") - ErrSameDenom = sdkerrors.Register(ModuleName, 101, "denom in and denom out are the same") + ErrSameDenom = sdkerrors.Register(ModuleName, 101, "denom in and denom out are the same") + ErrPoolNotFound = sdkerrors.Register(ModuleName, 102, "pool not found") + ErrAmountTooLow = sdkerrors.Register(ModuleName, 103, "amount too low") + ErrInvalidDenom = sdkerrors.Register(ModuleName, 104, "invalid denom") ) const ( diff --git a/x/amm/types/expected_keepers.go b/x/amm/types/expected_keepers.go index df40c1e05..f3517c796 100644 --- a/x/amm/types/expected_keepers.go +++ b/x/amm/types/expected_keepers.go @@ -30,6 +30,8 @@ type BankKeeper interface { } // OracleKeeper defines the expected interface needed to retrieve price info +// +//go:generate mockery --srcpkg . --name OracleKeeper --structname OracleKeeper --filename oracle_keeper.go --with-expecter type OracleKeeper interface { GetAssetPrice(ctx sdk.Context, asset string) (oracletypes.Price, bool) GetAssetPriceFromDenom(ctx sdk.Context, denom string) sdk.Dec @@ -45,6 +47,8 @@ type AssetProfileKeeper interface { } // AccountedPoolKeeper defines the expected interfaces +// +//go:generate mockery --srcpkg . --name AccountedPoolKeeper --structname AccountedPoolKeeper --filename accounted_pool_keeper.go --with-expecter type AccountedPoolKeeper interface { GetAccountedBalance(sdk.Context, uint64, string) sdk.Int } diff --git a/x/amm/types/mocks/accounted_pool_keeper.go b/x/amm/types/mocks/accounted_pool_keeper.go new file mode 100644 index 000000000..202d3d50e --- /dev/null +++ b/x/amm/types/mocks/accounted_pool_keeper.go @@ -0,0 +1,80 @@ +// Code generated by mockery v2.32.4. DO NOT EDIT. + +package mocks + +import ( + math "cosmossdk.io/math" + types "github.com/cosmos/cosmos-sdk/types" + mock "github.com/stretchr/testify/mock" +) + +// AccountedPoolKeeper is an autogenerated mock type for the AccountedPoolKeeper type +type AccountedPoolKeeper struct { + mock.Mock +} + +type AccountedPoolKeeper_Expecter struct { + mock *mock.Mock +} + +func (_m *AccountedPoolKeeper) EXPECT() *AccountedPoolKeeper_Expecter { + return &AccountedPoolKeeper_Expecter{mock: &_m.Mock} +} + +// GetAccountedBalance provides a mock function with given fields: _a0, _a1, _a2 +func (_m *AccountedPoolKeeper) GetAccountedBalance(_a0 types.Context, _a1 uint64, _a2 string) math.Int { + ret := _m.Called(_a0, _a1, _a2) + + var r0 math.Int + if rf, ok := ret.Get(0).(func(types.Context, uint64, string) math.Int); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Get(0).(math.Int) + } + + return r0 +} + +// AccountedPoolKeeper_GetAccountedBalance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAccountedBalance' +type AccountedPoolKeeper_GetAccountedBalance_Call struct { + *mock.Call +} + +// GetAccountedBalance is a helper method to define mock.On call +// - _a0 types.Context +// - _a1 uint64 +// - _a2 string +func (_e *AccountedPoolKeeper_Expecter) GetAccountedBalance(_a0 interface{}, _a1 interface{}, _a2 interface{}) *AccountedPoolKeeper_GetAccountedBalance_Call { + return &AccountedPoolKeeper_GetAccountedBalance_Call{Call: _e.mock.On("GetAccountedBalance", _a0, _a1, _a2)} +} + +func (_c *AccountedPoolKeeper_GetAccountedBalance_Call) Run(run func(_a0 types.Context, _a1 uint64, _a2 string)) *AccountedPoolKeeper_GetAccountedBalance_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(uint64), args[2].(string)) + }) + return _c +} + +func (_c *AccountedPoolKeeper_GetAccountedBalance_Call) Return(_a0 math.Int) *AccountedPoolKeeper_GetAccountedBalance_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *AccountedPoolKeeper_GetAccountedBalance_Call) RunAndReturn(run func(types.Context, uint64, string) math.Int) *AccountedPoolKeeper_GetAccountedBalance_Call { + _c.Call.Return(run) + return _c +} + +// NewAccountedPoolKeeper creates a new instance of AccountedPoolKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAccountedPoolKeeper(t interface { + mock.TestingT + Cleanup(func()) +}) *AccountedPoolKeeper { + mock := &AccountedPoolKeeper{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/x/amm/types/mocks/oracle_keeper.go b/x/amm/types/mocks/oracle_keeper.go new file mode 100644 index 000000000..5348ac7d5 --- /dev/null +++ b/x/amm/types/mocks/oracle_keeper.go @@ -0,0 +1,187 @@ +// Code generated by mockery v2.32.4. DO NOT EDIT. + +package mocks + +import ( + math "cosmossdk.io/math" + oracletypes "github.com/elys-network/elys/x/oracle/types" + mock "github.com/stretchr/testify/mock" + + types "github.com/cosmos/cosmos-sdk/types" +) + +// OracleKeeper is an autogenerated mock type for the OracleKeeper type +type OracleKeeper struct { + mock.Mock +} + +type OracleKeeper_Expecter struct { + mock *mock.Mock +} + +func (_m *OracleKeeper) EXPECT() *OracleKeeper_Expecter { + return &OracleKeeper_Expecter{mock: &_m.Mock} +} + +// GetAssetPrice provides a mock function with given fields: ctx, asset +func (_m *OracleKeeper) GetAssetPrice(ctx types.Context, asset string) (oracletypes.Price, bool) { + ret := _m.Called(ctx, asset) + + var r0 oracletypes.Price + var r1 bool + if rf, ok := ret.Get(0).(func(types.Context, string) (oracletypes.Price, bool)); ok { + return rf(ctx, asset) + } + if rf, ok := ret.Get(0).(func(types.Context, string) oracletypes.Price); ok { + r0 = rf(ctx, asset) + } else { + r0 = ret.Get(0).(oracletypes.Price) + } + + if rf, ok := ret.Get(1).(func(types.Context, string) bool); ok { + r1 = rf(ctx, asset) + } else { + r1 = ret.Get(1).(bool) + } + + return r0, r1 +} + +// OracleKeeper_GetAssetPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAssetPrice' +type OracleKeeper_GetAssetPrice_Call struct { + *mock.Call +} + +// GetAssetPrice is a helper method to define mock.On call +// - ctx types.Context +// - asset string +func (_e *OracleKeeper_Expecter) GetAssetPrice(ctx interface{}, asset interface{}) *OracleKeeper_GetAssetPrice_Call { + return &OracleKeeper_GetAssetPrice_Call{Call: _e.mock.On("GetAssetPrice", ctx, asset)} +} + +func (_c *OracleKeeper_GetAssetPrice_Call) Run(run func(ctx types.Context, asset string)) *OracleKeeper_GetAssetPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(string)) + }) + return _c +} + +func (_c *OracleKeeper_GetAssetPrice_Call) Return(_a0 oracletypes.Price, _a1 bool) *OracleKeeper_GetAssetPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *OracleKeeper_GetAssetPrice_Call) RunAndReturn(run func(types.Context, string) (oracletypes.Price, bool)) *OracleKeeper_GetAssetPrice_Call { + _c.Call.Return(run) + return _c +} + +// GetAssetPriceFromDenom provides a mock function with given fields: ctx, denom +func (_m *OracleKeeper) GetAssetPriceFromDenom(ctx types.Context, denom string) math.LegacyDec { + ret := _m.Called(ctx, denom) + + var r0 math.LegacyDec + if rf, ok := ret.Get(0).(func(types.Context, string) math.LegacyDec); ok { + r0 = rf(ctx, denom) + } else { + r0 = ret.Get(0).(math.LegacyDec) + } + + return r0 +} + +// OracleKeeper_GetAssetPriceFromDenom_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAssetPriceFromDenom' +type OracleKeeper_GetAssetPriceFromDenom_Call struct { + *mock.Call +} + +// GetAssetPriceFromDenom is a helper method to define mock.On call +// - ctx types.Context +// - denom string +func (_e *OracleKeeper_Expecter) GetAssetPriceFromDenom(ctx interface{}, denom interface{}) *OracleKeeper_GetAssetPriceFromDenom_Call { + return &OracleKeeper_GetAssetPriceFromDenom_Call{Call: _e.mock.On("GetAssetPriceFromDenom", ctx, denom)} +} + +func (_c *OracleKeeper_GetAssetPriceFromDenom_Call) Run(run func(ctx types.Context, denom string)) *OracleKeeper_GetAssetPriceFromDenom_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(string)) + }) + return _c +} + +func (_c *OracleKeeper_GetAssetPriceFromDenom_Call) Return(_a0 math.LegacyDec) *OracleKeeper_GetAssetPriceFromDenom_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *OracleKeeper_GetAssetPriceFromDenom_Call) RunAndReturn(run func(types.Context, string) math.LegacyDec) *OracleKeeper_GetAssetPriceFromDenom_Call { + _c.Call.Return(run) + return _c +} + +// GetPriceFeeder provides a mock function with given fields: ctx, feeder +func (_m *OracleKeeper) GetPriceFeeder(ctx types.Context, feeder string) (oracletypes.PriceFeeder, bool) { + ret := _m.Called(ctx, feeder) + + var r0 oracletypes.PriceFeeder + var r1 bool + if rf, ok := ret.Get(0).(func(types.Context, string) (oracletypes.PriceFeeder, bool)); ok { + return rf(ctx, feeder) + } + if rf, ok := ret.Get(0).(func(types.Context, string) oracletypes.PriceFeeder); ok { + r0 = rf(ctx, feeder) + } else { + r0 = ret.Get(0).(oracletypes.PriceFeeder) + } + + if rf, ok := ret.Get(1).(func(types.Context, string) bool); ok { + r1 = rf(ctx, feeder) + } else { + r1 = ret.Get(1).(bool) + } + + return r0, r1 +} + +// OracleKeeper_GetPriceFeeder_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPriceFeeder' +type OracleKeeper_GetPriceFeeder_Call struct { + *mock.Call +} + +// GetPriceFeeder is a helper method to define mock.On call +// - ctx types.Context +// - feeder string +func (_e *OracleKeeper_Expecter) GetPriceFeeder(ctx interface{}, feeder interface{}) *OracleKeeper_GetPriceFeeder_Call { + return &OracleKeeper_GetPriceFeeder_Call{Call: _e.mock.On("GetPriceFeeder", ctx, feeder)} +} + +func (_c *OracleKeeper_GetPriceFeeder_Call) Run(run func(ctx types.Context, feeder string)) *OracleKeeper_GetPriceFeeder_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(string)) + }) + return _c +} + +func (_c *OracleKeeper_GetPriceFeeder_Call) Return(val oracletypes.PriceFeeder, found bool) *OracleKeeper_GetPriceFeeder_Call { + _c.Call.Return(val, found) + return _c +} + +func (_c *OracleKeeper_GetPriceFeeder_Call) RunAndReturn(run func(types.Context, string) (oracletypes.PriceFeeder, bool)) *OracleKeeper_GetPriceFeeder_Call { + _c.Call.Return(run) + return _c +} + +// NewOracleKeeper creates a new instance of OracleKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewOracleKeeper(t interface { + mock.TestingT + Cleanup(func()) +}) *OracleKeeper { + mock := &OracleKeeper{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/x/amm/types/query.pb.go b/x/amm/types/query.pb.go index af4ea5d50..f993d53ec 100644 --- a/x/amm/types/query.pb.go +++ b/x/amm/types/query.pb.go @@ -1036,6 +1036,127 @@ func (m *QueryOutRouteByDenomResponse) GetOutRoute() []*SwapAmountOutRoute { return nil } +type QuerySwapEstimationByDenomRequest struct { + Amount types.Coin `protobuf:"bytes,1,opt,name=amount,proto3" json:"amount"` + DenomIn string `protobuf:"bytes,2,opt,name=denom_in,json=denomIn,proto3" json:"denom_in,omitempty"` + DenomOut string `protobuf:"bytes,3,opt,name=denom_out,json=denomOut,proto3" json:"denom_out,omitempty"` +} + +func (m *QuerySwapEstimationByDenomRequest) Reset() { *m = QuerySwapEstimationByDenomRequest{} } +func (m *QuerySwapEstimationByDenomRequest) String() string { return proto.CompactTextString(m) } +func (*QuerySwapEstimationByDenomRequest) ProtoMessage() {} +func (*QuerySwapEstimationByDenomRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_763da04a7298bbac, []int{22} +} +func (m *QuerySwapEstimationByDenomRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySwapEstimationByDenomRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySwapEstimationByDenomRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySwapEstimationByDenomRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySwapEstimationByDenomRequest.Merge(m, src) +} +func (m *QuerySwapEstimationByDenomRequest) XXX_Size() int { + return m.Size() +} +func (m *QuerySwapEstimationByDenomRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySwapEstimationByDenomRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySwapEstimationByDenomRequest proto.InternalMessageInfo + +func (m *QuerySwapEstimationByDenomRequest) GetAmount() types.Coin { + if m != nil { + return m.Amount + } + return types.Coin{} +} + +func (m *QuerySwapEstimationByDenomRequest) GetDenomIn() string { + if m != nil { + return m.DenomIn + } + return "" +} + +func (m *QuerySwapEstimationByDenomRequest) GetDenomOut() string { + if m != nil { + return m.DenomOut + } + return "" +} + +type QuerySwapEstimationByDenomResponse struct { + InRoute []*SwapAmountInRoute `protobuf:"bytes,1,rep,name=in_route,json=inRoute,proto3" json:"in_route,omitempty"` + OutRoute []*SwapAmountOutRoute `protobuf:"bytes,2,rep,name=out_route,json=outRoute,proto3" json:"out_route,omitempty"` + SpotPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=spot_price,json=spotPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"spot_price"` + Amount types.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount"` +} + +func (m *QuerySwapEstimationByDenomResponse) Reset() { *m = QuerySwapEstimationByDenomResponse{} } +func (m *QuerySwapEstimationByDenomResponse) String() string { return proto.CompactTextString(m) } +func (*QuerySwapEstimationByDenomResponse) ProtoMessage() {} +func (*QuerySwapEstimationByDenomResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_763da04a7298bbac, []int{23} +} +func (m *QuerySwapEstimationByDenomResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySwapEstimationByDenomResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySwapEstimationByDenomResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySwapEstimationByDenomResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySwapEstimationByDenomResponse.Merge(m, src) +} +func (m *QuerySwapEstimationByDenomResponse) XXX_Size() int { + return m.Size() +} +func (m *QuerySwapEstimationByDenomResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySwapEstimationByDenomResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySwapEstimationByDenomResponse proto.InternalMessageInfo + +func (m *QuerySwapEstimationByDenomResponse) GetInRoute() []*SwapAmountInRoute { + if m != nil { + return m.InRoute + } + return nil +} + +func (m *QuerySwapEstimationByDenomResponse) GetOutRoute() []*SwapAmountOutRoute { + if m != nil { + return m.OutRoute + } + return nil +} + +func (m *QuerySwapEstimationByDenomResponse) GetAmount() types.Coin { + if m != nil { + return m.Amount + } + return types.Coin{} +} + func init() { proto.RegisterType((*QueryParamsRequest)(nil), "elys.amm.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "elys.amm.QueryParamsResponse") @@ -1059,89 +1180,96 @@ func init() { proto.RegisterType((*QueryInRouteByDenomResponse)(nil), "elys.amm.QueryInRouteByDenomResponse") proto.RegisterType((*QueryOutRouteByDenomRequest)(nil), "elys.amm.QueryOutRouteByDenomRequest") proto.RegisterType((*QueryOutRouteByDenomResponse)(nil), "elys.amm.QueryOutRouteByDenomResponse") + proto.RegisterType((*QuerySwapEstimationByDenomRequest)(nil), "elys.amm.QuerySwapEstimationByDenomRequest") + proto.RegisterType((*QuerySwapEstimationByDenomResponse)(nil), "elys.amm.QuerySwapEstimationByDenomResponse") } func init() { proto.RegisterFile("elys/amm/query.proto", fileDescriptor_763da04a7298bbac) } var fileDescriptor_763da04a7298bbac = []byte{ - // 1221 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x97, 0xcf, 0x6f, 0x1b, 0x45, - 0x14, 0xc7, 0xb3, 0x69, 0x6a, 0xc7, 0x03, 0xa4, 0x65, 0x1a, 0x44, 0xb2, 0x49, 0x36, 0xb0, 0x6d, - 0x7e, 0x08, 0x29, 0xbb, 0x4d, 0x0a, 0xe5, 0x87, 0x40, 0xad, 0x4d, 0x4b, 0x88, 0x04, 0x4a, 0x6a, - 0xca, 0x01, 0x10, 0x32, 0x6b, 0x7b, 0x64, 0x56, 0xd9, 0xdd, 0xd9, 0x78, 0xc7, 0x04, 0x2b, 0xca, - 0xa5, 0x37, 0x0e, 0x95, 0x90, 0x22, 0x71, 0xe1, 0x8e, 0x50, 0x8f, 0xfc, 0x15, 0x3d, 0x56, 0xe2, - 0x82, 0x38, 0x54, 0x28, 0xe1, 0x0f, 0x41, 0x33, 0xf3, 0xc6, 0xf6, 0xec, 0xae, 0x7f, 0x20, 0xf5, - 0x14, 0xef, 0xcc, 0x7b, 0xef, 0xfb, 0x79, 0x6f, 0xdf, 0xcc, 0xdb, 0xa0, 0x79, 0x12, 0x74, 0x13, - 0xd7, 0x0b, 0x43, 0xf7, 0xa8, 0x43, 0xda, 0x5d, 0x27, 0x6e, 0x53, 0x46, 0xf1, 0x2c, 0x5f, 0x75, - 0xbc, 0x30, 0x34, 0xe7, 0x5b, 0xb4, 0x45, 0xc5, 0xa2, 0xcb, 0x7f, 0xc9, 0x7d, 0x73, 0xb9, 0x45, - 0x69, 0x2b, 0x20, 0xae, 0x17, 0xfb, 0xae, 0x17, 0x45, 0x94, 0x79, 0xcc, 0xa7, 0x51, 0x02, 0xbb, - 0x6f, 0x35, 0x68, 0x12, 0xd2, 0xc4, 0xad, 0x7b, 0x09, 0x91, 0x61, 0xdd, 0x1f, 0xb6, 0xeb, 0x84, - 0x79, 0xdb, 0x6e, 0xec, 0xb5, 0xfc, 0x48, 0x18, 0x83, 0xed, 0x6b, 0x3d, 0xfd, 0xd8, 0x6b, 0x7b, - 0xa1, 0x0a, 0x71, 0xad, 0xbf, 0x4c, 0x69, 0x00, 0x8b, 0x8b, 0xda, 0x62, 0xcd, 0x4b, 0x12, 0xc2, - 0x60, 0xcb, 0xd4, 0xb7, 0xb4, 0x58, 0xd6, 0x20, 0x8e, 0x02, 0x69, 0x50, 0x5f, 0x21, 0x58, 0x3d, - 0xdf, 0x26, 0x89, 0x68, 0x58, 0x0b, 0xfc, 0xa3, 0x8e, 0xdf, 0xf4, 0x59, 0x37, 0x23, 0x9b, 0x1c, - 0x7b, 0x71, 0xad, 0x4d, 0x3b, 0x8c, 0xc8, 0x2d, 0x7b, 0x1e, 0xe1, 0x07, 0x3c, 0xbf, 0x03, 0xa1, - 0x57, 0x25, 0x47, 0x1d, 0x92, 0x30, 0xfb, 0x3e, 0xba, 0xa6, 0xad, 0x26, 0x31, 0x8d, 0x12, 0x82, - 0x1d, 0x54, 0x90, 0x5c, 0x0b, 0xc6, 0x1b, 0xc6, 0xe6, 0x4b, 0x3b, 0x57, 0x1d, 0x55, 0x65, 0x47, - 0x5a, 0x56, 0x66, 0x9e, 0x3e, 0x5f, 0x9d, 0xaa, 0x82, 0x95, 0xed, 0x40, 0x98, 0x5d, 0xc2, 0x0e, - 0x28, 0x0d, 0x20, 0x3a, 0x7e, 0x1d, 0x15, 0x45, 0x8e, 0x7e, 0x53, 0xc4, 0x99, 0xa9, 0x16, 0xf8, - 0xe3, 0x5e, 0xd3, 0xbe, 0x8b, 0xe6, 0x75, 0x7b, 0xd0, 0xdd, 0x44, 0x33, 0xdc, 0x02, 0x54, 0xe7, - 0x06, 0x54, 0x29, 0x0d, 0x40, 0x53, 0x58, 0xd8, 0xdf, 0x82, 0x62, 0x39, 0x08, 0x06, 0x15, 0x3f, - 0x41, 0xa8, 0xff, 0xde, 0x20, 0xcc, 0xba, 0x23, 0xab, 0xea, 0xf0, 0xaa, 0x3a, 0xb2, 0x77, 0xa0, - 0xb6, 0xce, 0x81, 0xd7, 0x22, 0xe0, 0x5b, 0x1d, 0xf0, 0xb4, 0x7f, 0x32, 0x80, 0xb0, 0x17, 0x3f, - 0x43, 0x78, 0x69, 0x34, 0x21, 0xde, 0xd5, 0x50, 0xa6, 0x05, 0xca, 0xc6, 0x58, 0x14, 0x29, 0xa3, - 0xb1, 0xbc, 0x83, 0x56, 0x54, 0xb1, 0xee, 0xf1, 0xb7, 0xfe, 0x99, 0x7a, 0xe9, 0x2a, 0xe9, 0x79, - 0x74, 0x59, 0xb4, 0x83, 0xc8, 0xb7, 0x54, 0x95, 0x0f, 0xb6, 0x8f, 0xac, 0x61, 0x6e, 0x90, 0xcb, - 0x2e, 0xba, 0x92, 0x6a, 0x23, 0xa8, 0xd8, 0x42, 0x3f, 0x2d, 0xdd, 0x15, 0x12, 0x9c, 0x6b, 0x6a, - 0xab, 0x76, 0x0b, 0x08, 0xcb, 0x41, 0x90, 0x4f, 0xf8, 0xa2, 0x5e, 0xcb, 0x1f, 0x06, 0x24, 0x95, - 0xa3, 0x34, 0x2a, 0xa9, 0x4b, 0xff, 0x3f, 0xa9, 0x17, 0xf7, 0xfe, 0x1e, 0x1b, 0xc8, 0x14, 0xd0, - 0x5f, 0x1c, 0x7b, 0xf1, 0xfd, 0x84, 0xf9, 0xa1, 0x58, 0x57, 0xb5, 0xb9, 0x85, 0x0a, 0xe2, 0x9c, - 0x26, 0xc0, 0xb9, 0xd4, 0xe7, 0xe4, 0x0e, 0xe5, 0x90, 0x76, 0x22, 0xb6, 0x17, 0x55, 0xb9, 0x4d, - 0x15, 0x4c, 0xf1, 0x07, 0x68, 0x96, 0xd1, 0x43, 0x12, 0xd5, 0x7c, 0x85, 0xb6, 0xa8, 0xa1, 0x29, - 0xa8, 0x8f, 0xa9, 0x1f, 0x41, 0x7e, 0x45, 0xe1, 0xb0, 0x17, 0xd9, 0x4f, 0x0c, 0xb4, 0x94, 0xcb, - 0x03, 0x15, 0xfc, 0x1c, 0xa1, 0x24, 0xa6, 0xac, 0x16, 0xb7, 0xfd, 0x06, 0x91, 0x3d, 0x55, 0x71, - 0x78, 0x88, 0xbf, 0x9f, 0xaf, 0xae, 0xb7, 0x7c, 0xf6, 0x7d, 0xa7, 0xee, 0x34, 0x68, 0xe8, 0xc2, - 0x5d, 0x25, 0xff, 0x6c, 0x25, 0xcd, 0x43, 0x97, 0x75, 0x63, 0x92, 0x38, 0xf7, 0x48, 0xa3, 0x5a, - 0xe2, 0x11, 0x0e, 0x78, 0x00, 0xfc, 0x21, 0x2a, 0x49, 0x54, 0xda, 0x61, 0x93, 0xb2, 0xca, 0xe4, - 0xf6, 0x3b, 0xcc, 0x7e, 0x1b, 0x2d, 0x4a, 0xd6, 0xc0, 0x8f, 0x63, 0xaf, 0x45, 0x1e, 0xb6, 0xbd, - 0xc6, 0xe1, 0xd8, 0xfb, 0xe5, 0x1b, 0x55, 0x71, 0xdd, 0x0b, 0x12, 0xfc, 0x08, 0x5d, 0x66, 0x7c, - 0x01, 0x1a, 0xf1, 0xcd, 0x7e, 0xc1, 0xf7, 0xdb, 0x5e, 0x23, 0x20, 0xfc, 0x28, 0x6b, 0x9e, 0x40, - 0x25, 0xbd, 0x6c, 0x0b, 0x2d, 0x67, 0x83, 0x97, 0x03, 0x75, 0x07, 0xd9, 0xdf, 0xc1, 0x69, 0xc8, - 0xee, 0x83, 0xfe, 0x1d, 0x54, 0x10, 0x91, 0xd4, 0x1b, 0x9f, 0x18, 0x00, 0xdc, 0x7a, 0xb7, 0x76, - 0xc5, 0x0b, 0xbc, 0xa8, 0xa1, 0x4e, 0x0a, 0x5e, 0x40, 0x45, 0xaf, 0xd9, 0x6c, 0x93, 0x24, 0x81, - 0x9b, 0x40, 0x3d, 0xf6, 0x6f, 0x88, 0xe9, 0xc1, 0x1b, 0xe2, 0x01, 0xdc, 0x71, 0xbd, 0x30, 0xc0, - 0xf7, 0x3e, 0x2a, 0xd6, 0xe5, 0x12, 0x54, 0x68, 0x7c, 0x6f, 0x81, 0xbd, 0xfd, 0x10, 0x0a, 0x0f, - 0xfd, 0x5a, 0xe9, 0x8a, 0xa3, 0xa6, 0x00, 0x17, 0xd1, 0xac, 0x3c, 0x9b, 0x7e, 0xa4, 0x08, 0xc5, - 0xf3, 0x5e, 0x84, 0x97, 0x50, 0x49, 0x6e, 0xa9, 0x2e, 0x29, 0x55, 0xa5, 0x2d, 0x6f, 0x82, 0x2f, - 0xa1, 0x61, 0xd3, 0x51, 0x81, 0xf7, 0x36, 0x9a, 0xf5, 0x23, 0x39, 0xec, 0x26, 0x39, 0x43, 0x45, - 0x5f, 0xfe, 0xe8, 0x85, 0xdd, 0xef, 0xb0, 0x3c, 0x5a, 0x0d, 0xc9, 0xd0, 0x91, 0xb4, 0x54, 0xa6, - 0xb5, 0x54, 0xec, 0xaf, 0xa0, 0x3f, 0x32, 0x61, 0x7b, 0xe5, 0x2d, 0xd1, 0x0e, 0xd3, 0x78, 0x97, - 0xf3, 0x78, 0x95, 0x7f, 0x75, 0x96, 0xc2, 0xaf, 0x9d, 0xdf, 0x5f, 0x46, 0x97, 0x45, 0x6c, 0x1c, - 0xa0, 0x82, 0x9c, 0xc4, 0x78, 0xc0, 0x37, 0x3b, 0xe0, 0xcd, 0x95, 0x21, 0xbb, 0x92, 0xc5, 0x5e, - 0x7b, 0xf4, 0xe7, 0xbf, 0x67, 0xd3, 0xab, 0x78, 0xc5, 0xe5, 0x66, 0x5b, 0x11, 0x61, 0xc7, 0xb4, - 0x7d, 0xe8, 0xa6, 0xbe, 0x74, 0x30, 0x43, 0x33, 0xbc, 0x27, 0x71, 0x3a, 0x9a, 0x3e, 0xef, 0x4d, - 0x6b, 0xd8, 0x36, 0xa8, 0x6d, 0x09, 0xb5, 0x0d, 0xbc, 0x36, 0x4c, 0x8d, 0xd2, 0xc0, 0x3d, 0x81, - 0x23, 0x7d, 0x8a, 0x43, 0x54, 0xe4, 0xee, 0xe5, 0x20, 0x2b, 0xac, 0x8f, 0xfd, 0x8c, 0x70, 0x6a, - 0x6a, 0xdb, 0xd7, 0x85, 0xf0, 0x0a, 0x5e, 0x1a, 0x21, 0x8c, 0x7f, 0x35, 0xd0, 0x9c, 0x3e, 0x19, - 0xf0, 0x46, 0x36, 0xa1, 0xdc, 0x01, 0x67, 0x6e, 0x8e, 0x37, 0x04, 0x94, 0xdb, 0x02, 0xe5, 0x26, - 0x76, 0x86, 0xa0, 0xa4, 0x86, 0x97, 0x7b, 0x22, 0x16, 0x4e, 0xf1, 0x2f, 0x06, 0x7a, 0x55, 0x0f, - 0xc9, 0xeb, 0xb2, 0x91, 0x4d, 0x7c, 0x32, 0xc0, 0xa1, 0x03, 0xd4, 0x76, 0x04, 0xe0, 0x26, 0x5e, - 0x9f, 0x0c, 0x10, 0x3f, 0x36, 0xd0, 0x9c, 0x3e, 0x49, 0xf0, 0x8d, 0x94, 0x58, 0xee, 0xe0, 0x33, - 0xd7, 0xc6, 0x58, 0x4d, 0xc8, 0x23, 0xbe, 0x74, 0x49, 0x5f, 0xfc, 0xcc, 0x40, 0xaf, 0x68, 0x97, - 0x27, 0xbe, 0x9e, 0x16, 0xca, 0x99, 0x25, 0xe6, 0x8d, 0xd1, 0x46, 0x00, 0xf3, 0xae, 0x80, 0xd9, - 0xc6, 0xee, 0x30, 0x18, 0xf0, 0xaa, 0x89, 0x9b, 0x7a, 0xa0, 0x97, 0xcf, 0x0c, 0x74, 0x35, 0x3d, - 0x10, 0xf0, 0xfa, 0x28, 0xcd, 0xfe, 0x44, 0x31, 0x37, 0xc6, 0xda, 0x4d, 0x5a, 0x2b, 0x0d, 0x2f, - 0xc1, 0x8f, 0x0c, 0x54, 0x84, 0xdb, 0x3f, 0x73, 0xc4, 0xf4, 0xe1, 0x92, 0x39, 0x62, 0xa9, 0xa1, - 0x61, 0xbf, 0x27, 0xa4, 0x77, 0xf0, 0xcd, 0x21, 0xd2, 0x30, 0x21, 0xdc, 0x13, 0x98, 0x49, 0xa7, - 0xbd, 0xce, 0xfe, 0xcd, 0x40, 0x73, 0xfa, 0xcd, 0x9e, 0x69, 0xa0, 0xdc, 0x71, 0x92, 0x69, 0xa0, - 0xfc, 0xf1, 0x60, 0xef, 0x0a, 0xb2, 0x32, 0xbe, 0x33, 0x84, 0x4c, 0xcd, 0x8e, 0x5a, 0xbd, 0x5b, - 0x13, 0x48, 0x40, 0x56, 0xf3, 0x23, 0x05, 0xc9, 0x47, 0xc0, 0x29, 0x7e, 0x62, 0xa0, 0x2b, 0xa9, - 0x4b, 0x1d, 0xa7, 0x19, 0xf2, 0x67, 0x89, 0xb9, 0x3e, 0xce, 0x0c, 0x58, 0x3f, 0x15, 0xac, 0x15, - 0x7c, 0x77, 0x08, 0x6b, 0x6f, 0x70, 0x64, 0x60, 0x39, 0xe1, 0x00, 0x78, 0xa5, 0xf2, 0xf4, 0xdc, - 0x32, 0x9e, 0x9d, 0x5b, 0xc6, 0x3f, 0xe7, 0x96, 0xf1, 0xf3, 0x85, 0x35, 0xf5, 0xec, 0xc2, 0x9a, - 0xfa, 0xeb, 0xc2, 0x9a, 0xfa, 0x7a, 0x73, 0xe0, 0x1b, 0x2e, 0xab, 0xf2, 0xa3, 0xd0, 0x11, 0x5f, - 0x72, 0xf5, 0x82, 0xf8, 0xd7, 0xf1, 0xd6, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe5, 0x64, 0x0a, - 0xff, 0x7a, 0x0f, 0x00, 0x00, + // 1308 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x98, 0xcf, 0x6f, 0x1b, 0xc5, + 0x17, 0xc0, 0xb3, 0x4e, 0x6a, 0xc7, 0xef, 0xab, 0xa6, 0xfd, 0x4e, 0x53, 0xd1, 0x38, 0x89, 0x43, + 0xb7, 0xcd, 0x0f, 0x01, 0xd9, 0x6d, 0x52, 0x68, 0x01, 0x81, 0x5a, 0x9b, 0x96, 0x10, 0x09, 0x94, + 0xd4, 0x94, 0x03, 0x20, 0x64, 0xd6, 0xf6, 0xc8, 0xac, 0xb2, 0xbb, 0xb3, 0xf1, 0x8e, 0x09, 0x56, + 0x94, 0x4b, 0x6f, 0x1c, 0x2a, 0x21, 0x05, 0x71, 0xe1, 0xc0, 0x8d, 0x43, 0xb9, 0xf1, 0x57, 0xf4, + 0x58, 0x09, 0x09, 0x21, 0x0e, 0x15, 0x4a, 0xf8, 0x43, 0xd0, 0xce, 0xbc, 0xb5, 0x3d, 0xbb, 0xeb, + 0x1f, 0x51, 0x7b, 0xaa, 0x77, 0xe6, 0xcd, 0x7b, 0x9f, 0xf7, 0xe6, 0xbd, 0x79, 0xaf, 0x81, 0x59, + 0xea, 0x74, 0x02, 0xd3, 0x72, 0x5d, 0x73, 0xbf, 0x4d, 0x5b, 0x1d, 0xc3, 0x6f, 0x31, 0xce, 0xc8, + 0x74, 0xb8, 0x6a, 0x58, 0xae, 0x5b, 0x98, 0x6d, 0xb2, 0x26, 0x13, 0x8b, 0x66, 0xf8, 0x4b, 0xee, + 0x17, 0x16, 0x9a, 0x8c, 0x35, 0x1d, 0x6a, 0x5a, 0xbe, 0x6d, 0x5a, 0x9e, 0xc7, 0xb8, 0xc5, 0x6d, + 0xe6, 0x05, 0xb8, 0xfb, 0x5a, 0x9d, 0x05, 0x2e, 0x0b, 0xcc, 0x9a, 0x15, 0x50, 0xa9, 0xd6, 0xfc, + 0x76, 0xa3, 0x46, 0xb9, 0xb5, 0x61, 0xfa, 0x56, 0xd3, 0xf6, 0x84, 0x30, 0xca, 0x5e, 0xee, 0xda, + 0xf7, 0xad, 0x96, 0xe5, 0x46, 0x2a, 0x2e, 0xf5, 0x96, 0x19, 0x73, 0x70, 0x71, 0x4e, 0x59, 0xac, + 0x5a, 0x41, 0x40, 0x39, 0x6e, 0x15, 0xd4, 0x2d, 0x45, 0x57, 0xb1, 0x1f, 0x27, 0x02, 0xa9, 0x33, + 0x3b, 0x42, 0x28, 0x76, 0xcf, 0x36, 0xa8, 0xc7, 0xdc, 0xaa, 0x63, 0xef, 0xb7, 0xed, 0x86, 0xcd, + 0x3b, 0x09, 0xb3, 0xc1, 0x81, 0xe5, 0x57, 0x5b, 0xac, 0xcd, 0xa9, 0xdc, 0xd2, 0x67, 0x81, 0x3c, + 0x08, 0xfd, 0xdb, 0x15, 0xf6, 0x2a, 0x74, 0xbf, 0x4d, 0x03, 0xae, 0xdf, 0x87, 0x4b, 0xca, 0x6a, + 0xe0, 0x33, 0x2f, 0xa0, 0xc4, 0x80, 0xac, 0xe4, 0xba, 0xa2, 0xbd, 0xaa, 0xad, 0xfd, 0x6f, 0xf3, + 0xa2, 0x11, 0x45, 0xd9, 0x90, 0x92, 0xe5, 0xa9, 0xa7, 0xcf, 0x97, 0x26, 0x2a, 0x28, 0xa5, 0x1b, + 0xa8, 0x66, 0x8b, 0xf2, 0x5d, 0xc6, 0x1c, 0xd4, 0x4e, 0x5e, 0x81, 0x9c, 0xf0, 0xd1, 0x6e, 0x08, + 0x3d, 0x53, 0x95, 0x6c, 0xf8, 0xb9, 0xdd, 0xd0, 0xef, 0xc2, 0xac, 0x2a, 0x8f, 0x76, 0xd7, 0x60, + 0x2a, 0x94, 0x40, 0xab, 0x33, 0x7d, 0x56, 0x19, 0x73, 0xd0, 0xa6, 0x90, 0xd0, 0xbf, 0x42, 0x8b, + 0x25, 0xc7, 0xe9, 0xb7, 0xf8, 0x21, 0x40, 0xef, 0xde, 0x50, 0xcd, 0x8a, 0x21, 0xa3, 0x6a, 0x84, + 0x51, 0x35, 0x64, 0xee, 0x60, 0x6c, 0x8d, 0x5d, 0xab, 0x49, 0xf1, 0x6c, 0xa5, 0xef, 0xa4, 0xfe, + 0xbd, 0x86, 0x84, 0x5d, 0xfd, 0x09, 0xc2, 0xc9, 0xe1, 0x84, 0x64, 0x4b, 0x41, 0xc9, 0x08, 0x94, + 0xd5, 0x91, 0x28, 0xd2, 0x8c, 0xc2, 0xf2, 0x16, 0x2c, 0x46, 0xc1, 0xba, 0x17, 0xde, 0xfa, 0xc7, + 0xd1, 0xa5, 0x47, 0x4e, 0xcf, 0xc2, 0x39, 0x91, 0x0e, 0xc2, 0xdf, 0x7c, 0x45, 0x7e, 0xe8, 0x36, + 0x14, 0x07, 0x1d, 0x43, 0x5f, 0xb6, 0xe0, 0x42, 0x2c, 0x8d, 0x30, 0x62, 0x57, 0x7a, 0x6e, 0xa9, + 0x47, 0xd1, 0xc1, 0x99, 0x86, 0xb2, 0xaa, 0x37, 0x91, 0xb0, 0xe4, 0x38, 0xe9, 0x84, 0x2f, 0xeb, + 0x5a, 0x7e, 0xd7, 0xd0, 0xa9, 0x14, 0x4b, 0xc3, 0x9c, 0x9a, 0x3c, 0xbb, 0x53, 0x2f, 0xef, 0xfe, + 0x1e, 0x6b, 0x50, 0x10, 0xd0, 0x9f, 0x1e, 0x58, 0xfe, 0xfd, 0x80, 0xdb, 0xae, 0x58, 0x8f, 0x62, + 0x73, 0x13, 0xb2, 0xa2, 0x4e, 0x03, 0xe4, 0x9c, 0xef, 0x71, 0x86, 0x07, 0x4a, 0x2e, 0x6b, 0x7b, + 0x7c, 0xdb, 0xab, 0x84, 0x32, 0x15, 0x14, 0x25, 0xef, 0xc2, 0x34, 0x67, 0x7b, 0xd4, 0xab, 0xda, + 0x11, 0xda, 0x9c, 0x82, 0x16, 0x41, 0x7d, 0xc0, 0x6c, 0x0f, 0xfd, 0xcb, 0x89, 0x03, 0xdb, 0x9e, + 0xfe, 0x44, 0x83, 0xf9, 0x54, 0x1e, 0x8c, 0xe0, 0x27, 0x00, 0x81, 0xcf, 0x78, 0xd5, 0x6f, 0xd9, + 0x75, 0x2a, 0x73, 0xaa, 0x6c, 0x84, 0x2a, 0xfe, 0x7e, 0xbe, 0xb4, 0xd2, 0xb4, 0xf9, 0x37, 0xed, + 0x9a, 0x51, 0x67, 0xae, 0x89, 0x6f, 0x95, 0xfc, 0x67, 0x3d, 0x68, 0xec, 0x99, 0xbc, 0xe3, 0xd3, + 0xc0, 0xb8, 0x47, 0xeb, 0x95, 0x7c, 0xa8, 0x61, 0x37, 0x54, 0x40, 0xde, 0x83, 0xbc, 0x44, 0x65, + 0x6d, 0x3e, 0x2e, 0xab, 0x74, 0x6e, 0xa7, 0xcd, 0xf5, 0x37, 0x61, 0x4e, 0xb2, 0x3a, 0xb6, 0xef, + 0x5b, 0x4d, 0xfa, 0xb0, 0x65, 0xd5, 0xf7, 0x46, 0xbe, 0x2f, 0x5f, 0x46, 0x11, 0x57, 0x4f, 0xa1, + 0x83, 0xef, 0xc3, 0x39, 0x1e, 0x2e, 0x60, 0x22, 0x5e, 0xed, 0x05, 0x7c, 0xa7, 0x65, 0xd5, 0x1d, + 0x1a, 0x96, 0xb2, 0x72, 0x12, 0xa9, 0xe4, 0x29, 0xbd, 0x08, 0x0b, 0x49, 0xe5, 0x25, 0x27, 0x7a, + 0x83, 0xf4, 0xaf, 0xb1, 0x1a, 0x92, 0xfb, 0x68, 0xff, 0x0e, 0x64, 0x85, 0xa6, 0xe8, 0xc6, 0xc7, + 0x06, 0xc0, 0x63, 0xdd, 0x57, 0xbb, 0x6c, 0x39, 0x96, 0x57, 0x8f, 0x2a, 0x85, 0x5c, 0x81, 0x9c, + 0xd5, 0x68, 0xb4, 0x68, 0x10, 0xe0, 0x4b, 0x10, 0x7d, 0xf6, 0x5e, 0x88, 0x4c, 0xff, 0x0b, 0xf1, + 0x00, 0xdf, 0xb8, 0xae, 0x1a, 0xe4, 0x7b, 0x07, 0x72, 0x35, 0xb9, 0x84, 0x11, 0x1a, 0x9d, 0x5b, + 0x28, 0xaf, 0x3f, 0xc4, 0xc0, 0x63, 0xbe, 0x96, 0x3b, 0xa2, 0xd4, 0x22, 0xc0, 0x39, 0x98, 0x96, + 0xb5, 0x69, 0x7b, 0x11, 0xa1, 0xf8, 0xde, 0xf6, 0xc8, 0x3c, 0xe4, 0xe5, 0x56, 0x94, 0x25, 0xf9, + 0x8a, 0x94, 0x0d, 0x93, 0xe0, 0x33, 0x4c, 0xd8, 0xb8, 0x56, 0xe4, 0xbd, 0x05, 0xd3, 0xb6, 0x27, + 0x9b, 0xdd, 0x38, 0x35, 0x94, 0xb3, 0xe5, 0x8f, 0xae, 0xda, 0x9d, 0x36, 0x4f, 0xa3, 0x55, 0x90, + 0x34, 0x15, 0x49, 0x71, 0x25, 0xa3, 0xb8, 0xa2, 0x7f, 0x8e, 0xf9, 0x91, 0x50, 0xdb, 0x0d, 0x6f, + 0x9e, 0xb5, 0xb9, 0xc2, 0xbb, 0x90, 0xc6, 0x1b, 0x9d, 0xaf, 0x4c, 0x33, 0xfc, 0xa5, 0xff, 0xa8, + 0xc1, 0xd5, 0x94, 0xd2, 0x8d, 0x81, 0xdf, 0x86, 0xac, 0x25, 0x34, 0x8c, 0x7b, 0x7d, 0x28, 0x3e, + 0xc4, 0x29, 0x35, 0x18, 0x93, 0xb1, 0xfb, 0xf9, 0x25, 0x03, 0xfa, 0x30, 0xac, 0x17, 0xbb, 0x27, + 0x35, 0x60, 0x99, 0xb3, 0x04, 0x2c, 0xf6, 0x96, 0x4d, 0xbe, 0xe8, 0x5b, 0xd6, 0x8b, 0xec, 0xd4, + 0x99, 0x22, 0xbb, 0xf9, 0xe7, 0x79, 0x38, 0x27, 0x22, 0x44, 0x1c, 0xc8, 0xca, 0x11, 0x8a, 0xf4, + 0xf9, 0x90, 0x9c, 0xcc, 0x0a, 0x8b, 0x03, 0x76, 0x65, 0x2c, 0xf5, 0xe5, 0x47, 0x7f, 0xfc, 0x7b, + 0x9c, 0x59, 0x22, 0x8b, 0x66, 0x28, 0xb6, 0xee, 0x51, 0x7e, 0xc0, 0x5a, 0x7b, 0x66, 0x6c, 0x44, + 0x25, 0x1c, 0xa6, 0xc2, 0xc7, 0x84, 0xc4, 0xb5, 0xa9, 0x83, 0x5a, 0xa1, 0x38, 0x68, 0x1b, 0xad, + 0xad, 0x0b, 0x6b, 0xab, 0x64, 0x79, 0x90, 0x35, 0xc6, 0x1c, 0xf3, 0x10, 0xdf, 0xe2, 0x23, 0xe2, + 0x42, 0x2e, 0x3c, 0x5e, 0x72, 0x92, 0x86, 0xd5, 0x79, 0x2d, 0x61, 0x38, 0x36, 0x6e, 0xe9, 0xd7, + 0x84, 0xe1, 0x45, 0x32, 0x3f, 0xc4, 0x30, 0xf9, 0x59, 0x83, 0x19, 0xb5, 0xa5, 0x93, 0xd5, 0xa4, + 0x43, 0xa9, 0x93, 0x49, 0x61, 0x6d, 0xb4, 0x20, 0xa2, 0xdc, 0x12, 0x28, 0x37, 0x88, 0x31, 0x00, + 0x25, 0x36, 0x75, 0x98, 0x87, 0x62, 0xe1, 0x88, 0xfc, 0xa4, 0xc1, 0xff, 0x55, 0x95, 0x61, 0x5c, + 0x56, 0x93, 0x8e, 0x8f, 0x07, 0x38, 0x70, 0xf2, 0xd1, 0x0d, 0x01, 0xb8, 0x46, 0x56, 0xc6, 0x03, + 0x24, 0x8f, 0x35, 0x98, 0x51, 0x0b, 0x96, 0x5c, 0x8f, 0x19, 0x4b, 0x9d, 0x58, 0x0a, 0xcb, 0x23, + 0xa4, 0xc6, 0xe4, 0x11, 0xff, 0x45, 0xa1, 0x3d, 0xe3, 0xc7, 0x1a, 0x9c, 0x57, 0xba, 0x1e, 0xb9, + 0x16, 0x37, 0x94, 0x32, 0x04, 0x14, 0xae, 0x0f, 0x17, 0x42, 0x98, 0xdb, 0x02, 0x66, 0x83, 0x98, + 0x83, 0x60, 0xf0, 0x54, 0x55, 0xb4, 0xd8, 0xbe, 0x5c, 0x3e, 0xd6, 0xe0, 0x62, 0xbc, 0x93, 0x93, + 0x95, 0x61, 0x36, 0x7b, 0xa3, 0x40, 0x61, 0x75, 0xa4, 0xdc, 0xb8, 0xb1, 0x52, 0xf0, 0x02, 0xf2, + 0x48, 0x83, 0x1c, 0xb6, 0xed, 0x44, 0x89, 0xa9, 0x53, 0x41, 0xa2, 0xc4, 0x62, 0xdd, 0x5e, 0x7f, + 0x5b, 0x98, 0xde, 0x24, 0x37, 0x06, 0x98, 0xc6, 0xd6, 0x6e, 0x1e, 0xe2, 0x30, 0x71, 0xd4, 0xcd, + 0xec, 0x5f, 0x35, 0x98, 0x51, 0x5b, 0x72, 0x22, 0x81, 0x52, 0xe7, 0x80, 0x44, 0x02, 0xa5, 0xf7, + 0x75, 0x7d, 0x4b, 0x90, 0x95, 0xc8, 0x9d, 0x01, 0x64, 0x51, 0x33, 0xa9, 0xd6, 0x3a, 0x55, 0x81, + 0x84, 0x64, 0x55, 0xdb, 0x8b, 0x20, 0xc3, 0x76, 0x75, 0x44, 0x9e, 0x68, 0x70, 0x21, 0xd6, 0x8d, + 0x49, 0x9c, 0x21, 0x7d, 0x08, 0x28, 0xac, 0x8c, 0x12, 0x43, 0xd6, 0x8f, 0x04, 0x6b, 0x99, 0xdc, + 0x1d, 0xc0, 0xda, 0x6d, 0x60, 0x09, 0xd8, 0x90, 0xb0, 0x0f, 0x9c, 0xfc, 0xa6, 0xc1, 0xe5, 0xd4, + 0x3e, 0x4a, 0x5e, 0x1f, 0x5a, 0x77, 0x31, 0xf0, 0x37, 0xc6, 0x13, 0x1e, 0xb7, 0x3c, 0xd4, 0x5a, + 0xed, 0x3a, 0x51, 0x2e, 0x3f, 0x3d, 0x29, 0x6a, 0xcf, 0x4e, 0x8a, 0xda, 0x3f, 0x27, 0x45, 0xed, + 0x87, 0xd3, 0xe2, 0xc4, 0xb3, 0xd3, 0xe2, 0xc4, 0x5f, 0xa7, 0xc5, 0x89, 0x2f, 0xd6, 0xfa, 0xda, + 0x6b, 0x52, 0xe9, 0x77, 0x42, 0xad, 0x68, 0xb2, 0xb5, 0xac, 0xf8, 0x0b, 0xc5, 0xcd, 0xff, 0x02, + 0x00, 0x00, 0xff, 0xff, 0x03, 0x24, 0x21, 0x75, 0xe1, 0x11, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1176,6 +1304,8 @@ type QueryClient interface { InRouteByDenom(ctx context.Context, in *QueryInRouteByDenomRequest, opts ...grpc.CallOption) (*QueryInRouteByDenomResponse, error) // Queries a list of OutRouteByDenom items. OutRouteByDenom(ctx context.Context, in *QueryOutRouteByDenomRequest, opts ...grpc.CallOption) (*QueryOutRouteByDenomResponse, error) + // Queries a list of SwapEstimationByDenom items. + SwapEstimationByDenom(ctx context.Context, in *QuerySwapEstimationByDenomRequest, opts ...grpc.CallOption) (*QuerySwapEstimationByDenomResponse, error) } type queryClient struct { @@ -1285,6 +1415,15 @@ func (c *queryClient) OutRouteByDenom(ctx context.Context, in *QueryOutRouteByDe return out, nil } +func (c *queryClient) SwapEstimationByDenom(ctx context.Context, in *QuerySwapEstimationByDenomRequest, opts ...grpc.CallOption) (*QuerySwapEstimationByDenomResponse, error) { + out := new(QuerySwapEstimationByDenomResponse) + err := c.cc.Invoke(ctx, "/elys.amm.Query/SwapEstimationByDenom", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Parameters queries the parameters of the module. @@ -1307,6 +1446,8 @@ type QueryServer interface { InRouteByDenom(context.Context, *QueryInRouteByDenomRequest) (*QueryInRouteByDenomResponse, error) // Queries a list of OutRouteByDenom items. OutRouteByDenom(context.Context, *QueryOutRouteByDenomRequest) (*QueryOutRouteByDenomResponse, error) + // Queries a list of SwapEstimationByDenom items. + SwapEstimationByDenom(context.Context, *QuerySwapEstimationByDenomRequest) (*QuerySwapEstimationByDenomResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1346,6 +1487,9 @@ func (*UnimplementedQueryServer) InRouteByDenom(ctx context.Context, req *QueryI func (*UnimplementedQueryServer) OutRouteByDenom(ctx context.Context, req *QueryOutRouteByDenomRequest) (*QueryOutRouteByDenomResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method OutRouteByDenom not implemented") } +func (*UnimplementedQueryServer) SwapEstimationByDenom(ctx context.Context, req *QuerySwapEstimationByDenomRequest) (*QuerySwapEstimationByDenomResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SwapEstimationByDenom not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -1549,6 +1693,24 @@ func _Query_OutRouteByDenom_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Query_SwapEstimationByDenom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QuerySwapEstimationByDenomRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).SwapEstimationByDenom(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/elys.amm.Query/SwapEstimationByDenom", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).SwapEstimationByDenom(ctx, req.(*QuerySwapEstimationByDenomRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "elys.amm.Query", HandlerType: (*QueryServer)(nil), @@ -1597,6 +1759,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "OutRouteByDenom", Handler: _Query_OutRouteByDenom_Handler, }, + { + MethodName: "SwapEstimationByDenom", + Handler: _Query_SwapEstimationByDenom_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "elys/amm/query.proto", @@ -2379,6 +2545,124 @@ func (m *QueryOutRouteByDenomResponse) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } +func (m *QuerySwapEstimationByDenomRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySwapEstimationByDenomRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySwapEstimationByDenomRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.DenomOut) > 0 { + i -= len(m.DenomOut) + copy(dAtA[i:], m.DenomOut) + i = encodeVarintQuery(dAtA, i, uint64(len(m.DenomOut))) + i-- + dAtA[i] = 0x1a + } + if len(m.DenomIn) > 0 { + i -= len(m.DenomIn) + copy(dAtA[i:], m.DenomIn) + i = encodeVarintQuery(dAtA, i, uint64(len(m.DenomIn))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QuerySwapEstimationByDenomResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySwapEstimationByDenomResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySwapEstimationByDenomResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size := m.SpotPrice.Size() + i -= size + if _, err := m.SpotPrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.OutRoute) > 0 { + for iNdEx := len(m.OutRoute) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.OutRoute[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.InRoute) > 0 { + for iNdEx := len(m.InRoute) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.InRoute[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -2690,6 +2974,50 @@ func (m *QueryOutRouteByDenomResponse) Size() (n int) { return n } +func (m *QuerySwapEstimationByDenomRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Amount.Size() + n += 1 + l + sovQuery(uint64(l)) + l = len(m.DenomIn) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.DenomOut) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QuerySwapEstimationByDenomResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.InRoute) > 0 { + for _, e := range m.InRoute { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if len(m.OutRoute) > 0 { + for _, e := range m.OutRoute { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + l = m.SpotPrice.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.Amount.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -4671,6 +4999,338 @@ func (m *QueryOutRouteByDenomResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QuerySwapEstimationByDenomRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySwapEstimationByDenomRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySwapEstimationByDenomRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DenomIn", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DenomIn = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DenomOut", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DenomOut = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QuerySwapEstimationByDenomResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySwapEstimationByDenomResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySwapEstimationByDenomResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InRoute", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.InRoute = append(m.InRoute, &SwapAmountInRoute{}) + if err := m.InRoute[len(m.InRoute)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OutRoute", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OutRoute = append(m.OutRoute, &SwapAmountOutRoute{}) + if err := m.OutRoute[len(m.OutRoute)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SpotPrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SpotPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/amm/types/query.pb.gw.go b/x/amm/types/query.pb.gw.go index 5bdd5d3f4..389049bcc 100644 --- a/x/amm/types/query.pb.gw.go +++ b/x/amm/types/query.pb.gw.go @@ -567,6 +567,42 @@ func local_request_Query_OutRouteByDenom_0(ctx context.Context, marshaler runtim } +var ( + filter_Query_SwapEstimationByDenom_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_SwapEstimationByDenom_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySwapEstimationByDenomRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_SwapEstimationByDenom_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.SwapEstimationByDenom(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_SwapEstimationByDenom_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySwapEstimationByDenomRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_SwapEstimationByDenom_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.SwapEstimationByDenom(ctx, &protoReq) + return msg, metadata, err + +} + // 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. @@ -826,6 +862,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_SwapEstimationByDenom_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 { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_SwapEstimationByDenom_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) + return + } + + forward_Query_SwapEstimationByDenom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1087,6 +1146,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_SwapEstimationByDenom_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_SwapEstimationByDenom_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_SwapEstimationByDenom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1112,6 +1191,8 @@ var ( pattern_Query_InRouteByDenom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"elys-network", "elys", "amm", "in_route_by_denom", "denom_in", "denom_out"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_OutRouteByDenom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"elys-network", "elys", "amm", "out_route_by_denom", "denom_out", "denom_in"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_SwapEstimationByDenom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"elys-network", "elys", "amm", "swap_estimation_by_denom"}, "", runtime.AssumeColonVerbOpt(true))) ) var ( @@ -1136,4 +1217,6 @@ var ( forward_Query_InRouteByDenom_0 = runtime.ForwardResponseMessage forward_Query_OutRouteByDenom_0 = runtime.ForwardResponseMessage + + forward_Query_SwapEstimationByDenom_0 = runtime.ForwardResponseMessage )