From f19ae6f6c565ff3fdfe71a134b99463888af8934 Mon Sep 17 00:00:00 2001 From: Cosmic Vagabond <121588426+cosmic-vagabond@users.noreply.github.com> Date: Fri, 24 Nov 2023 10:02:33 +0100 Subject: [PATCH] feat: apply discount to swap msgs (#271) * feat: apply discount to swap msgs * test: fix --- docs/static/openapi.yml | 28 +- proto/elys/amm/params.proto | 1 + proto/elys/amm/tx.proto | 29 +- x/amm/client/cli/tx.go | 1 + x/amm/client/cli/tx_swap_by_denom.go | 1 - x/amm/client/cli/tx_swap_exact_amount_in.go | 12 + x/amm/client/cli/tx_swap_exact_amount_out.go | 12 + x/amm/keeper/abci.go | 4 +- x/amm/keeper/abci_test.go | 12 + x/amm/keeper/apply_discount.go | 24 + x/amm/keeper/apply_discount_test.go | 102 ++++ x/amm/keeper/calc_swap_estimation_by_denom.go | 4 +- x/amm/keeper/msg_server_swap_by_denom.go | 95 +++- x/amm/keeper/msg_server_swap_by_denom_test.go | 164 +++++++ .../keeper/msg_server_swap_exact_amount_in.go | 2 +- .../msg_server_swap_exact_amount_in_test.go | 3 + .../msg_server_swap_exact_amount_out.go | 2 +- .../msg_server_swap_exact_amount_out_test.go | 1 + x/amm/keeper/params.go | 7 + x/amm/keeper/route_exact_amount_in.go | 7 + x/amm/keeper/route_exact_amount_in_test.go | 4 +- x/amm/keeper/route_exact_amount_out.go | 7 + x/amm/keeper/route_exact_amount_out_test.go | 4 +- x/amm/migrations/new_migrator.go | 13 + x/amm/migrations/v2_migration.go | 12 + x/amm/module.go | 8 +- x/amm/types/codec.go | 6 +- x/amm/types/errors.go | 9 +- x/amm/types/message_swap_exact_amount_in.go | 3 +- x/amm/types/message_swap_exact_amount_out.go | 3 +- x/amm/types/params.go | 22 + x/amm/types/params.pb.go | 69 ++- x/amm/types/tx.pb.go | 446 ++++++++++++++---- x/transferhook/keeper/swap.go | 1 + 34 files changed, 970 insertions(+), 148 deletions(-) create mode 100644 x/amm/keeper/apply_discount.go create mode 100644 x/amm/keeper/apply_discount_test.go create mode 100644 x/amm/keeper/msg_server_swap_by_denom_test.go create mode 100644 x/amm/migrations/new_migrator.go create mode 100644 x/amm/migrations/v2_migration.go diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index c013f684d..f3b64545d 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -37851,6 +37851,8 @@ paths: pool_creation_fee: type: string format: uint64 + broker_address: + type: string description: >- QueryParamsResponse is response type for the Query/Params RPC method. @@ -82920,10 +82922,28 @@ definitions: NOTE: The amount field is an Int which implements the custom method signatures required by gogoproto. - route: + in_route: type: array items: - type: string + type: object + properties: + pool_id: + type: string + format: uint64 + token_out_denom: + type: string + out_route: + type: array + items: + type: object + properties: + pool_id: + type: string + format: uint64 + token_in_denom: + type: string + spot_price: + type: string discount: type: string elys.amm.MsgSwapExactAmountInResponse: @@ -82965,6 +82985,8 @@ definitions: pool_creation_fee: type: string format: uint64 + broker_address: + type: string description: Params defines the parameters for the module. elys.amm.Pool: type: object @@ -83339,6 +83361,8 @@ definitions: pool_creation_fee: type: string format: uint64 + broker_address: + type: string description: QueryParamsResponse is response type for the Query/Params RPC method. elys.amm.QuerySlippageTrackAllResponse: type: object diff --git a/proto/elys/amm/params.proto b/proto/elys/amm/params.proto index 7922ce03d..ae24f0088 100644 --- a/proto/elys/amm/params.proto +++ b/proto/elys/amm/params.proto @@ -10,4 +10,5 @@ message Params { option (gogoproto.goproto_stringer) = false; uint64 pool_creation_fee = 1; + string broker_address = 2; } diff --git a/proto/elys/amm/tx.proto b/proto/elys/amm/tx.proto index 53850d96d..6c4a2bc98 100644 --- a/proto/elys/amm/tx.proto +++ b/proto/elys/amm/tx.proto @@ -4,6 +4,7 @@ package elys.amm; import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; +import "elys/amm/params.proto"; import "elys/amm/swap_route.proto"; import "elys/amm/pool_params.proto"; import "elys/amm/pool_asset.proto"; @@ -17,9 +18,10 @@ service Msg { rpc ExitPool (MsgExitPool ) returns (MsgExitPoolResponse ); rpc SwapExactAmountIn (MsgSwapExactAmountIn ) returns (MsgSwapExactAmountInResponse ); rpc SwapExactAmountOut (MsgSwapExactAmountOut ) returns (MsgSwapExactAmountOutResponse ); - rpc FeedMultipleExternalLiquidity (MsgFeedMultipleExternalLiquidity) returns (MsgFeedMultipleExternalLiquidityResponse); rpc SwapByDenom (MsgSwapByDenom ) returns (MsgSwapByDenomResponse ); + rpc FeedMultipleExternalLiquidity (MsgFeedMultipleExternalLiquidity) returns (MsgFeedMultipleExternalLiquidityResponse); } + message MsgCreatePool { string sender = 1; PoolParams pool_params = 2; @@ -60,10 +62,13 @@ message MsgSwapExactAmountIn { repeated SwapAmountInRoute routes = 2 [(gogoproto.nullable) = false ] ; cosmos.base.v1beta1.Coin token_in = 3 [(gogoproto.nullable) = false ] ; string token_out_min_amount = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false]; + string discount = 5 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; + } message MsgSwapExactAmountInResponse { string token_out_amount = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false]; + string discount = 2 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; } message MsgSwapExactAmountOut { @@ -71,10 +76,12 @@ message MsgSwapExactAmountOut { repeated SwapAmountOutRoute routes = 2 [(gogoproto.nullable) = false ] ; cosmos.base.v1beta1.Coin token_out = 3 [(gogoproto.nullable) = false ] ; string token_in_max_amount = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false]; + string discount = 5 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; } message MsgSwapExactAmountOutResponse { string token_in_amount = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false]; + string discount = 2 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; } message MsgFeedMultipleExternalLiquidity { @@ -97,19 +104,19 @@ message ExternalLiquidity { } message MsgSwapByDenom { - string sender = 1; - cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false]; - cosmos.base.v1beta1.Coin min_amount = 3 [(gogoproto.nullable) = false]; - cosmos.base.v1beta1.Coin max_amount = 4 [(gogoproto.nullable) = false]; + string sender = 1; + cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false ] ; + cosmos.base.v1beta1.Coin min_amount = 3 [(gogoproto.nullable) = false ] ; + cosmos.base.v1beta1.Coin max_amount = 4 [(gogoproto.nullable) = false ] ; string denom_in = 5; string denom_out = 6; - string discount = 7 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; + string discount = 7 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; } message MsgSwapByDenomResponse { - cosmos.base.v1beta1.Coin amount = 1 [(gogoproto.nullable) = false]; - repeated SwapAmountInRoute in_route = 2; - repeated SwapAmountInRoute out_route = 3; - string discount = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; + cosmos.base.v1beta1.Coin amount = 1 [(gogoproto.nullable) = false ] ; + repeated SwapAmountInRoute in_route = 2; + repeated SwapAmountOutRoute out_route = 3; + string spot_price = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; + string discount = 5 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; } - diff --git a/x/amm/client/cli/tx.go b/x/amm/client/cli/tx.go index e2eb6d24c..d7540d077 100644 --- a/x/amm/client/cli/tx.go +++ b/x/amm/client/cli/tx.go @@ -16,6 +16,7 @@ var ( ) const ( + FlagDiscount = "discount" flagPacketTimeoutTimestamp = "packet-timeout-timestamp" listSeparator = "," ) diff --git a/x/amm/client/cli/tx_swap_by_denom.go b/x/amm/client/cli/tx_swap_by_denom.go index 0798f3415..d7ee70400 100644 --- a/x/amm/client/cli/tx_swap_by_denom.go +++ b/x/amm/client/cli/tx_swap_by_denom.go @@ -16,7 +16,6 @@ var _ = strconv.Itoa(0) const ( FlagMinAmount = "min-amount" FlagMaxAmount = "max-amount" - FlagDiscount = "discount" ) func CmdSwapByDenom() *cobra.Command { diff --git a/x/amm/client/cli/tx_swap_exact_amount_in.go b/x/amm/client/cli/tx_swap_exact_amount_in.go index ae590d8b6..67e639e2d 100644 --- a/x/amm/client/cli/tx_swap_exact_amount_in.go +++ b/x/amm/client/cli/tx_swap_exact_amount_in.go @@ -44,6 +44,15 @@ func CmdSwapExactAmountIn() *cobra.Command { } argSwapRouteDenoms := strings.Split(args[3], listSeparator) + discountStr, err := cmd.Flags().GetString(FlagDiscount) + if err != nil { + return err + } + discount, err := sdk.NewDecFromStr(discountStr) + if err != nil { + return err + } + clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err @@ -55,6 +64,7 @@ func CmdSwapExactAmountIn() *cobra.Command { argTokenOutMinAmount, argSwapRoutePoolIds, argSwapRouteDenoms, + discount, ) if err := msg.ValidateBasic(); err != nil { return err @@ -65,5 +75,7 @@ func CmdSwapExactAmountIn() *cobra.Command { flags.AddTxFlagsToCmd(cmd) + cmd.Flags().String(FlagDiscount, "0.0", "discount to apply to the swap fee (only smart contract broker can apply the discount)") + return cmd } diff --git a/x/amm/client/cli/tx_swap_exact_amount_out.go b/x/amm/client/cli/tx_swap_exact_amount_out.go index 5cc374c36..05950cf52 100644 --- a/x/amm/client/cli/tx_swap_exact_amount_out.go +++ b/x/amm/client/cli/tx_swap_exact_amount_out.go @@ -44,6 +44,15 @@ func CmdSwapExactAmountOut() *cobra.Command { } argSwapRouteDenoms := strings.Split(args[3], listSeparator) + discountStr, err := cmd.Flags().GetString(FlagDiscount) + if err != nil { + return err + } + discount, err := sdk.NewDecFromStr(discountStr) + if err != nil { + return err + } + clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err @@ -55,6 +64,7 @@ func CmdSwapExactAmountOut() *cobra.Command { argTokenOutMaxAmount, argSwapRoutePoolIds, argSwapRouteDenoms, + discount, ) if err := msg.ValidateBasic(); err != nil { return err @@ -65,5 +75,7 @@ func CmdSwapExactAmountOut() *cobra.Command { flags.AddTxFlagsToCmd(cmd) + cmd.Flags().String(FlagDiscount, "0.0", "discount to apply to the swap fee (only smart contract broker can apply the discount)") + return cmd } diff --git a/x/amm/keeper/abci.go b/x/amm/keeper/abci.go index 74919686a..08ba8304d 100644 --- a/x/amm/keeper/abci.go +++ b/x/amm/keeper/abci.go @@ -28,7 +28,7 @@ func (k Keeper) ApplySwapRequest(ctx sdk.Context, msg sdk.Msg) error { if err != nil { return err } - _, err = k.RouteExactAmountIn(ctx, sender, msg.Routes, msg.TokenIn, math.Int(msg.TokenOutMinAmount)) + _, err = k.RouteExactAmountIn(ctx, sender, msg.Routes, msg.TokenIn, math.Int(msg.TokenOutMinAmount), msg.Discount) if err != nil { return err } @@ -38,7 +38,7 @@ func (k Keeper) ApplySwapRequest(ctx sdk.Context, msg sdk.Msg) error { if err != nil { return err } - _, err = k.RouteExactAmountOut(ctx, sender, msg.Routes, msg.TokenInMaxAmount, msg.TokenOut) + _, err = k.RouteExactAmountOut(ctx, sender, msg.Routes, msg.TokenInMaxAmount, msg.TokenOut, msg.Discount) if err != nil { return err } diff --git a/x/amm/keeper/abci_test.go b/x/amm/keeper/abci_test.go index e96310234..2e766ddf5 100644 --- a/x/amm/keeper/abci_test.go +++ b/x/amm/keeper/abci_test.go @@ -34,6 +34,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.Elys, 10000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, }, expSwapOrder: []uint64{0}, @@ -52,6 +53,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.Elys, 10000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, &types.MsgSwapExactAmountIn{ Sender: sender.String(), @@ -63,6 +65,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.BaseCurrency, 8000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, }, expSwapOrder: []uint64{1, 0}, @@ -81,6 +84,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.Elys, 11000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, &types.MsgSwapExactAmountIn{ Sender: sender.String(), @@ -92,6 +96,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.BaseCurrency, 8000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, &types.MsgSwapExactAmountIn{ Sender: sender.String(), @@ -103,6 +108,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.BaseCurrency, 1000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, }, expSwapOrder: []uint64{1, 0, 2}, @@ -121,6 +127,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.Elys, 11000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, &types.MsgSwapExactAmountOut{ Sender: sender.String(), @@ -132,6 +139,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenOut: sdk.NewInt64Coin(ptypes.Elys, 8000), TokenInMaxAmount: sdk.NewInt(1000000), + Discount: sdk.ZeroDec(), }, &types.MsgSwapExactAmountIn{ Sender: sender.String(), @@ -143,6 +151,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.BaseCurrency, 1000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, }, expSwapOrder: []uint64{2, 1, 0}, @@ -161,6 +170,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.Elys, 11000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, &types.MsgSwapExactAmountOut{ Sender: sender.String(), @@ -172,6 +182,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenOut: sdk.NewInt64Coin(ptypes.Elys, 8000), TokenInMaxAmount: sdk.NewInt(1000000), + Discount: sdk.ZeroDec(), }, &types.MsgSwapExactAmountIn{ Sender: sender.String(), @@ -187,6 +198,7 @@ func (suite *KeeperTestSuite) TestExecuteSwapRequests() { }, TokenIn: sdk.NewInt64Coin(ptypes.BaseCurrency, 1000), TokenOutMinAmount: sdk.ZeroInt(), + Discount: sdk.ZeroDec(), }, }, expSwapOrder: []uint64{2, 1, 0}, diff --git a/x/amm/keeper/apply_discount.go b/x/amm/keeper/apply_discount.go new file mode 100644 index 000000000..a59442265 --- /dev/null +++ b/x/amm/keeper/apply_discount.go @@ -0,0 +1,24 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/elys-network/elys/x/amm/types" +) + +// ApplyDiscount applies discount to swap fee if applicable +func (k Keeper) ApplyDiscount(ctx sdk.Context, swapFee sdk.Dec, discount sdk.Dec, sender string) (sdk.Dec, sdk.Dec, error) { + if discount.IsZero() { + return swapFee, sdk.ZeroDec(), nil + } + + // check if discount is positive and signer address is broker address otherwise throw an error + if discount.IsPositive() && sender != k.BrokerAddress(ctx) { + return sdk.ZeroDec(), sdk.ZeroDec(), sdkerrors.Wrapf(types.ErrInvalidDiscount, "discount %s is positive and signer address %s is not broker address %s", discount, sender, k.BrokerAddress(ctx)) + } + + // apply discount percentage to swap fee + swapFee = swapFee.Mul(sdk.OneDec().Sub(discount)) + + return swapFee, discount, nil +} diff --git a/x/amm/keeper/apply_discount_test.go b/x/amm/keeper/apply_discount_test.go new file mode 100644 index 000000000..0cf251ad9 --- /dev/null +++ b/x/amm/keeper/apply_discount_test.go @@ -0,0 +1,102 @@ +package keeper_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/types" + keepertest "github.com/elys-network/elys/testutil/keeper" + "github.com/stretchr/testify/require" +) + +func TestApplyDiscount(t *testing.T) { + // Mock context and keeper + k, ctx, _, _ := keepertest.AmmKeeper(t) + + // Define test cases + tests := []struct { + name string + swapFee types.Dec + discount types.Dec + sender string + wantFee types.Dec + wantError bool + }{ + { + name: "Zero discount", + swapFee: types.NewDecWithPrec(100, 2), // 1.00 as an example + discount: types.ZeroDec(), + sender: "testSender", + wantFee: types.NewDecWithPrec(100, 2), + }, + { + name: "Positive discount with valid broker address", + swapFee: types.NewDecWithPrec(100, 2), + discount: types.NewDecWithPrec(10, 2), // 0.10 (10%) + sender: k.BrokerAddress(ctx), + wantFee: types.NewDecWithPrec(90, 2), // 0.90 after discount + }, + { + name: "Positive discount with invalid broker address", + swapFee: types.NewDecWithPrec(100, 2), + discount: types.NewDecWithPrec(10, 2), + sender: "invalidBroker", + wantError: true, + }, + { + name: "Boundary value for discount", + swapFee: types.NewDecWithPrec(100, 2), + discount: types.NewDecWithPrec(9999, 4), // 0.9999 (99.99%) + sender: k.BrokerAddress(ctx), + wantFee: types.NewDecWithPrec(1, 4), // 0.01 after discount + }, + { + name: "Discount greater than swap fee", + swapFee: types.NewDecWithPrec(50, 2), // 0.50 + discount: types.NewDecWithPrec(75, 2), // 0.75 + sender: k.BrokerAddress(ctx), + wantFee: types.NewDecWithPrec(125, 3), + }, + { + name: "Invalid swap fee", + swapFee: types.NewDecWithPrec(-100, 2), // -1.00 (invalid) + discount: types.NewDecWithPrec(10, 2), + sender: "testSender", + wantError: true, + }, + { + name: "Zero swap fee with valid discount", + swapFee: types.ZeroDec(), + discount: types.NewDecWithPrec(10, 2), + sender: k.BrokerAddress(ctx), + wantFee: types.ZeroDec(), + }, + { + name: "Large discount with valid broker address", + swapFee: types.NewDecWithPrec(100, 2), + discount: types.NewDecWithPrec(9000, 4), // 0.90 (90%) + sender: k.BrokerAddress(ctx), + wantFee: types.NewDecWithPrec(10, 2), // 0.10 after discount + }, + { + name: "Large discount with invalid broker address", + swapFee: types.NewDecWithPrec(100, 2), + discount: types.NewDecWithPrec(9000, 4), // 0.90 + sender: "invalidBroker", + wantError: true, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + fee, discount, err := k.ApplyDiscount(ctx, tc.swapFee, tc.discount, tc.sender) + + if tc.wantError { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.wantFee, fee) + require.Equal(t, tc.discount, discount) + } + }) + } +} diff --git a/x/amm/keeper/calc_swap_estimation_by_denom.go b/x/amm/keeper/calc_swap_estimation_by_denom.go index 55f2d365c..cfd4e8968 100644 --- a/x/amm/keeper/calc_swap_estimation_by_denom.go +++ b/x/amm/keeper/calc_swap_estimation_by_denom.go @@ -38,11 +38,11 @@ func (k Keeper) CalcSwapEstimationByDenom( if err != nil { return nil, nil, sdk.Coin{}, sdk.ZeroDec(), err } - spotPrice, tokenOut, err := k.CalcOutRouteSpotPrice(ctx, amount, outRoute) + spotPrice, tokenIn, err := k.CalcOutRouteSpotPrice(ctx, amount, outRoute) if err != nil { return nil, nil, sdk.Coin{}, sdk.ZeroDec(), err } - return nil, outRoute, tokenOut, spotPrice, nil + return nil, outRoute, tokenIn, spotPrice, nil } // if amount denom is neither equal to denomIn nor denomOut, return error diff --git a/x/amm/keeper/msg_server_swap_by_denom.go b/x/amm/keeper/msg_server_swap_by_denom.go index 99b859ff1..35960fda2 100644 --- a/x/amm/keeper/msg_server_swap_by_denom.go +++ b/x/amm/keeper/msg_server_swap_by_denom.go @@ -4,14 +4,103 @@ 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" ) func (k msgServer) SwapByDenom(goCtx context.Context, msg *types.MsgSwapByDenom) (*types.MsgSwapByDenomResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - // TODO: Handling the message - _ = ctx + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } - return &types.MsgSwapByDenomResponse{}, nil + 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 + + inRoute, outRoute, _, spotPrice, err := k.CalcSwapEstimationByDenom(ctx, msg.Amount, msg.DenomIn, msg.DenomOut, baseCurrency) + if err != nil { + return nil, err + } + + // swap to token out with exact amount in using in route + if inRoute != nil { + // check min amount denom is equals to denom out + if msg.MinAmount.Denom != msg.DenomOut { + return nil, sdkerrors.Wrapf(types.ErrInvalidDenom, "min amount denom %s is not equals to denom out %s", msg.MinAmount.Denom, msg.DenomOut) + } + + // convert route []*types.SwapAmountInRoute to []types.SwapAmountInRoute + route := make([]types.SwapAmountInRoute, len(inRoute)) + for i, r := range inRoute { + route[i] = *r + } + + res, err := k.SwapExactAmountIn( + ctx, + &types.MsgSwapExactAmountIn{ + Sender: msg.Sender, + Routes: route, + TokenIn: msg.Amount, + TokenOutMinAmount: msg.MinAmount.Amount, + Discount: msg.Discount, + }, + ) + if err != nil { + return nil, err + } + + return &types.MsgSwapByDenomResponse{ + Amount: sdk.NewCoin(msg.DenomOut, res.TokenOutAmount), + InRoute: inRoute, + OutRoute: nil, + SpotPrice: spotPrice, + Discount: msg.Discount, + }, nil + } + + // swap to token in with exact amount out using out route + if outRoute != nil { + // check max amount denom is equals to denom out + if msg.MaxAmount.Denom != msg.DenomOut { + return nil, sdkerrors.Wrapf(types.ErrInvalidDenom, "max amount denom %s is not equals to denom out %s", msg.MaxAmount.Denom, msg.DenomOut) + } + + // convert route []*types.SwapAmountOutRoute to []types.SwapAmountOutRoute + route := make([]types.SwapAmountOutRoute, len(outRoute)) + for i, r := range outRoute { + route[i] = *r + } + + res, err := k.SwapExactAmountOut( + ctx, + &types.MsgSwapExactAmountOut{ + Sender: msg.Sender, + Routes: route, + TokenInMaxAmount: msg.MaxAmount.Amount, + TokenOut: msg.Amount, + Discount: msg.Discount, + }, + ) + if err != nil { + return nil, err + } + + return &types.MsgSwapByDenomResponse{ + Amount: sdk.NewCoin(msg.DenomOut, res.TokenInAmount), + InRoute: nil, + OutRoute: outRoute, + SpotPrice: spotPrice, + Discount: msg.Discount, + }, nil + } + + // otherwise throw an error + return nil, sdkerrors.Wrapf(types.ErrInvalidSwapMsgType, "neither inRoute nor outRoute are available") } diff --git a/x/amm/keeper/msg_server_swap_by_denom_test.go b/x/amm/keeper/msg_server_swap_by_denom_test.go new file mode 100644 index 000000000..9db124646 --- /dev/null +++ b/x/amm/keeper/msg_server_swap_by_denom_test.go @@ -0,0 +1,164 @@ +package keeper_test + +import ( + "github.com/cometbft/cometbft/crypto/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/elys-network/elys/x/amm/keeper" + "github.com/elys-network/elys/x/amm/types" + ptypes "github.com/elys-network/elys/x/parameter/types" +) + +func (suite *KeeperTestSuite) TestMsgServerSwapByDenom() { + for _, tc := range []struct { + desc string + senderInitBalance sdk.Coins + swapFee sdk.Dec + tokenIn sdk.Coin + tokenOutMin sdk.Int + tokenOut sdk.Coin + expSenderBalance sdk.Coins + expPass bool + }{ + { + desc: "successful execution with positive swap fee", + senderInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)}, + swapFee: sdk.NewDecWithPrec(1, 2), // 1% + tokenIn: sdk.NewInt64Coin(ptypes.Elys, 10000), + tokenOutMin: sdk.ZeroInt(), + tokenOut: sdk.NewInt64Coin(ptypes.BaseCurrency, 9704), + expSenderBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 990000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1009704)}, + expPass: true, + }, + { + desc: "successful execution with zero swap fee", + senderInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)}, + swapFee: sdk.ZeroDec(), + tokenIn: sdk.NewInt64Coin(ptypes.Elys, 10000), + tokenOutMin: sdk.ZeroInt(), + tokenOut: sdk.NewInt64Coin(ptypes.BaseCurrency, 9900), + expSenderBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 990000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1009900)}, + expPass: true, + }, + { + desc: "multiple routes", + senderInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)}, + swapFee: sdk.ZeroDec(), + tokenIn: sdk.NewInt64Coin(ptypes.BaseCurrency, 10000), + tokenOutMin: sdk.ZeroInt(), + tokenOut: sdk.NewInt64Coin("uusdt", 9802), + expSenderBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 990000), sdk.NewInt64Coin("uusdt", 9802)}, + expPass: false, + }, + } { + suite.Run(tc.desc, func() { + suite.SetupTest() + + // bootstrap accounts + sender := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + poolAddr := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + treasuryAddr := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + poolAddr2 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + treasuryAddr2 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + poolCoins := sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)} + pool2Coins := sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin("uusdt", 1000000)} + + // bootstrap balances + err := suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, tc.senderInitBalance) + suite.Require().NoError(err) + err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, sender, tc.senderInitBalance) + suite.Require().NoError(err) + err = suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, poolCoins) + suite.Require().NoError(err) + err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, poolAddr, poolCoins) + suite.Require().NoError(err) + err = suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, pool2Coins) + suite.Require().NoError(err) + err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, poolAddr2, pool2Coins) + suite.Require().NoError(err) + + // execute function + suite.app.AmmKeeper.SetDenomLiquidity(suite.ctx, types.DenomLiquidity{ + Denom: ptypes.Elys, + Liquidity: sdk.NewInt(2000000), + }) + suite.app.AmmKeeper.SetDenomLiquidity(suite.ctx, types.DenomLiquidity{ + Denom: ptypes.BaseCurrency, + Liquidity: sdk.NewInt(1000000), + }) + suite.app.AmmKeeper.SetDenomLiquidity(suite.ctx, types.DenomLiquidity{ + Denom: "uusdt", + Liquidity: sdk.NewInt(1000000), + }) + + pool := types.Pool{ + PoolId: 1, + Address: poolAddr.String(), + RebalanceTreasury: treasuryAddr.String(), + PoolParams: types.PoolParams{ + SwapFee: tc.swapFee, + FeeDenom: ptypes.BaseCurrency, + }, + TotalShares: sdk.Coin{}, + PoolAssets: []types.PoolAsset{ + { + Token: poolCoins[0], + Weight: sdk.NewInt(10), + }, + { + Token: poolCoins[1], + Weight: sdk.NewInt(10), + }, + }, + TotalWeight: sdk.ZeroInt(), + } + pool2 := types.Pool{ + PoolId: 2, + Address: poolAddr2.String(), + RebalanceTreasury: treasuryAddr2.String(), + PoolParams: types.PoolParams{ + SwapFee: tc.swapFee, + FeeDenom: ptypes.BaseCurrency, + }, + TotalShares: sdk.Coin{}, + PoolAssets: []types.PoolAsset{ + { + Token: pool2Coins[0], + Weight: sdk.NewInt(10), + }, + { + Token: pool2Coins[1], + Weight: sdk.NewInt(10), + }, + }, + TotalWeight: sdk.ZeroInt(), + } + suite.app.AmmKeeper.SetPool(suite.ctx, pool) + suite.app.AmmKeeper.SetPool(suite.ctx, pool2) + + msgServer := keeper.NewMsgServerImpl(suite.app.AmmKeeper) + resp, err := msgServer.SwapByDenom( + sdk.WrapSDKContext(suite.ctx), + &types.MsgSwapByDenom{ + Sender: sender.String(), + Amount: tc.tokenIn, + MinAmount: sdk.NewCoin(tc.tokenOut.Denom, tc.tokenOutMin), + MaxAmount: sdk.Coin{}, + DenomIn: tc.tokenIn.Denom, + DenomOut: tc.tokenOut.Denom, + Discount: sdk.ZeroDec(), + }) + if !tc.expPass { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(resp.Amount.String(), tc.tokenOut.String()) + suite.app.AmmKeeper.EndBlocker(suite.ctx) + + // check balance change on sender + balances := suite.app.BankKeeper.GetAllBalances(suite.ctx, sender) + suite.Require().Equal(balances.String(), tc.expSenderBalance.String()) + } + }) + } +} diff --git a/x/amm/keeper/msg_server_swap_exact_amount_in.go b/x/amm/keeper/msg_server_swap_exact_amount_in.go index b3e8fb0fb..48bf4d733 100644 --- a/x/amm/keeper/msg_server_swap_exact_amount_in.go +++ b/x/amm/keeper/msg_server_swap_exact_amount_in.go @@ -19,7 +19,7 @@ func (k msgServer) SwapExactAmountIn(goCtx context.Context, msg *types.MsgSwapEx // Try executing the tx on cached context environment, to filter invalid transactions out cacheCtx, _ := ctx.CacheContext() - tokenOutAmount, err := k.RouteExactAmountIn(cacheCtx, sender, msg.Routes, msg.TokenIn, math.Int(msg.TokenOutMinAmount)) + tokenOutAmount, err := k.RouteExactAmountIn(cacheCtx, sender, msg.Routes, msg.TokenIn, math.Int(msg.TokenOutMinAmount), msg.Discount) if err != nil { return nil, err } diff --git a/x/amm/keeper/msg_server_swap_exact_amount_in_test.go b/x/amm/keeper/msg_server_swap_exact_amount_in_test.go index e10129f2a..e237c7d17 100644 --- a/x/amm/keeper/msg_server_swap_exact_amount_in_test.go +++ b/x/amm/keeper/msg_server_swap_exact_amount_in_test.go @@ -185,6 +185,7 @@ func (suite *KeeperTestSuite) TestMsgServerSwapExactAmountIn() { Routes: tc.swapRoute, TokenIn: tc.tokenIn, TokenOutMinAmount: tc.tokenOutMin, + Discount: sdk.ZeroDec(), }) if !tc.expPass { suite.Require().Error(err) @@ -278,6 +279,7 @@ func (suite *KeeperTestSuite) TestMsgServerSlippageDifferenceWhenSplit() { Routes: swapRoute, TokenIn: tokenIn, TokenOutMinAmount: tokenOutMin, + Discount: sdk.ZeroDec(), }) suite.Require().NoError(err) suite.Require().Equal(resp.TokenOutAmount.String(), tokenOut.Amount.String()) @@ -297,6 +299,7 @@ func (suite *KeeperTestSuite) TestMsgServerSlippageDifferenceWhenSplit() { Routes: swapRoute, TokenIn: sdk.Coin{Denom: tokenIn.Denom, Amount: tokenIn.Amount.Quo(sdk.NewInt(100))}, TokenOutMinAmount: tokenOutMin, + Discount: sdk.ZeroDec(), }) suite.Require().NoError(err) fmt.Printf("outAmount%d: %s\n", i, resp.TokenOutAmount.String()) diff --git a/x/amm/keeper/msg_server_swap_exact_amount_out.go b/x/amm/keeper/msg_server_swap_exact_amount_out.go index ab265a68a..e2ab0e9de 100644 --- a/x/amm/keeper/msg_server_swap_exact_amount_out.go +++ b/x/amm/keeper/msg_server_swap_exact_amount_out.go @@ -17,7 +17,7 @@ func (k msgServer) SwapExactAmountOut(goCtx context.Context, msg *types.MsgSwapE // Try executing the tx on cached context environment, to filter invalid transactions out cacheCtx, _ := ctx.CacheContext() - tokenInAmount, err := k.RouteExactAmountOut(cacheCtx, sender, msg.Routes, msg.TokenInMaxAmount, msg.TokenOut) + tokenInAmount, err := k.RouteExactAmountOut(cacheCtx, sender, msg.Routes, msg.TokenInMaxAmount, msg.TokenOut, msg.Discount) if err != nil { return nil, err } diff --git a/x/amm/keeper/msg_server_swap_exact_amount_out_test.go b/x/amm/keeper/msg_server_swap_exact_amount_out_test.go index ea883a30b..b3666ec6a 100644 --- a/x/amm/keeper/msg_server_swap_exact_amount_out_test.go +++ b/x/amm/keeper/msg_server_swap_exact_amount_out_test.go @@ -182,6 +182,7 @@ func (suite *KeeperTestSuite) TestMsgServerSwapExactAmountOut() { Routes: tc.swapRoutes, TokenOut: tc.tokenOut, TokenInMaxAmount: tc.tokenInMax, + Discount: sdk.ZeroDec(), }) if !tc.expPass { suite.Require().Error(err) diff --git a/x/amm/keeper/params.go b/x/amm/keeper/params.go index 99f4b8be6..1c6675d38 100644 --- a/x/amm/keeper/params.go +++ b/x/amm/keeper/params.go @@ -9,6 +9,7 @@ import ( func (k Keeper) GetParams(ctx sdk.Context) types.Params { return types.NewParams( k.PoolCreationFee(ctx), + k.BrokerAddress(ctx), ) } @@ -22,3 +23,9 @@ func (k Keeper) PoolCreationFee(ctx sdk.Context) (res uint64) { k.paramstore.Get(ctx, types.KeyPoolCreationFee, &res) return } + +// BrokerAddress returns the BrokerAddress param +func (k Keeper) BrokerAddress(ctx sdk.Context) (res string) { + k.paramstore.Get(ctx, types.KeyBrokerAddress, &res) + return +} diff --git a/x/amm/keeper/route_exact_amount_in.go b/x/amm/keeper/route_exact_amount_in.go index c95656832..6a9166cfa 100644 --- a/x/amm/keeper/route_exact_amount_in.go +++ b/x/amm/keeper/route_exact_amount_in.go @@ -15,6 +15,7 @@ func (k Keeper) RouteExactAmountIn( routes []types.SwapAmountInRoute, tokenIn sdk.Coin, tokenOutMinAmount math.Int, + discount sdk.Dec, ) (tokenOutAmount math.Int, err error) { var ( isMultiHopRouted bool @@ -72,6 +73,12 @@ func (k Keeper) RouteExactAmountIn( swapFee = routeSwapFee.Mul((swapFee.Quo(sumOfSwapFees))) } + // Apply discount to swap fee if applicable + swapFee, discount, err = k.ApplyDiscount(ctx, swapFee, discount, sender.String()) + if err != nil { + return math.Int{}, err + } + tokenOutAmount, err = k.SwapExactAmountIn(ctx, sender, pool, tokenIn, route.TokenOutDenom, _outMinAmount, swapFee) if err != nil { ctx.Logger().Error(err.Error()) diff --git a/x/amm/keeper/route_exact_amount_in_test.go b/x/amm/keeper/route_exact_amount_in_test.go index 97f872d7f..739a5d9e0 100644 --- a/x/amm/keeper/route_exact_amount_in_test.go +++ b/x/amm/keeper/route_exact_amount_in_test.go @@ -186,7 +186,9 @@ func (suite *KeeperTestSuite) TestRouteExactAmountIn() { TokenOutDenom: tc.tokenOut.Denom, }, }, - tc.tokenIn, tc.tokenOutMin) + tc.tokenIn, tc.tokenOutMin, + sdk.ZeroDec(), + ) if !tc.expPass { suite.Require().Error(err) } else { diff --git a/x/amm/keeper/route_exact_amount_out.go b/x/amm/keeper/route_exact_amount_out.go index 0f2cfc414..a8b00c356 100644 --- a/x/amm/keeper/route_exact_amount_out.go +++ b/x/amm/keeper/route_exact_amount_out.go @@ -17,6 +17,7 @@ func (k Keeper) RouteExactAmountOut(ctx sdk.Context, routes []types.SwapAmountOutRoute, tokenInMaxAmount math.Int, tokenOut sdk.Coin, + discount sdk.Dec, ) (tokenInAmount math.Int, err error) { isMultiHopRouted, routeSwapFee, sumOfSwapFees := false, sdk.Dec{}, sdk.Dec{} route := types.SwapAmountOutRoutes(routes) @@ -93,6 +94,12 @@ func (k Keeper) RouteExactAmountOut(ctx sdk.Context, swapFee = routeSwapFee.Mul((swapFee.Quo(sumOfSwapFees))) } + // Apply discount to swap fee if applicable + swapFee, discount, err = k.ApplyDiscount(ctx, swapFee, discount, sender.String()) + if err != nil { + return math.Int{}, err + } + _tokenInAmount, swapErr := k.SwapExactAmountOut(ctx, sender, pool, route.TokenInDenom, insExpected[i], _tokenOut, swapFee) if swapErr != nil { return math.Int{}, swapErr diff --git a/x/amm/keeper/route_exact_amount_out_test.go b/x/amm/keeper/route_exact_amount_out_test.go index 5ba76f5a4..4dc83d627 100644 --- a/x/amm/keeper/route_exact_amount_out_test.go +++ b/x/amm/keeper/route_exact_amount_out_test.go @@ -182,7 +182,9 @@ func (suite *KeeperTestSuite) TestRouteExactAmountOut() { PoolId: pool.PoolId, TokenInDenom: tc.tokenIn.Denom, }, - }, tc.tokenInMax, tc.tokenOut) + }, tc.tokenInMax, tc.tokenOut, + sdk.ZeroDec(), + ) if !tc.expPass { suite.Require().Error(err) } else { diff --git a/x/amm/migrations/new_migrator.go b/x/amm/migrations/new_migrator.go new file mode 100644 index 000000000..ae9476b4a --- /dev/null +++ b/x/amm/migrations/new_migrator.go @@ -0,0 +1,13 @@ +package migrations + +import ( + "github.com/elys-network/elys/x/amm/keeper" +) + +type Migrator struct { + keeper keeper.Keeper +} + +func NewMigrator(keeper keeper.Keeper) Migrator { + return Migrator{keeper: keeper} +} diff --git a/x/amm/migrations/v2_migration.go b/x/amm/migrations/v2_migration.go new file mode 100644 index 000000000..cee53347e --- /dev/null +++ b/x/amm/migrations/v2_migration.go @@ -0,0 +1,12 @@ +package migrations + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/elys-network/elys/x/amm/types" +) + +func (m Migrator) V2Migration(ctx sdk.Context) error { + params := types.DefaultParams() + m.keeper.SetParams(ctx, params) + return nil +} diff --git a/x/amm/module.go b/x/amm/module.go index 32be53d28..f732a106f 100644 --- a/x/amm/module.go +++ b/x/amm/module.go @@ -19,6 +19,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" "github.com/elys-network/elys/x/amm/client/cli" "github.com/elys-network/elys/x/amm/keeper" + "github.com/elys-network/elys/x/amm/migrations" "github.com/elys-network/elys/x/amm/types" ) @@ -115,6 +116,11 @@ func NewAppModule( func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + m := migrations.NewMigrator(am.keeper) + err := cfg.RegisterMigration(types.ModuleName, 1, m.V2Migration) + if err != nil { + panic(err) + } } // RegisterInvariants registers the invariants of the module. If an invariant deviates from its predicted value, the InvariantRegistry triggers appropriate logic (most often the chain will be halted) @@ -138,7 +144,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion is a sequence number for state-breaking change of the module. It should be incremented on each consensus-breaking change introduced by the module. To avoid wrong/empty versions, the initial version should be set to 1 -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock contains the logic that is automatically triggered at the beginning of each block func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/amm/types/codec.go b/x/amm/types/codec.go index 183449a42..241be977f 100644 --- a/x/amm/types/codec.go +++ b/x/amm/types/codec.go @@ -12,9 +12,9 @@ func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgJoinPool{}, "amm/JoinPool", nil) cdc.RegisterConcrete(&MsgExitPool{}, "amm/ExitPool", nil) cdc.RegisterConcrete(&MsgSwapExactAmountIn{}, "amm/SwapExactAmountIn", nil) - cdc.RegisterConcrete(&MsgFeedMultipleExternalLiquidity{}, "amm/FeedMultipleExternalLiquidity", nil) cdc.RegisterConcrete(&MsgSwapExactAmountOut{}, "amm/SwapExactAmountOut", nil) cdc.RegisterConcrete(&MsgSwapByDenom{}, "amm/SwapByDenom", nil) + cdc.RegisterConcrete(&MsgFeedMultipleExternalLiquidity{}, "amm/FeedMultipleExternalLiquidity", nil) // this line is used by starport scaffolding # 2 } @@ -25,10 +25,8 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { &MsgExitPool{}, &MsgSwapExactAmountIn{}, &MsgSwapExactAmountOut{}, - &MsgFeedMultipleExternalLiquidity{}, - ) - registry.RegisterImplementations((*sdk.Msg)(nil), &MsgSwapByDenom{}, + &MsgFeedMultipleExternalLiquidity{}, ) // this line is used by starport scaffolding # 3 diff --git a/x/amm/types/errors.go b/x/amm/types/errors.go index e5bf16045..e25bed213 100644 --- a/x/amm/types/errors.go +++ b/x/amm/types/errors.go @@ -25,10 +25,11 @@ 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") - ErrPoolNotFound = sdkerrors.Register(ModuleName, 102, "pool not found") - ErrAmountTooLow = sdkerrors.Register(ModuleName, 103, "amount too low") - ErrInvalidDenom = sdkerrors.Register(ModuleName, 104, "invalid denom") + 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") + ErrInvalidDiscount = sdkerrors.Register(ModuleName, 105, "invalid discount") ) const ( diff --git a/x/amm/types/message_swap_exact_amount_in.go b/x/amm/types/message_swap_exact_amount_in.go index d27f83bb9..759286946 100644 --- a/x/amm/types/message_swap_exact_amount_in.go +++ b/x/amm/types/message_swap_exact_amount_in.go @@ -10,7 +10,7 @@ const TypeMsgSwapExactAmountIn = "swap_exact_amount_in" var _ sdk.Msg = &MsgSwapExactAmountIn{} -func NewMsgSwapExactAmountIn(sender string, tokenIn sdk.Coin, tokenOutMinAmount math.Int, swapRoutePoolIds []uint64, swapRouteDenoms []string) *MsgSwapExactAmountIn { +func NewMsgSwapExactAmountIn(sender string, tokenIn sdk.Coin, tokenOutMinAmount math.Int, swapRoutePoolIds []uint64, swapRouteDenoms []string, discount sdk.Dec) *MsgSwapExactAmountIn { if len(swapRoutePoolIds) != len(swapRouteDenoms) { return nil // or raise an error as the input lists should have the same length } @@ -29,6 +29,7 @@ func NewMsgSwapExactAmountIn(sender string, tokenIn sdk.Coin, tokenOutMinAmount Routes: routes, TokenIn: tokenIn, TokenOutMinAmount: tokenOutMinAmount, + Discount: discount, } } diff --git a/x/amm/types/message_swap_exact_amount_out.go b/x/amm/types/message_swap_exact_amount_out.go index 0e835e3d4..84eb5889c 100644 --- a/x/amm/types/message_swap_exact_amount_out.go +++ b/x/amm/types/message_swap_exact_amount_out.go @@ -10,7 +10,7 @@ const TypeMsgSwapExactAmountOut = "swap_exact_amount_out" var _ sdk.Msg = &MsgSwapExactAmountOut{} -func NewMsgSwapExactAmountOut(sender string, tokenOut sdk.Coin, tokenInMaxAmount math.Int, swapRoutePoolIds []uint64, swapRouteDenoms []string) *MsgSwapExactAmountOut { +func NewMsgSwapExactAmountOut(sender string, tokenOut sdk.Coin, tokenInMaxAmount math.Int, swapRoutePoolIds []uint64, swapRouteDenoms []string, discount sdk.Dec) *MsgSwapExactAmountOut { if len(swapRoutePoolIds) != len(swapRouteDenoms) { return nil // or raise an error as the input lists should have the same length } @@ -29,6 +29,7 @@ func NewMsgSwapExactAmountOut(sender string, tokenOut sdk.Coin, tokenInMaxAmount Routes: routes, TokenOut: tokenOut, TokenInMaxAmount: tokenInMaxAmount, + Discount: discount, } } diff --git a/x/amm/types/params.go b/x/amm/types/params.go index 6788bf113..4757a17e4 100644 --- a/x/amm/types/params.go +++ b/x/amm/types/params.go @@ -11,8 +11,10 @@ var _ paramtypes.ParamSet = (*Params)(nil) var ( KeyPoolCreationFee = []byte("PoolCreationFee") + KeyBrokerAddress = []byte("BrokerAddress") // TODO: Determine the default value DefaultPoolCreationFee uint64 = 0 + DefaultBrokerAddress string = "" ) // ParamKeyTable the param key table for launch module @@ -23,9 +25,11 @@ func ParamKeyTable() paramtypes.KeyTable { // NewParams creates a new Params instance func NewParams( poolCreationFee uint64, + brokerAddress string, ) Params { return Params{ PoolCreationFee: poolCreationFee, + BrokerAddress: brokerAddress, } } @@ -33,6 +37,7 @@ func NewParams( func DefaultParams() Params { return NewParams( DefaultPoolCreationFee, + DefaultBrokerAddress, ) } @@ -40,6 +45,7 @@ func DefaultParams() Params { func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ paramtypes.NewParamSetPair(KeyPoolCreationFee, &p.PoolCreationFee, validatePoolCreationFee), + paramtypes.NewParamSetPair(KeyBrokerAddress, &p.BrokerAddress, validateBrokerAddress), } } @@ -48,6 +54,9 @@ func (p Params) Validate() error { if err := validatePoolCreationFee(p.PoolCreationFee); err != nil { return err } + if err := validateBrokerAddress(p.BrokerAddress); err != nil { + return err + } return nil } @@ -70,3 +79,16 @@ func validatePoolCreationFee(v interface{}) error { return nil } + +// validateBrokerAddress validates the BrokerAddress param +func validateBrokerAddress(v interface{}) error { + brokerAddress, ok := v.(string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", v) + } + + // TODO implement validation + _ = brokerAddress + + return nil +} diff --git a/x/amm/types/params.pb.go b/x/amm/types/params.pb.go index 99f1539a6..f75444f0f 100644 --- a/x/amm/types/params.pb.go +++ b/x/amm/types/params.pb.go @@ -26,6 +26,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Params defines the parameters for the module. type Params struct { PoolCreationFee uint64 `protobuf:"varint,1,opt,name=pool_creation_fee,json=poolCreationFee,proto3" json:"pool_creation_fee,omitempty"` + BrokerAddress string `protobuf:"bytes,2,opt,name=broker_address,json=brokerAddress,proto3" json:"broker_address,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -67,6 +68,13 @@ func (m *Params) GetPoolCreationFee() uint64 { return 0 } +func (m *Params) GetBrokerAddress() string { + if m != nil { + return m.BrokerAddress + } + return "" +} + func init() { proto.RegisterType((*Params)(nil), "elys.amm.Params") } @@ -74,19 +82,21 @@ func init() { func init() { proto.RegisterFile("elys/amm/params.proto", fileDescriptor_1209ca218537a425) } var fileDescriptor_1209ca218537a425 = []byte{ - // 184 bytes of a gzipped FileDescriptorProto + // 215 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4d, 0xcd, 0xa9, 0x2c, 0xd6, 0x4f, 0xcc, 0xcd, 0xd5, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x00, 0x09, 0xeb, 0x25, 0xe6, 0xe6, 0x4a, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, - 0x05, 0xf5, 0x41, 0x2c, 0x88, 0xbc, 0x92, 0x15, 0x17, 0x5b, 0x00, 0x58, 0xbd, 0x90, 0x16, 0x97, + 0x05, 0xf5, 0x41, 0x2c, 0x88, 0xbc, 0x52, 0x22, 0x17, 0x5b, 0x00, 0x58, 0xbd, 0x90, 0x16, 0x97, 0x60, 0x41, 0x7e, 0x7e, 0x4e, 0x7c, 0x72, 0x51, 0x6a, 0x62, 0x49, 0x66, 0x7e, 0x5e, 0x7c, 0x5a, 0x6a, 0xaa, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x3f, 0x48, 0xc2, 0x19, 0x2a, 0xee, 0x96, - 0x9a, 0x6a, 0xc5, 0x32, 0x63, 0x81, 0x3c, 0x83, 0x93, 0xd3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, - 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, - 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa4, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, - 0x83, 0x1c, 0xa0, 0x9b, 0x97, 0x5a, 0x52, 0x9e, 0x5f, 0x94, 0x0d, 0xe6, 0xe8, 0x57, 0x80, 0x9d, - 0x59, 0x52, 0x59, 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0x76, 0x86, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, - 0x80, 0xf9, 0xf7, 0xd8, 0xbf, 0x00, 0x00, 0x00, + 0x9a, 0x2a, 0xa4, 0xca, 0xc5, 0x97, 0x54, 0x94, 0x9f, 0x9d, 0x5a, 0x14, 0x9f, 0x98, 0x92, 0x52, + 0x94, 0x5a, 0x5c, 0x2c, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x19, 0xc4, 0x0b, 0x11, 0x75, 0x84, 0x08, + 0x5a, 0xb1, 0xcc, 0x58, 0x20, 0xcf, 0xe0, 0xe4, 0x74, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, + 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, + 0x72, 0x0c, 0x51, 0x1a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x20, + 0x77, 0xea, 0xe6, 0xa5, 0x96, 0x94, 0xe7, 0x17, 0x65, 0x83, 0x39, 0xfa, 0x15, 0x60, 0xdf, 0x94, + 0x54, 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, 0x5d, 0x6b, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xe7, + 0xdf, 0x05, 0x9b, 0xe6, 0x00, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -109,6 +119,13 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.BrokerAddress) > 0 { + i -= len(m.BrokerAddress) + copy(dAtA[i:], m.BrokerAddress) + i = encodeVarintParams(dAtA, i, uint64(len(m.BrokerAddress))) + i-- + dAtA[i] = 0x12 + } if m.PoolCreationFee != 0 { i = encodeVarintParams(dAtA, i, uint64(m.PoolCreationFee)) i-- @@ -137,6 +154,10 @@ func (m *Params) Size() (n int) { if m.PoolCreationFee != 0 { n += 1 + sovParams(uint64(m.PoolCreationFee)) } + l = len(m.BrokerAddress) + if l > 0 { + n += 1 + l + sovParams(uint64(l)) + } return n } @@ -194,6 +215,38 @@ func (m *Params) Unmarshal(dAtA []byte) error { break } } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BrokerAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + 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 ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BrokerAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/amm/types/tx.pb.go b/x/amm/types/tx.pb.go index 72b4e5c25..bb6d309a6 100644 --- a/x/amm/types/tx.pb.go +++ b/x/amm/types/tx.pb.go @@ -366,6 +366,7 @@ type MsgSwapExactAmountIn struct { Routes []SwapAmountInRoute `protobuf:"bytes,2,rep,name=routes,proto3" json:"routes"` TokenIn types.Coin `protobuf:"bytes,3,opt,name=token_in,json=tokenIn,proto3" json:"token_in"` TokenOutMinAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=token_out_min_amount,json=tokenOutMinAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"token_out_min_amount"` + Discount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=discount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"discount"` } func (m *MsgSwapExactAmountIn) Reset() { *m = MsgSwapExactAmountIn{} } @@ -424,6 +425,7 @@ func (m *MsgSwapExactAmountIn) GetTokenIn() types.Coin { type MsgSwapExactAmountInResponse struct { TokenOutAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=token_out_amount,json=tokenOutAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"token_out_amount"` + Discount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=discount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"discount"` } func (m *MsgSwapExactAmountInResponse) Reset() { *m = MsgSwapExactAmountInResponse{} } @@ -464,6 +466,7 @@ type MsgSwapExactAmountOut struct { Routes []SwapAmountOutRoute `protobuf:"bytes,2,rep,name=routes,proto3" json:"routes"` TokenOut types.Coin `protobuf:"bytes,3,opt,name=token_out,json=tokenOut,proto3" json:"token_out"` TokenInMaxAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=token_in_max_amount,json=tokenInMaxAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"token_in_max_amount"` + Discount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=discount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"discount"` } func (m *MsgSwapExactAmountOut) Reset() { *m = MsgSwapExactAmountOut{} } @@ -522,6 +525,7 @@ func (m *MsgSwapExactAmountOut) GetTokenOut() types.Coin { type MsgSwapExactAmountOutResponse struct { TokenInAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=token_in_amount,json=tokenInAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"token_in_amount"` + Discount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=discount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"discount"` } func (m *MsgSwapExactAmountOutResponse) Reset() { *m = MsgSwapExactAmountOutResponse{} } @@ -832,10 +836,11 @@ func (m *MsgSwapByDenom) GetDenomOut() string { } type MsgSwapByDenomResponse struct { - Amount types.Coin `protobuf:"bytes,1,opt,name=amount,proto3" json:"amount"` - InRoute []*SwapAmountInRoute `protobuf:"bytes,2,rep,name=in_route,json=inRoute,proto3" json:"in_route,omitempty"` - OutRoute []*SwapAmountInRoute `protobuf:"bytes,3,rep,name=out_route,json=outRoute,proto3" json:"out_route,omitempty"` - Discount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=discount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"discount"` + Amount types.Coin `protobuf:"bytes,1,opt,name=amount,proto3" json:"amount"` + InRoute []*SwapAmountInRoute `protobuf:"bytes,2,rep,name=in_route,json=inRoute,proto3" json:"in_route,omitempty"` + OutRoute []*SwapAmountOutRoute `protobuf:"bytes,3,rep,name=out_route,json=outRoute,proto3" json:"out_route,omitempty"` + SpotPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=spot_price,json=spotPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"spot_price"` + Discount github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=discount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"discount"` } func (m *MsgSwapByDenomResponse) Reset() { *m = MsgSwapByDenomResponse{} } @@ -885,7 +890,7 @@ func (m *MsgSwapByDenomResponse) GetInRoute() []*SwapAmountInRoute { return nil } -func (m *MsgSwapByDenomResponse) GetOutRoute() []*SwapAmountInRoute { +func (m *MsgSwapByDenomResponse) GetOutRoute() []*SwapAmountOutRoute { if m != nil { return m.OutRoute } @@ -914,79 +919,82 @@ func init() { func init() { proto.RegisterFile("elys/amm/tx.proto", fileDescriptor_ed7ddafd861f6b7f) } var fileDescriptor_ed7ddafd861f6b7f = []byte{ - // 1145 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xcf, 0x3a, 0xae, 0x63, 0x3f, 0x37, 0xff, 0x36, 0x69, 0xe3, 0xb8, 0x8d, 0x63, 0x16, 0x29, - 0x58, 0x95, 0xba, 0x56, 0x83, 0xf8, 0x17, 0x55, 0x40, 0xdd, 0x24, 0xc8, 0x55, 0xad, 0x54, 0x5b, - 0xa9, 0x42, 0x20, 0xb0, 0x36, 0xf6, 0xd4, 0x19, 0xc5, 0x3b, 0x63, 0x3c, 0xb3, 0xc4, 0x81, 0x03, - 0x12, 0x07, 0xe0, 0x06, 0x67, 0xbe, 0x02, 0x77, 0x3e, 0x43, 0x8f, 0x3d, 0xa2, 0x1e, 0x22, 0x94, - 0x88, 0xef, 0x81, 0x66, 0x76, 0x76, 0xd6, 0x1b, 0xff, 0x89, 0x63, 0x38, 0xc5, 0x3b, 0x6f, 0x7e, - 0xef, 0xbd, 0xf9, 0xfd, 0xde, 0x7b, 0x33, 0x81, 0x65, 0xd4, 0x3e, 0x65, 0x65, 0xd7, 0xf3, 0xca, - 0xbc, 0x67, 0x77, 0xba, 0x94, 0x53, 0x33, 0x2d, 0x96, 0x6c, 0xd7, 0xf3, 0xf2, 0xab, 0x2d, 0xda, - 0xa2, 0x72, 0xb1, 0x2c, 0x7e, 0x05, 0xf6, 0x7c, 0xa1, 0x41, 0x99, 0x47, 0x59, 0xf9, 0xd0, 0x65, - 0xa8, 0xfc, 0xed, 0x83, 0x43, 0xc4, 0xdd, 0x07, 0xe5, 0x06, 0xc5, 0x44, 0xd9, 0xd7, 0xb5, 0x4b, - 0x76, 0xe2, 0x76, 0xea, 0x5d, 0xea, 0x73, 0xa4, 0x4c, 0x79, 0x6d, 0xea, 0x50, 0xda, 0xae, 0x77, - 0xdc, 0xae, 0xeb, 0xb1, 0x01, 0x98, 0xb4, 0xb9, 0x8c, 0x21, 0x1e, 0x98, 0xac, 0xdf, 0x0d, 0x98, - 0xaf, 0xb1, 0xd6, 0xe3, 0x2e, 0x72, 0x39, 0x7a, 0x46, 0x69, 0xdb, 0xbc, 0x0d, 0x29, 0x86, 0x48, - 0x13, 0x75, 0x73, 0x46, 0xd1, 0x28, 0x65, 0x1c, 0xf5, 0x65, 0xbe, 0x07, 0xd9, 0x3e, 0xcf, 0xb9, - 0x44, 0xd1, 0x28, 0x65, 0xb7, 0x57, 0xed, 0xf0, 0x44, 0xb6, 0x00, 0x3f, 0x93, 0x36, 0x07, 0x3a, - 0xfa, 0xb7, 0xb9, 0xa3, 0x60, 0x32, 0x28, 0xcb, 0xcd, 0x16, 0x67, 0x4b, 0xd9, 0xed, 0x95, 0x38, - 0xec, 0x91, 0xb0, 0x55, 0x92, 0xaf, 0xce, 0x36, 0x67, 0x02, 0xac, 0x5c, 0x60, 0xd6, 0x43, 0xb8, - 0x15, 0xcb, 0xcd, 0x41, 0xac, 0x43, 0x09, 0x43, 0xe6, 0xdb, 0x30, 0x27, 0x9d, 0xe2, 0xa6, 0x4c, - 0x32, 0x59, 0x81, 0xf3, 0xb3, 0xcd, 0x94, 0xd8, 0x52, 0xdd, 0x75, 0x52, 0xc2, 0x54, 0x6d, 0x5a, - 0x3f, 0x26, 0x20, 0x5b, 0x63, 0xad, 0x27, 0x14, 0x93, 0xb1, 0x07, 0x5b, 0x8b, 0x9c, 0x89, 0x43, - 0x25, 0x43, 0x07, 0xe6, 0x1e, 0x2c, 0x78, 0x6e, 0xaf, 0xee, 0x7a, 0xd4, 0x27, 0x9c, 0xd5, 0x31, - 0x51, 0xd9, 0xaf, 0xdb, 0x81, 0x4c, 0xb6, 0x90, 0xc9, 0x56, 0x32, 0xd9, 0x8f, 0x29, 0x26, 0xea, - 0x0c, 0x37, 0x3d, 0xb7, 0xf7, 0x28, 0x40, 0x55, 0x89, 0xf9, 0x39, 0x2c, 0xb1, 0x23, 0xb7, 0x8b, - 0x94, 0xa3, 0x3a, 0xf5, 0x79, 0x2e, 0x29, 0x32, 0xa8, 0xd8, 0x62, 0xf7, 0x9b, 0xb3, 0xcd, 0xad, - 0x16, 0xe6, 0x47, 0xfe, 0xa1, 0xdd, 0xa0, 0x5e, 0x59, 0x55, 0x40, 0xf0, 0xe7, 0x3e, 0x6b, 0x1e, - 0x97, 0xf9, 0x69, 0x07, 0x31, 0xbb, 0x4a, 0xb8, 0xb3, 0x20, 0xfd, 0x04, 0x9e, 0x0f, 0x7c, 0x6e, - 0xbe, 0x05, 0x37, 0x09, 0xad, 0x77, 0x91, 0xe7, 0x62, 0x82, 0x49, 0x2b, 0x77, 0xa3, 0x68, 0x94, - 0xd2, 0x4e, 0x96, 0x50, 0x27, 0x5c, 0xb2, 0xfe, 0x30, 0x60, 0xa5, 0x8f, 0x04, 0xcd, 0xe0, 0xb0, - 0xa4, 0x8c, 0xff, 0x25, 0xa9, 0x1d, 0x48, 0x73, 0x7a, 0x8c, 0x88, 0xe0, 0x2b, 0x31, 0x19, 0x5f, - 0x73, 0x12, 0x50, 0x25, 0xd6, 0xcf, 0x81, 0x64, 0x7b, 0x3d, 0xcc, 0xa7, 0x93, 0xec, 0x33, 0x58, - 0xf4, 0x30, 0xd1, 0x92, 0x89, 0x53, 0x4d, 0xa8, 0xd9, 0xbc, 0x87, 0x89, 0xd2, 0x4c, 0x9c, 0xe2, - 0x05, 0x2c, 0xc6, 0xf8, 0xc1, 0x64, 0x4a, 0xcd, 0xe6, 0xfb, 0xe8, 0xa9, 0x12, 0x73, 0x0b, 0x16, - 0x03, 0x76, 0xa8, 0xcf, 0xeb, 0x4d, 0x44, 0xa8, 0x27, 0x55, 0xcb, 0x38, 0xf3, 0x72, 0xf9, 0xc0, - 0xe7, 0xbb, 0x62, 0xd1, 0x7a, 0x2e, 0x65, 0x0b, 0x89, 0xd0, 0xb2, 0x3d, 0x84, 0x8c, 0x86, 0x4f, - 0xca, 0x6e, 0x3a, 0xf4, 0x6c, 0xfd, 0x94, 0x80, 0xd5, 0x1a, 0x6b, 0x3d, 0x3f, 0x71, 0x3b, 0x7b, - 0x3d, 0xb7, 0xc1, 0x75, 0x56, 0xa3, 0x78, 0xfe, 0x08, 0x52, 0x72, 0xc6, 0x30, 0x15, 0xeb, 0x4e, - 0xd4, 0xb7, 0xc2, 0x49, 0x88, 0x77, 0xc4, 0x1e, 0x15, 0x4d, 0x01, 0x62, 0x65, 0x30, 0x2b, 0x67, - 0xc5, 0xc4, 0x65, 0x60, 0xd6, 0x61, 0x35, 0x22, 0x29, 0xd2, 0x73, 0x4a, 0x05, 0x96, 0xc3, 0xf3, - 0xd7, 0x42, 0x85, 0xad, 0x1e, 0xdc, 0x1d, 0xc6, 0x43, 0x7f, 0x77, 0x44, 0x09, 0xa8, 0xe0, 0x53, - 0x76, 0x47, 0x18, 0x5c, 0x45, 0xfe, 0x25, 0x21, 0x67, 0xda, 0xa5, 0xd0, 0xa2, 0xe2, 0x46, 0x69, - 0xb0, 0x73, 0x49, 0x83, 0xbb, 0xc3, 0x34, 0x38, 0xf0, 0xf9, 0x30, 0x11, 0x62, 0xe5, 0x32, 0xa1, - 0x0a, 0xba, 0x5c, 0xcc, 0xaf, 0x60, 0x25, 0x94, 0xb0, 0x1e, 0x0d, 0xc2, 0x29, 0x55, 0x58, 0x52, - 0xe2, 0xd6, 0xc2, 0xd1, 0x68, 0x9d, 0xc0, 0xc6, 0x50, 0x26, 0xb4, 0x0a, 0x2f, 0xc2, 0x5e, 0x89, - 0x2a, 0x60, 0x3a, 0x11, 0xe6, 0x55, 0x6c, 0x15, 0xf8, 0x7b, 0x28, 0xd6, 0x58, 0x6b, 0x1f, 0xa1, - 0x66, 0xcd, 0x6f, 0x73, 0xdc, 0x69, 0xa3, 0xbd, 0x1e, 0x47, 0x5d, 0xe2, 0xb6, 0x9f, 0xe2, 0x6f, - 0x7c, 0xdc, 0xc4, 0xfc, 0x74, 0xa4, 0x1a, 0x9f, 0x40, 0xa6, 0x1d, 0x6e, 0x1a, 0x6c, 0x8a, 0x01, - 0x3f, 0x8a, 0xd3, 0x08, 0x63, 0xdd, 0x83, 0xd2, 0x55, 0xc1, 0x43, 0x02, 0xac, 0x3f, 0x0d, 0x58, - 0x92, 0x57, 0x61, 0x90, 0xf8, 0x2e, 0xea, 0xf0, 0x23, 0x73, 0x15, 0x6e, 0xc8, 0xbb, 0x54, 0x25, - 0x16, 0x7c, 0x98, 0xfb, 0x90, 0x52, 0x14, 0x25, 0xae, 0x4d, 0xd1, 0x2e, 0x6a, 0x38, 0x0a, 0x6d, - 0xee, 0xc2, 0x8d, 0xa6, 0x08, 0x23, 0xab, 0xe5, 0xfa, 0x6e, 0x02, 0xb0, 0xf5, 0x1d, 0x2c, 0x0f, - 0x52, 0xba, 0x76, 0xe9, 0xd2, 0xd6, 0x43, 0xfb, 0x29, 0x2c, 0xab, 0x29, 0x2b, 0xd1, 0x75, 0x4c, - 0x5e, 0x52, 0xc5, 0x6d, 0x3e, 0xe2, 0xf6, 0x32, 0x11, 0x8a, 0xda, 0x45, 0x37, 0x5a, 0xaa, 0x92, - 0x97, 0xd4, 0xfa, 0x27, 0x01, 0x0b, 0xaa, 0xae, 0x2a, 0xa7, 0x72, 0x98, 0x8e, 0x14, 0xf3, 0x83, - 0x18, 0x69, 0x13, 0xf4, 0x46, 0xc8, 0xd2, 0xc7, 0x00, 0x7d, 0x63, 0x69, 0xc2, 0xc6, 0xca, 0xe8, - 0x1b, 0x46, 0xe2, 0xe3, 0x0d, 0x35, 0x11, 0x3e, 0x6c, 0x1d, 0x73, 0x1d, 0xd2, 0xf2, 0xee, 0x10, - 0xc3, 0x35, 0xb8, 0x3e, 0xe6, 0xe4, 0x77, 0x95, 0x98, 0x77, 0x20, 0x13, 0x98, 0x44, 0xcb, 0xa7, - 0xa4, 0x2d, 0xd8, 0x2b, 0x3a, 0xfa, 0x09, 0xa4, 0x9b, 0x98, 0x35, 0x64, 0xd4, 0xb9, 0xa9, 0x04, - 0xd6, 0x78, 0xeb, 0xd7, 0x04, 0xdc, 0x8e, 0xf3, 0xac, 0x1b, 0x37, 0xe2, 0xd5, 0xb8, 0x1e, 0xaf, - 0xef, 0x43, 0x1a, 0x93, 0xe0, 0x59, 0x3b, 0xc1, 0x8d, 0xe3, 0xcc, 0xe1, 0xe0, 0x87, 0xf9, 0x21, - 0x64, 0xc4, 0xa4, 0x0e, 0x80, 0xb3, 0x57, 0x03, 0xd3, 0x54, 0xcd, 0xcb, 0x18, 0x23, 0xc9, 0xff, - 0xc6, 0xc8, 0xf6, 0x9b, 0x24, 0xcc, 0xd6, 0x58, 0xcb, 0xdc, 0x07, 0xe8, 0x7b, 0x4f, 0xaf, 0x45, - 0x89, 0xc4, 0x1e, 0xb3, 0xf9, 0xcd, 0x11, 0x06, 0x4d, 0xe3, 0xa7, 0x90, 0xd6, 0x8f, 0xd7, 0x5b, - 0xb1, 0xcd, 0xe1, 0x72, 0x7e, 0x63, 0xe8, 0x72, 0xbf, 0x07, 0xfd, 0x96, 0x8a, 0x7b, 0x08, 0x97, - 0x2f, 0x79, 0x18, 0x78, 0x70, 0x7c, 0x09, 0xcb, 0x83, 0xcf, 0x85, 0x42, 0x0c, 0x33, 0x60, 0xcf, - 0x6f, 0x8d, 0xb7, 0x6b, 0xe7, 0x5f, 0x83, 0x39, 0xe4, 0x22, 0xdc, 0x1c, 0x87, 0x3e, 0xf0, 0x79, - 0xfe, 0x9d, 0x2b, 0x36, 0x68, 0xff, 0x3f, 0xc0, 0xc6, 0xf8, 0x29, 0x7f, 0x2f, 0xe6, 0x69, 0xec, - 0xde, 0xfc, 0xf6, 0xe4, 0x7b, 0x75, 0x02, 0x55, 0xc8, 0xf6, 0xcf, 0xa1, 0xdc, 0x40, 0xe2, 0xca, - 0x92, 0x2f, 0x8e, 0xb2, 0x84, 0xae, 0x2a, 0x95, 0x57, 0xe7, 0x05, 0xe3, 0xf5, 0x79, 0xc1, 0xf8, - 0xfb, 0xbc, 0x60, 0xfc, 0x76, 0x51, 0x98, 0x79, 0x7d, 0x51, 0x98, 0xf9, 0xeb, 0xa2, 0x30, 0xf3, - 0x45, 0xa9, 0xaf, 0x50, 0x85, 0x97, 0xfb, 0x04, 0xf1, 0x13, 0xda, 0x3d, 0x96, 0x1f, 0xe5, 0x5e, - 0xf0, 0x1f, 0xa8, 0x28, 0xd7, 0xc3, 0x94, 0xfc, 0x9f, 0xef, 0xdd, 0x7f, 0x03, 0x00, 0x00, 0xff, - 0xff, 0x7e, 0xa8, 0xd6, 0x96, 0x9a, 0x0e, 0x00, 0x00, + // 1191 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0x41, 0x4f, 0x1b, 0xc7, + 0x17, 0x67, 0x0d, 0x18, 0xfb, 0x39, 0x84, 0xb0, 0x40, 0x30, 0x4e, 0x30, 0xfe, 0xef, 0x5f, 0xa2, + 0x56, 0xa4, 0xac, 0x15, 0xaa, 0xb6, 0x0a, 0x8a, 0xda, 0xc6, 0x01, 0x2a, 0x47, 0xb1, 0x40, 0x1b, + 0x29, 0xaa, 0x5a, 0xb5, 0xab, 0xc5, 0x9e, 0x98, 0x15, 0xde, 0x99, 0xad, 0x67, 0xb6, 0x98, 0xf6, + 0x50, 0xa9, 0x97, 0x5e, 0x7b, 0xee, 0x57, 0xe8, 0xbd, 0x5f, 0xa0, 0x3d, 0xe4, 0x18, 0x55, 0x3d, + 0x54, 0x39, 0xd0, 0x0a, 0xd4, 0xef, 0x51, 0xcd, 0xec, 0xec, 0xac, 0x17, 0xdb, 0x60, 0x1c, 0x7a, + 0xc2, 0xfb, 0xde, 0xbc, 0xdf, 0xce, 0xfb, 0xbd, 0xdf, 0xbc, 0x37, 0x0b, 0xcc, 0xa3, 0xf6, 0x31, + 0xad, 0x38, 0x9e, 0x57, 0x61, 0x5d, 0xd3, 0xef, 0x10, 0x46, 0xf4, 0x0c, 0x37, 0x99, 0x8e, 0xe7, + 0x15, 0x16, 0x5b, 0xa4, 0x45, 0x84, 0xb1, 0xc2, 0x7f, 0x85, 0xfe, 0x42, 0xb1, 0x41, 0xa8, 0x47, + 0x68, 0x65, 0xdf, 0xa1, 0xa8, 0xf2, 0xf5, 0x83, 0x7d, 0xc4, 0x9c, 0x07, 0x95, 0x06, 0x71, 0xb1, + 0xf4, 0x2f, 0x29, 0x48, 0xdf, 0xe9, 0x38, 0x1e, 0x95, 0xe6, 0x15, 0x65, 0xa6, 0x47, 0x8e, 0x6f, + 0x77, 0x48, 0xc0, 0x90, 0x74, 0x15, 0xe2, 0x08, 0x42, 0xda, 0xf6, 0x90, 0x30, 0xe1, 0x73, 0x28, + 0x45, 0x2c, 0x74, 0x19, 0x3f, 0x69, 0x30, 0x5b, 0xa7, 0xad, 0x27, 0x1d, 0xe4, 0x30, 0xb4, 0x47, + 0x48, 0x5b, 0xbf, 0x0d, 0x69, 0x8a, 0x70, 0x13, 0x75, 0xf2, 0x5a, 0x49, 0x2b, 0x67, 0x2d, 0xf9, + 0xa4, 0xbf, 0x07, 0xb9, 0x1e, 0xe4, 0x7c, 0xaa, 0xa4, 0x95, 0x73, 0x1b, 0x8b, 0x66, 0x94, 0xa8, + 0xc9, 0x83, 0xf7, 0x84, 0xcf, 0x02, 0x5f, 0xfd, 0xd6, 0x37, 0x65, 0x98, 0x78, 0x29, 0xcd, 0x4f, + 0x96, 0x26, 0xcb, 0xb9, 0x8d, 0x85, 0x64, 0xd8, 0x63, 0xee, 0xab, 0x4e, 0xbd, 0x3a, 0x59, 0x9b, + 0x08, 0x63, 0x85, 0x81, 0x1a, 0x8f, 0x60, 0x29, 0xb1, 0x37, 0x0b, 0x51, 0x9f, 0x60, 0x8a, 0xf4, + 0xff, 0xc3, 0x8c, 0x00, 0x75, 0x9b, 0x62, 0x93, 0x53, 0x55, 0x38, 0x3d, 0x59, 0x4b, 0xf3, 0x25, + 0xb5, 0x2d, 0x2b, 0xcd, 0x5d, 0xb5, 0xa6, 0xf1, 0x7d, 0x0a, 0x72, 0x75, 0xda, 0x7a, 0x4a, 0x5c, + 0x7c, 0x61, 0x62, 0xcb, 0x31, 0x18, 0x4f, 0x6a, 0x2a, 0x02, 0xd0, 0xb7, 0xe1, 0xa6, 0xe7, 0x74, + 0x6d, 0xc7, 0x23, 0x01, 0x66, 0xd4, 0x76, 0xb1, 0xdc, 0xfd, 0x8a, 0x19, 0x56, 0xcf, 0xe4, 0xd5, + 0x33, 0x65, 0xf5, 0xcc, 0x27, 0xc4, 0xc5, 0x32, 0x87, 0x1b, 0x9e, 0xd3, 0x7d, 0x1c, 0x46, 0xd5, + 0xb0, 0xfe, 0x29, 0xdc, 0xa2, 0x07, 0x4e, 0x07, 0x49, 0x20, 0x9b, 0x04, 0x2c, 0x3f, 0xc5, 0x77, + 0x50, 0x35, 0xf9, 0xea, 0x37, 0x27, 0x6b, 0xeb, 0x2d, 0x97, 0x1d, 0x04, 0xfb, 0x66, 0x83, 0x78, + 0x15, 0x29, 0x8c, 0xf0, 0xcf, 0x7d, 0xda, 0x3c, 0xac, 0xb0, 0x63, 0x1f, 0x51, 0xb3, 0x86, 0x99, + 0x75, 0x53, 0xe0, 0x84, 0xc8, 0xbb, 0x01, 0xd3, 0xff, 0x07, 0x37, 0x30, 0xb1, 0x3b, 0xc8, 0x73, + 0x5c, 0xec, 0xe2, 0x56, 0x7e, 0xba, 0xa4, 0x95, 0x33, 0x56, 0x0e, 0x13, 0x2b, 0x32, 0x19, 0x3f, + 0x6b, 0xb0, 0xd0, 0x43, 0x82, 0x62, 0x70, 0xd0, 0xa6, 0xb4, 0x6b, 0xd9, 0xd4, 0x26, 0x64, 0x18, + 0x39, 0x44, 0x98, 0xf3, 0x95, 0x1a, 0x8d, 0xaf, 0x19, 0x11, 0x50, 0xc3, 0xc6, 0x0f, 0x61, 0xc9, + 0xb6, 0xbb, 0x2e, 0x1b, 0xaf, 0x64, 0x9f, 0xc0, 0x9c, 0xe7, 0x62, 0x55, 0x32, 0x9e, 0xd5, 0x88, + 0x35, 0x9b, 0xf5, 0x5c, 0x2c, 0x6b, 0xc6, 0xb3, 0x78, 0x01, 0x73, 0x09, 0x7e, 0x5c, 0x3c, 0x66, + 0xcd, 0x66, 0x7b, 0xe8, 0xa9, 0x61, 0x7d, 0x1d, 0xe6, 0x42, 0x76, 0x48, 0xc0, 0xec, 0x26, 0xc2, + 0xc4, 0x13, 0x55, 0xcb, 0x5a, 0xb3, 0xc2, 0xbc, 0x1b, 0xb0, 0x2d, 0x6e, 0x34, 0x9e, 0x8b, 0xb2, + 0x45, 0x44, 0xa8, 0xb2, 0x3d, 0x82, 0xac, 0x0a, 0x1f, 0x95, 0xdd, 0x4c, 0x84, 0x6c, 0xfc, 0x9e, + 0x82, 0xc5, 0x3a, 0x6d, 0x3d, 0x3f, 0x72, 0xfc, 0xed, 0xae, 0xd3, 0x60, 0x6a, 0x57, 0xc3, 0x78, + 0x7e, 0x08, 0x69, 0xd1, 0x63, 0xa8, 0x7c, 0xd7, 0x9d, 0xf8, 0xdc, 0x72, 0x90, 0x28, 0xde, 0xe2, + 0x6b, 0xe4, 0xdb, 0x64, 0x40, 0x42, 0x06, 0x93, 0xa2, 0x57, 0x8c, 0x2c, 0x03, 0xdd, 0x86, 0xc5, + 0x98, 0xa4, 0xb8, 0x9e, 0x63, 0x56, 0x60, 0x3e, 0xca, 0xbf, 0x1e, 0x55, 0x58, 0x7f, 0x0a, 0x99, + 0xa6, 0x4b, 0x1b, 0x02, 0x74, 0xfa, 0xca, 0xa0, 0x5b, 0xa8, 0x61, 0xa9, 0x78, 0xe3, 0x37, 0x0d, + 0xee, 0x0e, 0x22, 0xb5, 0xf7, 0xa8, 0xc5, 0xd9, 0xc8, 0x4c, 0xc6, 0x3c, 0x6a, 0x51, 0x26, 0x03, + 0xd2, 0x48, 0xbd, 0x65, 0x1a, 0x7f, 0xa4, 0x44, 0xb3, 0x3d, 0x97, 0x06, 0x3f, 0x0a, 0xc3, 0xc4, + 0xb1, 0x79, 0x4e, 0x1c, 0x77, 0x07, 0x89, 0x63, 0x37, 0x60, 0x83, 0xd4, 0x91, 0xd0, 0xf1, 0x88, + 0xf2, 0x50, 0x3a, 0xd6, 0xbf, 0x80, 0x85, 0x48, 0x5b, 0x76, 0xdc, 0xa1, 0xc7, 0x94, 0xc7, 0x2d, + 0xa9, 0xba, 0x7a, 0xd4, 0xb3, 0xaf, 0x55, 0x1d, 0xbf, 0x6a, 0xb0, 0x3a, 0x90, 0x56, 0x25, 0x8f, + 0x17, 0x51, 0x47, 0x88, 0x75, 0x3e, 0x9e, 0x3a, 0x66, 0x65, 0x22, 0xff, 0x81, 0x38, 0xbe, 0x85, + 0x52, 0x9d, 0xb6, 0x76, 0x10, 0x6a, 0xd6, 0x83, 0x36, 0x73, 0xfd, 0x36, 0xda, 0xee, 0x32, 0xd4, + 0xc1, 0x4e, 0xfb, 0x99, 0xfb, 0x55, 0xe0, 0x36, 0x5d, 0x76, 0x3c, 0x54, 0x26, 0x1f, 0x41, 0xb6, + 0x1d, 0x2d, 0xea, 0x6f, 0x23, 0x7d, 0x38, 0xb2, 0xd8, 0x71, 0x8c, 0x71, 0x0f, 0xca, 0x97, 0xbd, + 0x3c, 0x22, 0xd3, 0xf8, 0x45, 0x83, 0x5b, 0xe2, 0xf2, 0x10, 0x92, 0xb0, 0x85, 0x7c, 0x76, 0xa0, + 0x2f, 0xc2, 0xb4, 0xb8, 0x7d, 0xc8, 0x8d, 0x85, 0x0f, 0xfa, 0x0e, 0xa4, 0x25, 0xdd, 0xe3, 0xb1, + 0x23, 0xa3, 0xf5, 0x2d, 0x98, 0x6e, 0xf2, 0xd7, 0x08, 0x19, 0x5f, 0x1d, 0x26, 0x0c, 0x36, 0xbe, + 0x81, 0xf9, 0x7e, 0x4a, 0x97, 0xcf, 0x5d, 0x73, 0xd4, 0x98, 0x7b, 0x06, 0xf3, 0x72, 0x2e, 0x89, + 0x68, 0xdb, 0xc5, 0x2f, 0x89, 0xe4, 0xb6, 0x10, 0x73, 0x7b, 0x9e, 0x08, 0x49, 0xed, 0x9c, 0x13, + 0x9b, 0x6a, 0xf8, 0x25, 0x31, 0xfe, 0x49, 0xc1, 0x4d, 0xa9, 0xd1, 0xea, 0xb1, 0x18, 0x3f, 0x43, + 0x8b, 0xf9, 0x41, 0x82, 0xb4, 0x11, 0x0e, 0x6d, 0xc4, 0xd2, 0x87, 0x00, 0x3d, 0x8d, 0x7c, 0xc4, + 0x13, 0x9f, 0x55, 0x33, 0x59, 0xc4, 0x27, 0x4f, 0xfa, 0x48, 0xf1, 0xea, 0x4c, 0xaf, 0x40, 0x46, + 0x4c, 0x5b, 0x3e, 0x8e, 0xc2, 0x81, 0x3b, 0x23, 0x9e, 0x6b, 0x58, 0xbf, 0x03, 0xd9, 0xd0, 0xc5, + 0x7b, 0x51, 0x5a, 0xf8, 0xc2, 0xb5, 0xbc, 0xd5, 0xf4, 0x9e, 0xa2, 0x99, 0xb7, 0x3c, 0x45, 0x7f, + 0xa5, 0xe0, 0x76, 0x92, 0x67, 0xd5, 0x04, 0x62, 0x5e, 0xb5, 0xab, 0xf1, 0xfa, 0x3e, 0x64, 0x5c, + 0x1c, 0x7e, 0x08, 0x8c, 0x30, 0xa3, 0xad, 0x19, 0x37, 0xfc, 0xa1, 0x3f, 0x84, 0x2c, 0x1f, 0x47, + 0x61, 0xe0, 0xe4, 0xe5, 0xfd, 0xdb, 0xca, 0x10, 0xf9, 0x4b, 0xaf, 0x03, 0x50, 0x9f, 0x30, 0xdb, + 0xef, 0xb8, 0x0d, 0x34, 0x46, 0xd3, 0xe5, 0xa4, 0x64, 0x39, 0xc2, 0x1e, 0x07, 0xb8, 0xce, 0x6e, + 0xbb, 0xf1, 0x66, 0x0a, 0x26, 0xeb, 0xb4, 0xa5, 0xef, 0x00, 0xf4, 0x7c, 0xd1, 0x2c, 0xc7, 0x89, + 0x25, 0x3e, 0x27, 0x0a, 0x6b, 0x43, 0x1c, 0xaa, 0x2c, 0x1f, 0x43, 0x46, 0x7d, 0x3e, 0x2c, 0x25, + 0x16, 0x47, 0xe6, 0xc2, 0xea, 0x40, 0x73, 0x2f, 0x82, 0xba, 0xcd, 0x26, 0x11, 0x22, 0xf3, 0x39, + 0x84, 0xbe, 0x2b, 0xdf, 0xe7, 0x30, 0xdf, 0x7f, 0x61, 0x2b, 0x26, 0x62, 0xfa, 0xfc, 0x85, 0xf5, + 0x8b, 0xfd, 0x0a, 0xfc, 0x4b, 0xd0, 0x07, 0x4c, 0xfc, 0xb5, 0x8b, 0xa2, 0x77, 0x03, 0x56, 0x78, + 0xe7, 0x92, 0x05, 0x0a, 0xbf, 0x06, 0xb9, 0xde, 0xb6, 0x92, 0xef, 0x8b, 0x93, 0x9e, 0x42, 0x69, + 0x98, 0x47, 0x41, 0x7d, 0x07, 0xab, 0x17, 0x0f, 0xa0, 0x7b, 0x09, 0x88, 0x0b, 0xd7, 0x16, 0x36, + 0x46, 0x5f, 0x1b, 0x6d, 0xa0, 0x5a, 0x7d, 0x75, 0x5a, 0xd4, 0x5e, 0x9f, 0x16, 0xb5, 0xbf, 0x4f, + 0x8b, 0xda, 0x8f, 0x67, 0xc5, 0x89, 0xd7, 0x67, 0xc5, 0x89, 0x3f, 0xcf, 0x8a, 0x13, 0x9f, 0x95, + 0x7b, 0x84, 0xca, 0x71, 0xef, 0x63, 0xc4, 0x8e, 0x48, 0xe7, 0x50, 0x3c, 0x54, 0xba, 0xe1, 0xbf, + 0x06, 0xb8, 0x5c, 0xf7, 0xd3, 0xe2, 0xab, 0xfb, 0xdd, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xb8, + 0x24, 0x05, 0x69, 0x33, 0x10, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1006,8 +1014,8 @@ type MsgClient interface { ExitPool(ctx context.Context, in *MsgExitPool, opts ...grpc.CallOption) (*MsgExitPoolResponse, error) SwapExactAmountIn(ctx context.Context, in *MsgSwapExactAmountIn, opts ...grpc.CallOption) (*MsgSwapExactAmountInResponse, error) SwapExactAmountOut(ctx context.Context, in *MsgSwapExactAmountOut, opts ...grpc.CallOption) (*MsgSwapExactAmountOutResponse, error) - FeedMultipleExternalLiquidity(ctx context.Context, in *MsgFeedMultipleExternalLiquidity, opts ...grpc.CallOption) (*MsgFeedMultipleExternalLiquidityResponse, error) SwapByDenom(ctx context.Context, in *MsgSwapByDenom, opts ...grpc.CallOption) (*MsgSwapByDenomResponse, error) + FeedMultipleExternalLiquidity(ctx context.Context, in *MsgFeedMultipleExternalLiquidity, opts ...grpc.CallOption) (*MsgFeedMultipleExternalLiquidityResponse, error) } type msgClient struct { @@ -1063,18 +1071,18 @@ func (c *msgClient) SwapExactAmountOut(ctx context.Context, in *MsgSwapExactAmou return out, nil } -func (c *msgClient) FeedMultipleExternalLiquidity(ctx context.Context, in *MsgFeedMultipleExternalLiquidity, opts ...grpc.CallOption) (*MsgFeedMultipleExternalLiquidityResponse, error) { - out := new(MsgFeedMultipleExternalLiquidityResponse) - err := c.cc.Invoke(ctx, "/elys.amm.Msg/FeedMultipleExternalLiquidity", in, out, opts...) +func (c *msgClient) SwapByDenom(ctx context.Context, in *MsgSwapByDenom, opts ...grpc.CallOption) (*MsgSwapByDenomResponse, error) { + out := new(MsgSwapByDenomResponse) + err := c.cc.Invoke(ctx, "/elys.amm.Msg/SwapByDenom", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *msgClient) SwapByDenom(ctx context.Context, in *MsgSwapByDenom, opts ...grpc.CallOption) (*MsgSwapByDenomResponse, error) { - out := new(MsgSwapByDenomResponse) - err := c.cc.Invoke(ctx, "/elys.amm.Msg/SwapByDenom", in, out, opts...) +func (c *msgClient) FeedMultipleExternalLiquidity(ctx context.Context, in *MsgFeedMultipleExternalLiquidity, opts ...grpc.CallOption) (*MsgFeedMultipleExternalLiquidityResponse, error) { + out := new(MsgFeedMultipleExternalLiquidityResponse) + err := c.cc.Invoke(ctx, "/elys.amm.Msg/FeedMultipleExternalLiquidity", in, out, opts...) if err != nil { return nil, err } @@ -1088,8 +1096,8 @@ type MsgServer interface { ExitPool(context.Context, *MsgExitPool) (*MsgExitPoolResponse, error) SwapExactAmountIn(context.Context, *MsgSwapExactAmountIn) (*MsgSwapExactAmountInResponse, error) SwapExactAmountOut(context.Context, *MsgSwapExactAmountOut) (*MsgSwapExactAmountOutResponse, error) - FeedMultipleExternalLiquidity(context.Context, *MsgFeedMultipleExternalLiquidity) (*MsgFeedMultipleExternalLiquidityResponse, error) SwapByDenom(context.Context, *MsgSwapByDenom) (*MsgSwapByDenomResponse, error) + FeedMultipleExternalLiquidity(context.Context, *MsgFeedMultipleExternalLiquidity) (*MsgFeedMultipleExternalLiquidityResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -1111,12 +1119,12 @@ func (*UnimplementedMsgServer) SwapExactAmountIn(ctx context.Context, req *MsgSw func (*UnimplementedMsgServer) SwapExactAmountOut(ctx context.Context, req *MsgSwapExactAmountOut) (*MsgSwapExactAmountOutResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SwapExactAmountOut not implemented") } -func (*UnimplementedMsgServer) FeedMultipleExternalLiquidity(ctx context.Context, req *MsgFeedMultipleExternalLiquidity) (*MsgFeedMultipleExternalLiquidityResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method FeedMultipleExternalLiquidity not implemented") -} func (*UnimplementedMsgServer) SwapByDenom(ctx context.Context, req *MsgSwapByDenom) (*MsgSwapByDenomResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SwapByDenom not implemented") } +func (*UnimplementedMsgServer) FeedMultipleExternalLiquidity(ctx context.Context, req *MsgFeedMultipleExternalLiquidity) (*MsgFeedMultipleExternalLiquidityResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FeedMultipleExternalLiquidity not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -1212,38 +1220,38 @@ func _Msg_SwapExactAmountOut_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } -func _Msg_FeedMultipleExternalLiquidity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgFeedMultipleExternalLiquidity) +func _Msg_SwapByDenom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSwapByDenom) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).FeedMultipleExternalLiquidity(ctx, in) + return srv.(MsgServer).SwapByDenom(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/elys.amm.Msg/FeedMultipleExternalLiquidity", + FullMethod: "/elys.amm.Msg/SwapByDenom", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).FeedMultipleExternalLiquidity(ctx, req.(*MsgFeedMultipleExternalLiquidity)) + return srv.(MsgServer).SwapByDenom(ctx, req.(*MsgSwapByDenom)) } return interceptor(ctx, in, info, handler) } -func _Msg_SwapByDenom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgSwapByDenom) +func _Msg_FeedMultipleExternalLiquidity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgFeedMultipleExternalLiquidity) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).SwapByDenom(ctx, in) + return srv.(MsgServer).FeedMultipleExternalLiquidity(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/elys.amm.Msg/SwapByDenom", + FullMethod: "/elys.amm.Msg/FeedMultipleExternalLiquidity", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).SwapByDenom(ctx, req.(*MsgSwapByDenom)) + return srv.(MsgServer).FeedMultipleExternalLiquidity(ctx, req.(*MsgFeedMultipleExternalLiquidity)) } return interceptor(ctx, in, info, handler) } @@ -1272,14 +1280,14 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "SwapExactAmountOut", Handler: _Msg_SwapExactAmountOut_Handler, }, - { - MethodName: "FeedMultipleExternalLiquidity", - Handler: _Msg_FeedMultipleExternalLiquidity_Handler, - }, { MethodName: "SwapByDenom", Handler: _Msg_SwapByDenom_Handler, }, + { + MethodName: "FeedMultipleExternalLiquidity", + Handler: _Msg_FeedMultipleExternalLiquidity_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "elys/amm/tx.proto", @@ -1608,6 +1616,16 @@ func (m *MsgSwapExactAmountIn) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.Discount.Size() + i -= size + if _, err := m.Discount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a { size := m.TokenOutMinAmount.Size() i -= size @@ -1672,6 +1690,16 @@ func (m *MsgSwapExactAmountInResponse) MarshalToSizedBuffer(dAtA []byte) (int, e _ = i var l int _ = l + { + size := m.Discount.Size() + i -= size + if _, err := m.Discount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 { size := m.TokenOutAmount.Size() i -= size @@ -1705,6 +1733,16 @@ func (m *MsgSwapExactAmountOut) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.Discount.Size() + i -= size + if _, err := m.Discount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a { size := m.TokenInMaxAmount.Size() i -= size @@ -1769,6 +1807,16 @@ func (m *MsgSwapExactAmountOutResponse) MarshalToSizedBuffer(dAtA []byte) (int, _ = i var l int _ = l + { + size := m.Discount.Size() + i -= size + if _, err := m.Discount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 { size := m.TokenInAmount.Size() i -= size @@ -2054,6 +2102,16 @@ func (m *MsgSwapByDenomResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) i = encodeVarintTx(dAtA, i, uint64(size)) } i-- + dAtA[i] = 0x2a + { + size := m.SpotPrice.Size() + i -= size + if _, err := m.SpotPrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- dAtA[i] = 0x22 if len(m.OutRoute) > 0 { for iNdEx := len(m.OutRoute) - 1; iNdEx >= 0; iNdEx-- { @@ -2249,6 +2307,8 @@ func (m *MsgSwapExactAmountIn) Size() (n int) { n += 1 + l + sovTx(uint64(l)) l = m.TokenOutMinAmount.Size() n += 1 + l + sovTx(uint64(l)) + l = m.Discount.Size() + n += 1 + l + sovTx(uint64(l)) return n } @@ -2260,6 +2320,8 @@ func (m *MsgSwapExactAmountInResponse) Size() (n int) { _ = l l = m.TokenOutAmount.Size() n += 1 + l + sovTx(uint64(l)) + l = m.Discount.Size() + n += 1 + l + sovTx(uint64(l)) return n } @@ -2283,6 +2345,8 @@ func (m *MsgSwapExactAmountOut) Size() (n int) { n += 1 + l + sovTx(uint64(l)) l = m.TokenInMaxAmount.Size() n += 1 + l + sovTx(uint64(l)) + l = m.Discount.Size() + n += 1 + l + sovTx(uint64(l)) return n } @@ -2294,6 +2358,8 @@ func (m *MsgSwapExactAmountOutResponse) Size() (n int) { _ = l l = m.TokenInAmount.Size() n += 1 + l + sovTx(uint64(l)) + l = m.Discount.Size() + n += 1 + l + sovTx(uint64(l)) return n } @@ -2409,6 +2475,8 @@ func (m *MsgSwapByDenomResponse) Size() (n int) { n += 1 + l + sovTx(uint64(l)) } } + l = m.SpotPrice.Size() + n += 1 + l + sovTx(uint64(l)) l = m.Discount.Size() n += 1 + l + sovTx(uint64(l)) return n @@ -3395,6 +3463,40 @@ func (m *MsgSwapExactAmountIn) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Discount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Discount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -3479,6 +3581,40 @@ func (m *MsgSwapExactAmountInResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Discount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Discount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -3662,6 +3798,40 @@ func (m *MsgSwapExactAmountOut) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Discount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Discount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -3746,6 +3916,40 @@ func (m *MsgSwapExactAmountOutResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Discount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Discount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -4590,12 +4794,46 @@ func (m *MsgSwapByDenomResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.OutRoute = append(m.OutRoute, &SwapAmountInRoute{}) + 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 4: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SpotPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Discount", wireType) } diff --git a/x/transferhook/keeper/swap.go b/x/transferhook/keeper/swap.go index 3b643a2dc..f0806d832 100644 --- a/x/transferhook/keeper/swap.go +++ b/x/transferhook/keeper/swap.go @@ -56,6 +56,7 @@ func (k Keeper) SwapExactAmountIn(ctx sdk.Context, addr sdk.AccAddress, tokenIn Routes: routes, TokenIn: tokenIn, TokenOutMinAmount: sdk.OneInt(), + Discount: sdk.ZeroDec(), } if err := msg.ValidateBasic(); err != nil { return err