From 72c729816d77944cac13e42138797c670db69160 Mon Sep 17 00:00:00 2001 From: Deividas Petraitis Date: Thu, 21 Nov 2024 13:22:57 +0200 Subject: [PATCH 1/4] BE-654 | Add liquidity cap for each routable pool in the quote and sum Introduces changes to add liquidity cap for each pool in the route and adds sum field of all liquidities for the route --- domain/routable_pool.go | 2 + .../plugins/orderbook/claimbot/export_test.go | 2 +- router/usecase/pools/pool_factory.go | 12 ++++- .../usecase/pools/routable_balancer_pool.go | 14 ++++-- .../pools/routable_concentrated_pool.go | 16 ++++--- .../routable_cw_alloy_transmuter_pool.go | 20 ++++++--- .../pools/routable_cw_orderbook_pool.go | 20 ++++++--- router/usecase/pools/routable_cw_pool.go | 34 ++++++++++---- .../pools/routable_cw_transmuter_pool.go | 18 +++++--- router/usecase/pools/routable_result_pool.go | 44 ++++++++++++++----- .../usecase/pools/routable_stableswap_pool.go | 14 ++++-- router/usecase/quote_in_given_out.go | 16 ++++--- router/usecase/quote_out_given_in.go | 20 ++++++--- router/usecase/route/route.go | 1 + 14 files changed, 165 insertions(+), 68 deletions(-) diff --git a/domain/routable_pool.go b/domain/routable_pool.go index 112378f1a..37dee8c5c 100644 --- a/domain/routable_pool.go +++ b/domain/routable_pool.go @@ -62,6 +62,8 @@ type RoutablePool interface { ChargeTakerFeeExactIn(tokenIn sdk.Coin) (tokenInAfterFee sdk.Coin) + GetLiquidityCap() osmomath.Int + GetTakerFee() osmomath.Dec GetSpreadFactor() osmomath.Dec diff --git a/ingest/usecase/plugins/orderbook/claimbot/export_test.go b/ingest/usecase/plugins/orderbook/claimbot/export_test.go index c75f7f357..2ab99f41f 100644 --- a/ingest/usecase/plugins/orderbook/claimbot/export_test.go +++ b/ingest/usecase/plugins/orderbook/claimbot/export_test.go @@ -9,8 +9,8 @@ import ( "github.com/osmosis-labs/sqs/domain/mvc" orderbookdomain "github.com/osmosis-labs/sqs/domain/orderbook" - txfeestypes "github.com/osmosis-labs/osmosis/v27/x/txfees/types" "github.com/osmosis-labs/osmosis/v27/app/params" + txfeestypes "github.com/osmosis-labs/osmosis/v27/x/txfees/types" "github.com/osmosis-labs/osmosis/osmomath" diff --git a/router/usecase/pools/pool_factory.go b/router/usecase/pools/pool_factory.go index ea41a5744..c1ebe919f 100644 --- a/router/usecase/pools/pool_factory.go +++ b/router/usecase/pools/pool_factory.go @@ -39,6 +39,7 @@ func NewRoutablePool(pool sqsdomain.PoolI, tokenOutDenom string, takerFee osmoma TickModel: tickModel, TokenOutDenom: tokenOutDenom, TakerFee: takerFee, + LiquidityCap: pool.GetPoolLiquidityCap(), }, nil } @@ -58,6 +59,7 @@ func NewRoutablePool(pool sqsdomain.PoolI, tokenOutDenom string, takerFee osmoma ChainPool: balancerPool, TokenOutDenom: tokenOutDenom, TakerFee: takerFee, + LiquidityCap: pool.GetPoolLiquidityCap(), }, nil } @@ -82,6 +84,7 @@ func NewRoutablePool(pool sqsdomain.PoolI, tokenOutDenom string, takerFee osmoma ChainPool: stableswapPool, TokenOutDenom: tokenOutDenom, TakerFee: takerFee, + LiquidityCap: pool.GetPoolLiquidityCap(), }, nil } @@ -93,6 +96,7 @@ func NewRoutablePool(pool sqsdomain.PoolI, tokenOutDenom string, takerFee osmoma func newRoutableCosmWasmPool(pool sqsdomain.PoolI, tokenOutDenom string, takerFee osmomath.Dec, cosmWasmPoolsParams cosmwasmdomain.CosmWasmPoolsParams) (domain.RoutablePool, error) { chainPool := pool.GetUnderlyingPool() poolType := pool.GetType() + liquidityCap := pool.GetPoolLiquidityCap() cosmwasmPool, ok := chainPool.(*cwpoolmodel.CosmWasmPool) if !ok { @@ -116,6 +120,7 @@ func newRoutableCosmWasmPool(pool sqsdomain.PoolI, tokenOutDenom string, takerFe TokenOutDenom: tokenOutDenom, TakerFee: takerFee, SpreadFactor: spreadFactor, + LiquidityCap: liquidityCap, }, nil } @@ -125,10 +130,10 @@ func newRoutableCosmWasmPool(pool sqsdomain.PoolI, tokenOutDenom string, takerFe // for most other CosmWasm pools, interaction with the chain will // be required. As a result, we have a custom implementation. - return NewRoutableCosmWasmPool(cosmwasmPool, balances, tokenOutDenom, takerFee, spreadFactor, cosmWasmPoolsParams), nil + return NewRoutableCosmWasmPool(cosmwasmPool, balances, tokenOutDenom, takerFee, spreadFactor, liquidityCap, cosmWasmPoolsParams), nil } - return newRoutableCosmWasmPoolWithCustomModel(pool, cosmwasmPool, cosmWasmPoolsParams, tokenOutDenom, takerFee) + return newRoutableCosmWasmPoolWithCustomModel(pool, cosmwasmPool, cosmWasmPoolsParams, tokenOutDenom, takerFee, liquidityCap) } // newRoutableCosmWasmPoolWithCustomModel creates a new RoutablePool for CosmWasm pools that require a custom CosmWasmPoolModel. @@ -142,6 +147,7 @@ func newRoutableCosmWasmPoolWithCustomModel( cosmWasmPoolsParams cosmwasmdomain.CosmWasmPoolsParams, tokenOutDenom string, takerFee osmomath.Dec, + liquidityCap osmomath.Int, ) (domain.RoutablePool, error) { sqsPoolModel := pool.GetSQSPoolModel() @@ -169,6 +175,7 @@ func newRoutableCosmWasmPoolWithCustomModel( TokenOutDenom: tokenOutDenom, TakerFee: takerFee, SpreadFactor: spreadFactor, + LiquidityCap: liquidityCap, }, nil } @@ -187,6 +194,7 @@ func newRoutableCosmWasmPoolWithCustomModel( TokenOutDenom: tokenOutDenom, TakerFee: takerFee, SpreadFactor: spreadFactor, + LiquidityCap: liquidityCap, OrderbookData: model.Data.Orderbook, }, nil } diff --git a/router/usecase/pools/routable_balancer_pool.go b/router/usecase/pools/routable_balancer_pool.go index c8fc991d0..6952b0333 100644 --- a/router/usecase/pools/routable_balancer_pool.go +++ b/router/usecase/pools/routable_balancer_pool.go @@ -19,10 +19,11 @@ import ( var _ domain.RoutablePool = &routableBalancerPoolImpl{} type routableBalancerPoolImpl struct { - ChainPool *balancer.Pool "json:\"pool\"" - TokenInDenom string "json:\"token_in_denom,omitempty\"" - TokenOutDenom string "json:\"token_out_denom,omitempty\"" - TakerFee osmomath.Dec "json:\"taker_fee\"" + ChainPool *balancer.Pool `json:"pool"` + TokenInDenom string `json:"token_in_denom,omitempty"` + TokenOutDenom string `json:"token_out_denom,omitempty"` + TakerFee osmomath.Dec `json:"taker_fee"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` } // CalculateTokenOutByTokenIn implements RoutablePool. @@ -62,6 +63,11 @@ func (r *routableBalancerPoolImpl) GetTakerFee() math.LegacyDec { return r.TakerFee } +// GetLiquidtyCap implements domain.RoutablePool. +func (r *routableBalancerPoolImpl) GetLiquidityCap() osmomath.Int { + return r.LiquidityCap +} + // SetTokenInDenom implements domain.RoutablePool. func (r *routableBalancerPoolImpl) SetTokenInDenom(tokenInDenom string) { r.TokenInDenom = tokenInDenom diff --git a/router/usecase/pools/routable_concentrated_pool.go b/router/usecase/pools/routable_concentrated_pool.go index 8cbd9f43e..ba686494d 100644 --- a/router/usecase/pools/routable_concentrated_pool.go +++ b/router/usecase/pools/routable_concentrated_pool.go @@ -24,11 +24,12 @@ var _ domain.RoutablePool = &routableConcentratedPoolImpl{} var smallestDec = osmomath.BigDecFromDec(osmomath.SmallestDec()) type routableConcentratedPoolImpl struct { - ChainPool *concentratedmodel.Pool "json:\"cl_pool\"" - TickModel *sqsdomain.TickModel "json:\"tick_model\"" - TokenInDenom string "json:\"token_in_denom,omitempty\"" - TokenOutDenom string "json:\"token_out_denom,omitempty\"" - TakerFee osmomath.Dec "json:\"taker_fee\"" + ChainPool *concentratedmodel.Pool `json:"cl_pool"` + TickModel *sqsdomain.TickModel `json:"tick_model"` + TokenInDenom string `json:"token_in_denom,omitempty"` + TokenOutDenom string `json:"token_out_denom,omitempty"` + TakerFee osmomath.Dec `json:"taker_fee"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` } // Size is roughly `keys * (2.5 * Key_size + 2*value_size)`. (Plus whatever excess overhead hashmaps internally have) @@ -73,6 +74,11 @@ func (r *routableConcentratedPoolImpl) GetTakerFee() math.LegacyDec { return r.TakerFee } +// GetLiquidityCap implements domain.RoutablePool. +func (r *routableConcentratedPoolImpl) GetLiquidityCap() osmomath.Int { + return r.LiquidityCap +} + // CalculateTokenOutByTokenIn implements domain.RoutablePool. // It calculates the amount of token out given the amount of token in for a concentrated liquidity pool. // Fails if: diff --git a/router/usecase/pools/routable_cw_alloy_transmuter_pool.go b/router/usecase/pools/routable_cw_alloy_transmuter_pool.go index 165ed2660..b542fdd54 100644 --- a/router/usecase/pools/routable_cw_alloy_transmuter_pool.go +++ b/router/usecase/pools/routable_cw_alloy_transmuter_pool.go @@ -19,13 +19,14 @@ import ( var _ domain.RoutablePool = &routableAlloyTransmuterPoolImpl{} type routableAlloyTransmuterPoolImpl struct { - ChainPool *cwpoolmodel.CosmWasmPool "json:\"pool\"" - AlloyTransmuterData *cosmwasmpool.AlloyTransmuterData "json:\"alloy_transmuter_data\"" - Balances sdk.Coins "json:\"balances\"" - TokenInDenom string "json:\"token_in_denom,omitempty\"" - TokenOutDenom string "json:\"token_out_denom,omitempty\"" - TakerFee osmomath.Dec "json:\"taker_fee\"" - SpreadFactor osmomath.Dec "json:\"spread_factor\"" + ChainPool *cwpoolmodel.CosmWasmPool `json:"pool"` + AlloyTransmuterData *cosmwasmpool.AlloyTransmuterData `json:"alloy_transmuter_data"` + Balances sdk.Coins `json:"balances"` + TokenInDenom string `json:"token_in_denom,omitempty"` + TokenOutDenom string `json:"token_out_denom,omitempty"` + TakerFee osmomath.Dec `json:"taker_fee"` + SpreadFactor osmomath.Dec `json:"spread_factor"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` } // GetId implements domain.RoutablePool. @@ -52,6 +53,11 @@ func (r *routableAlloyTransmuterPoolImpl) GetSpreadFactor() math.LegacyDec { return r.SpreadFactor } +// GetLiquidityCap implements domain.RoutablePool. +func (r *routableAlloyTransmuterPoolImpl) GetLiquidityCap() osmomath.Int { + return r.LiquidityCap +} + // CalculateTokenOutByTokenIn implements domain.RoutablePool. // It calculates the amount of token out given the amount of token in for a transmuter pool. // Transmuter pool allows no slippage swaps. For v3, the ratio of token in to token out is dependent on the normalization factor. diff --git a/router/usecase/pools/routable_cw_orderbook_pool.go b/router/usecase/pools/routable_cw_orderbook_pool.go index 8120426c6..46b9ff7b1 100644 --- a/router/usecase/pools/routable_cw_orderbook_pool.go +++ b/router/usecase/pools/routable_cw_orderbook_pool.go @@ -22,13 +22,14 @@ var oneBigDec = osmomath.OneBigDec() var _ domain.RoutablePool = &routableOrderbookPoolImpl{} type routableOrderbookPoolImpl struct { - ChainPool *cwpoolmodel.CosmWasmPool "json:\"pool\"" - Balances sdk.Coins "json:\"balances\"" - TokenInDenom string "json:\"token_in_denom,omitempty\"" - TokenOutDenom string "json:\"token_out_denom,omitempty\"" - TakerFee osmomath.Dec "json:\"taker_fee\"" - SpreadFactor osmomath.Dec "json:\"spread_factor\"" - OrderbookData *cosmwasmpool.OrderbookData "json:\"orderbook_data\"" + ChainPool *cwpoolmodel.CosmWasmPool `json:"pool"` + Balances sdk.Coins `json:"balances"` + TokenInDenom string `json:"token_in_denom,omitempty"` + TokenOutDenom string `json:"token_out_denom,omitempty"` + TakerFee osmomath.Dec `json:"taker_fee"` + SpreadFactor osmomath.Dec `json:"spread_factor"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` + OrderbookData *cosmwasmpool.OrderbookData `json:"orderbook_data"` } // GetId implements domain.RoutablePool. @@ -51,6 +52,11 @@ func (r *routableOrderbookPoolImpl) GetSpreadFactor() math.LegacyDec { return r.SpreadFactor } +// GetLiquidityCap implements domain.RoutablePool. +func (r *routableOrderbookPoolImpl) GetLiquidityCap() osmomath.Int { + return r.LiquidityCap +} + // CalculateTokenOutByTokenIn implements sqsdomain.RoutablePool. // It calculates the amount of token out given the amount of token in for a orderbook pool. // Fails if: diff --git a/router/usecase/pools/routable_cw_pool.go b/router/usecase/pools/routable_cw_pool.go index a306afc74..fc7b23cf5 100644 --- a/router/usecase/pools/routable_cw_pool.go +++ b/router/usecase/pools/routable_cw_pool.go @@ -29,18 +29,27 @@ var _ domain.RoutablePool = &routableCosmWasmPoolImpl{} // routableCosmWasmPool is an implemenation of the cosm wasm pool // that interacts with the chain for quotes and spot price. type routableCosmWasmPoolImpl struct { - ChainPool *cwpoolmodel.CosmWasmPool "json:\"pool\"" - Balances sdk.Coins "json:\"balances\"" - TokenOutDenom string "json:\"token_out_denom,omitempty\"" - TokenInDenom string "json:\"token_in_denom,omitempty\"" - TakerFee osmomath.Dec "json:\"taker_fee\"" - SpreadFactor osmomath.Dec "json:\"spread_factor\"" - wasmClient wasmtypes.QueryClient "json:\"-\"" - spotPriceQuoteCalculator domain.SpotPriceQuoteCalculator "json:\"-\"" + ChainPool *cwpoolmodel.CosmWasmPool `json:"pool"` + Balances sdk.Coins `json:"balances"` + TokenOutDenom string `json:"token_out_denom,omitempty"` + TokenInDenom string `json:"token_in_denom,omitempty"` + TakerFee osmomath.Dec `json:"taker_fee"` + SpreadFactor osmomath.Dec `json:"spread_factor"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` + wasmClient wasmtypes.QueryClient `json:"-"` + spotPriceQuoteCalculator domain.SpotPriceQuoteCalculator `json:"-"` } // NewRoutableCosmWasmPool returns a new routable cosmwasm pool with the given parameters. -func NewRoutableCosmWasmPool(pool *cwpoolmodel.CosmWasmPool, balances sdk.Coins, tokenOutDenom string, takerFee osmomath.Dec, spreadFactor osmomath.Dec, cosmWasmPoolsParams cosmwasmdomain.CosmWasmPoolsParams) domain.RoutablePool { +func NewRoutableCosmWasmPool( + pool *cwpoolmodel.CosmWasmPool, + balances sdk.Coins, + tokenOutDenom string, + takerFee osmomath.Dec, + spreadFactor osmomath.Dec, + liquidityCap osmomath.Int, + cosmWasmPoolsParams cosmwasmdomain.CosmWasmPoolsParams, +) domain.RoutablePool { // Initializa routable cosmwasm pool routableCosmWasmPool := &routableCosmWasmPoolImpl{ ChainPool: pool, @@ -53,6 +62,8 @@ func NewRoutableCosmWasmPool(pool *cwpoolmodel.CosmWasmPool, balances sdk.Coins, // Note, that there is no calculator set // since we need to wire quote calculation callback to it. spotPriceQuoteCalculator: nil, + + LiquidityCap: liquidityCap, } // Initialize spot price calculator. @@ -84,6 +95,11 @@ func (r *routableCosmWasmPoolImpl) GetSpreadFactor() math.LegacyDec { return r.SpreadFactor } +// GetLiquidityCap implements domain.RoutablePool. +func (r *routableCosmWasmPoolImpl) GetLiquidityCap() osmomath.Int { + return r.LiquidityCap +} + // CalculateTokenOutByTokenIn implements domain.RoutablePool. // It calculates the amount of token out given the amount of token in for a transmuter pool. // Transmuter pool allows no slippage swaps. It just returns the same amount of token out as token in diff --git a/router/usecase/pools/routable_cw_transmuter_pool.go b/router/usecase/pools/routable_cw_transmuter_pool.go index 94b3c3535..0872e29de 100644 --- a/router/usecase/pools/routable_cw_transmuter_pool.go +++ b/router/usecase/pools/routable_cw_transmuter_pool.go @@ -18,12 +18,13 @@ import ( var _ domain.RoutablePool = &routableTransmuterPoolImpl{} type routableTransmuterPoolImpl struct { - ChainPool *cwpoolmodel.CosmWasmPool "json:\"pool\"" - Balances sdk.Coins "json:\"balances\"" - TokenInDenom string "json:\"token_in_denom,omitempty\"" - TokenOutDenom string "json:\"token_out_denom,omitempty\"" - TakerFee osmomath.Dec "json:\"taker_fee\"" - SpreadFactor osmomath.Dec "json:\"spread_factor\"" + ChainPool *cwpoolmodel.CosmWasmPool `json:"pool"` + Balances sdk.Coins `json:"balances"` + TokenInDenom string `json:"token_in_denom,omitempty"` + TokenOutDenom string `json:"token_out_denom,omitempty"` + TakerFee osmomath.Dec `json:"taker_fee"` + SpreadFactor osmomath.Dec `json:"spread_factor"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` } // GetId implements domain.RoutablePool. @@ -46,6 +47,11 @@ func (r *routableTransmuterPoolImpl) GetSpreadFactor() math.LegacyDec { return r.SpreadFactor } +// GetLiquidityCap implements domain.RoutablePool. +func (r *routableTransmuterPoolImpl) GetLiquidityCap() osmomath.Int { + return r.LiquidityCap +} + // CalculateTokenOutByTokenIn implements domain.RoutablePool. // It calculates the amount of token out given the amount of token in for a transmuter pool. // Transmuter pool allows no slippage swaps. It just returns the same amount of token out as token in diff --git a/router/usecase/pools/routable_result_pool.go b/router/usecase/pools/routable_result_pool.go index 01d7dde91..cd9f6947f 100644 --- a/router/usecase/pools/routable_result_pool.go +++ b/router/usecase/pools/routable_result_pool.go @@ -25,14 +25,15 @@ var ( // routableResultPoolImpl is a generalized implementation that is returned to the client // side in quotes. It contains all the relevant pool data needed for Osmosis frontend type routableResultPoolImpl struct { - ID uint64 "json:\"id\"" - Type poolmanagertypes.PoolType "json:\"type\"" - Balances sdk.Coins "json:\"balances\"" - SpreadFactor osmomath.Dec "json:\"spread_factor\"" - TokenOutDenom string "json:\"token_out_denom,omitempty\"" - TokenInDenom string "json:\"token_in_denom,omitempty\"" - TakerFee osmomath.Dec "json:\"taker_fee\"" - CodeID uint64 "json:\"code_id,omitempty\"" + ID uint64 `json:"id"` + Type poolmanagertypes.PoolType `json:"type"` + Balances sdk.Coins `json:"balances"` + SpreadFactor osmomath.Dec `json:"spread_factor"` + TokenOutDenom string `json:"token_out_denom,omitempty"` + TokenInDenom string `json:"token_in_denom,omitempty"` + TakerFee osmomath.Dec `json:"taker_fee"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` + CodeID uint64 `json:"code_id,omitempty"` } // GetCodeID implements domain.RoutablePool. @@ -51,25 +52,43 @@ func (r *routableResultPoolImpl) SetOutDenom(denom string) { } // NewRoutableResultPool returns the new routable result pool with the given parameters. -func NewRoutableResultPool(ID uint64, poolType poolmanagertypes.PoolType, spreadFactor osmomath.Dec, tokenOutDenom string, takerFee osmomath.Dec, codeID uint64) domain.RoutablePool { +func NewRoutableResultPool( + ID uint64, + poolType poolmanagertypes.PoolType, + spreadFactor osmomath.Dec, + tokenOutDenom string, + takerFee osmomath.Dec, + liquidityCap osmomath.Int, + codeID uint64, +) domain.RoutablePool { return &routableResultPoolImpl{ ID: ID, Type: poolType, SpreadFactor: spreadFactor, TokenOutDenom: tokenOutDenom, TakerFee: takerFee, + LiquidityCap: liquidityCap, CodeID: codeID, } } // NewExactAmountOutRoutableResultPool returns the new routable result pool with the given parameters. -func NewExactAmountOutRoutableResultPool(ID uint64, poolType poolmanagertypes.PoolType, spreadFactor osmomath.Dec, tokenInDenom string, takerFee osmomath.Dec, codeID uint64) domain.RoutablePool { +func NewExactAmountOutRoutableResultPool( + ID uint64, + poolType poolmanagertypes.PoolType, + spreadFactor osmomath.Dec, + tokenInDenom string, + takerFee osmomath.Dec, + liquidityCap osmomath.Int, + codeID uint64, +) domain.RoutablePool { return &routableResultPoolImpl{ ID: ID, Type: poolType, SpreadFactor: spreadFactor, TokenInDenom: tokenInDenom, TakerFee: takerFee, + LiquidityCap: liquidityCap, CodeID: codeID, } } @@ -155,6 +174,11 @@ func (r *routableResultPoolImpl) GetTakerFee() math.LegacyDec { return r.TakerFee } +// GetLiquidityCap implements domain.RoutablePool. +func (r *routableResultPoolImpl) GetLiquidityCap() osmomath.Int { + return r.LiquidityCap +} + // GetBalances implements domain.RoutableResultPool. func (r *routableResultPoolImpl) GetBalances() sdk.Coins { return r.Balances diff --git a/router/usecase/pools/routable_stableswap_pool.go b/router/usecase/pools/routable_stableswap_pool.go index 5d55a8de0..172c9f2db 100644 --- a/router/usecase/pools/routable_stableswap_pool.go +++ b/router/usecase/pools/routable_stableswap_pool.go @@ -19,10 +19,11 @@ import ( var _ domain.RoutablePool = &routableStableswapPoolImpl{} type routableStableswapPoolImpl struct { - ChainPool *stableswap.Pool "json:\"pool\"" - TokenInDenom string "json:\"token_in_denom,omitempty\"" - TokenOutDenom string "json:\"token_out_denom,omitempty\"" - TakerFee osmomath.Dec "json:\"taker_fee\"" + ChainPool *stableswap.Pool `json:"pool"` + TokenInDenom string `json:"token_in_denom,omitempty"` + TokenOutDenom string `json:"token_out_denom,omitempty"` + TakerFee osmomath.Dec `json:"taker_fee"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` } // CalculateTokenOutByTokenIn implements RoutablePool. @@ -57,6 +58,11 @@ func (r *routableStableswapPoolImpl) GetTakerFee() math.LegacyDec { return r.TakerFee } +// GetLiquidityCap implements domain.RoutablePool. +func (r *routableStableswapPoolImpl) GetLiquidityCap() osmomath.Int { + return r.LiquidityCap +} + // GetTokenInDenom implements RoutablePool. func (r *routableStableswapPoolImpl) GetTokenInDenom() string { return r.TokenInDenom diff --git a/router/usecase/quote_in_given_out.go b/router/usecase/quote_in_given_out.go index 4e1214534..9d7c406a5 100644 --- a/router/usecase/quote_in_given_out.go +++ b/router/usecase/quote_in_given_out.go @@ -19,13 +19,14 @@ var ( // quoteExactAmountOut is a quote wrapper for exact out quotes. // Note that only the PrepareResult method is different from the quoteExactAmountIn. type quoteExactAmountOut struct { - *quoteExactAmountIn "json:\"-\"" - AmountIn osmomath.Int "json:\"amount_in\"" - AmountOut sdk.Coin "json:\"amount_out\"" - Route []domain.SplitRoute "json:\"route\"" - EffectiveFee osmomath.Dec "json:\"effective_fee\"" - PriceImpact osmomath.Dec "json:\"price_impact\"" - InBaseOutQuoteSpotPrice osmomath.Dec "json:\"in_base_out_quote_spot_price\"" + *quoteExactAmountIn `json:"-"` + AmountIn osmomath.Int `json:"amount_in"` + AmountOut sdk.Coin `json:"amount_out"` + Route []domain.SplitRoute `json:"route"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` + EffectiveFee osmomath.Dec `json:"effective_fee"` + PriceImpact osmomath.Dec `json:"price_impact"` + InBaseOutQuoteSpotPrice osmomath.Dec `json:"in_base_out_quote_spot_price"` } // PrepareResult implements domain.Quote. @@ -46,6 +47,7 @@ func (q *quoteExactAmountOut) PrepareResult(ctx context.Context, scalingFactor o q.AmountOut = q.quoteExactAmountIn.AmountIn q.AmountIn = q.quoteExactAmountIn.AmountOut q.Route = q.quoteExactAmountIn.Route + q.LiquidityCap = q.quoteExactAmountIn.LiquidityCap q.EffectiveFee = q.quoteExactAmountIn.EffectiveFee q.PriceImpact = q.quoteExactAmountIn.PriceImpact q.InBaseOutQuoteSpotPrice = q.quoteExactAmountIn.InBaseOutQuoteSpotPrice diff --git a/router/usecase/quote_out_given_in.go b/router/usecase/quote_out_given_in.go index b4a89c6bb..9e5800057 100644 --- a/router/usecase/quote_out_given_in.go +++ b/router/usecase/quote_out_given_in.go @@ -36,12 +36,13 @@ func NewQuoteExactAmountOut(q *QuoteExactAmountIn) *quoteExactAmountOut { // quoteExactAmountIn is a quote implementation for token swap method exact in. type quoteExactAmountIn struct { - AmountIn sdk.Coin "json:\"amount_in\"" - AmountOut osmomath.Int "json:\"amount_out\"" - Route []domain.SplitRoute "json:\"route\"" - EffectiveFee osmomath.Dec "json:\"effective_fee\"" - PriceImpact osmomath.Dec "json:\"price_impact\"" - InBaseOutQuoteSpotPrice osmomath.Dec "json:\"in_base_out_quote_spot_price\"" + AmountIn sdk.Coin `json:"amount_in"` + AmountOut osmomath.Int `json:"amount_out"` + Route []domain.SplitRoute `json:"route"` + LiquidityCap osmomath.Int `json:"liquidity_cap"` + EffectiveFee osmomath.Dec `json:"effective_fee"` + PriceImpact osmomath.Dec `json:"price_impact"` + InBaseOutQuoteSpotPrice osmomath.Dec `json:"in_base_out_quote_spot_price"` PriceInfo *domain.TxFeeInfo `json:"price_info,omitempty"` } @@ -57,6 +58,7 @@ func (q *quoteExactAmountIn) PrepareResult(ctx context.Context, scalingFactor os totalAmountIn := q.AmountIn.Amount.ToLegacyDec() totalFeeAcrossRoutes := osmomath.ZeroDec() + totalLiquidityCap := osmomath.ZeroInt() totalSpotPriceInBaseOutQuote := osmomath.ZeroDec() totalEffectiveSpotPriceInBaseOutQuote := osmomath.ZeroDec() @@ -88,6 +90,11 @@ func (q *quoteExactAmountIn) PrepareResult(ctx context.Context, scalingFactor os totalSpotPriceInBaseOutQuote = totalSpotPriceInBaseOutQuote.AddMut(routeSpotPriceInBaseOutQuote.MulMut(routeAmountInFraction)) totalEffectiveSpotPriceInBaseOutQuote = totalEffectiveSpotPriceInBaseOutQuote.AddMut(effectiveSpotPriceInBaseOutQuote.MulMut(routeAmountInFraction)) + // Calculate total liquidity cap for the route + for _, pool := range newPools { + totalLiquidityCap = totalLiquidityCap.Add(pool.GetLiquidityCap()) + } + resultRoutes = append(resultRoutes, &RouteWithOutAmount{ RouteImpl: route.RouteImpl{ Pools: newPools, @@ -103,6 +110,7 @@ func (q *quoteExactAmountIn) PrepareResult(ctx context.Context, scalingFactor os q.PriceImpact = totalEffectiveSpotPriceInBaseOutQuote.Quo(totalSpotPriceInBaseOutQuote).SubMut(one) } + q.LiquidityCap = totalLiquidityCap q.EffectiveFee = totalFeeAcrossRoutes q.Route = resultRoutes q.InBaseOutQuoteSpotPrice = totalSpotPriceInBaseOutQuote diff --git a/router/usecase/route/route.go b/router/usecase/route/route.go index 297ee90d3..d0bb65c0b 100644 --- a/router/usecase/route/route.go +++ b/router/usecase/route/route.go @@ -100,6 +100,7 @@ func (r RouteImpl) PrepareResultPools(ctx context.Context, tokenIn sdk.Coin, log pool.GetSpreadFactor(), pool.GetTokenOutDenom(), pool.GetTakerFee(), + pool.GetLiquidityCap(), pool.GetCodeID(), ) From 9f5d0cb78d12352abaa57b2a16b1bab7595b8b4a Mon Sep 17 00:00:00 2001 From: Deividas Petraitis Date: Thu, 21 Nov 2024 15:41:17 +0200 Subject: [PATCH 2/4] BE-654 | Fix Go tests --- domain/route_test.go | 2 + pools/usecase/pools_usecase_test.go | 2 +- router/usecase/pools/export_test.go | 3 +- router/usecase/pools/pool_factory_test.go | 5 +- router/usecase/quote_out_given_in.go | 4 +- router/usecase/quote_test.go | 6 + router/usecase/route/route_test.go | 3 + .../parsing/quote_amount_in_response.json | 100 +++++++-------- .../quote_amount_in_response_base_fee.json | 115 ++++++++--------- .../quote_amount_in_response_simulated.json | 116 +++++++++--------- .../parsing/quote_amount_out_response.json | 100 +++++++-------- router/usecase/routertesting/quote.go | 29 ++++- router/usecase/routertesting/suite.go | 1 + sqsdomain/pools.go | 7 +- 14 files changed, 272 insertions(+), 221 deletions(-) diff --git a/domain/route_test.go b/domain/route_test.go index 7f21646a7..685b8bdc8 100644 --- a/domain/route_test.go +++ b/domain/route_test.go @@ -42,6 +42,7 @@ var ( DefaultCoin0 = routertesting.DefaultCoin0 DefaultCoin1 = routertesting.DefaultCoin1 + DefaultLiquidityCap = routertesting.DefaultLiquidityCap DefaultLiquidityAmt = routertesting.DefaultLiquidityAmt // router specific variables @@ -117,6 +118,7 @@ func (s *RouterTestSuite) TestPrepareResultPools() { DefaultSpreadFactor, DenomOne, DefaultTakerFee, + DefaultLiquidityCap, notCosmWasmPoolCodeID, ), }, diff --git a/pools/usecase/pools_usecase_test.go b/pools/usecase/pools_usecase_test.go index 3b4137936..d521cf7be 100644 --- a/pools/usecase/pools_usecase_test.go +++ b/pools/usecase/pools_usecase_test.go @@ -551,7 +551,7 @@ func (s *PoolsUsecaseTestSuite) TestCalcExitCFMMPool_HappyPath() { s.Require().NoError(err) // Create sqs pool - sqsPool := sqsdomain.NewPool(cfmmPool, cfmmPool.GetSpreadFactor(s.Ctx), poolBalances) + sqsPool := sqsdomain.NewPool(cfmmPool, cfmmPool.GetSpreadFactor(s.Ctx), poolBalances, s.PoolOneLiquidityCap()) // Create default use case poolsUseCase := s.newDefaultPoolsUseCase() diff --git a/router/usecase/pools/export_test.go b/router/usecase/pools/export_test.go index 012c48302..15dcdaf0b 100644 --- a/router/usecase/pools/export_test.go +++ b/router/usecase/pools/export_test.go @@ -24,8 +24,9 @@ func NewRoutableCosmWasmPoolWithCustomModel( cosmWasmPoolsParams cosmwasmdomain.CosmWasmPoolsParams, tokenOutDenom string, takerFee osmomath.Dec, + liquidityCap osmomath.Int, ) (domain.RoutablePool, error) { - return newRoutableCosmWasmPoolWithCustomModel(pool, cosmwasmPool, cosmWasmPoolsParams, tokenOutDenom, takerFee) + return newRoutableCosmWasmPoolWithCustomModel(pool, cosmwasmPool, cosmWasmPoolsParams, tokenOutDenom, takerFee, liquidityCap) } func (r *routableAlloyTransmuterPoolImpl) CheckStaticRateLimiter(tokenInCoin sdk.Coin) error { diff --git a/router/usecase/pools/pool_factory_test.go b/router/usecase/pools/pool_factory_test.go index 6b04f4d23..8fa152ea0 100644 --- a/router/usecase/pools/pool_factory_test.go +++ b/router/usecase/pools/pool_factory_test.go @@ -66,6 +66,7 @@ func TestNewRoutableCosmWasmPoolWithCustomModel(t *testing.T) { cosmWasmConfig domain.CosmWasmPoolRouterConfig tokenOutDenom string takerFee osmomath.Dec + liquidityCap osmomath.Int expectedRoutablePool domain.RoutablePool expectedError error }{ @@ -137,6 +138,7 @@ func TestNewRoutableCosmWasmPoolWithCustomModel(t *testing.T) { }, tokenOutDenom: "quote", takerFee: orderbookTakerFee, + liquidityCap: osmomath.NewInt(851594865), expectedRoutablePool: &pools.RoutableOrderbookPoolImpl{ ChainPool: &orderbookCosmWasmPool, OrderbookData: orderbookModel.Data.Orderbook, @@ -144,6 +146,7 @@ func TestNewRoutableCosmWasmPoolWithCustomModel(t *testing.T) { TokenOutDenom: "quote", TakerFee: orderbookTakerFee, SpreadFactor: orderbookSpreadFactor, + LiquidityCap: osmomath.NewInt(851594865), }, }, { @@ -194,7 +197,7 @@ func TestNewRoutableCosmWasmPoolWithCustomModel(t *testing.T) { cosmWasmPoolsParams := cosmwasmdomain.CosmWasmPoolsParams{ Config: tt.cosmWasmConfig, } - routablePool, err := pools.NewRoutableCosmWasmPoolWithCustomModel(tt.pool, tt.cosmwasmPool, cosmWasmPoolsParams, tt.tokenOutDenom, tt.takerFee) + routablePool, err := pools.NewRoutableCosmWasmPoolWithCustomModel(tt.pool, tt.cosmwasmPool, cosmWasmPoolsParams, tt.tokenOutDenom, tt.takerFee, tt.liquidityCap) if tt.expectedError != nil { require.Equal(t, tt.expectedError, err) diff --git a/router/usecase/quote_out_given_in.go b/router/usecase/quote_out_given_in.go index 9e5800057..b2efb8c7a 100644 --- a/router/usecase/quote_out_given_in.go +++ b/router/usecase/quote_out_given_in.go @@ -92,7 +92,9 @@ func (q *quoteExactAmountIn) PrepareResult(ctx context.Context, scalingFactor os // Calculate total liquidity cap for the route for _, pool := range newPools { - totalLiquidityCap = totalLiquidityCap.Add(pool.GetLiquidityCap()) + if cap := pool.GetLiquidityCap(); !cap.IsNil() { + totalLiquidityCap = totalLiquidityCap.Add(pool.GetLiquidityCap()) + } } resultRoutes = append(resultRoutes, &RouteWithOutAmount{ diff --git a/router/usecase/quote_test.go b/router/usecase/quote_test.go index 10c80f2aa..7527f9d59 100644 --- a/router/usecase/quote_test.go +++ b/router/usecase/quote_test.go @@ -87,6 +87,7 @@ func (s *RouterTestSuite) TestPrepareResult() { poolOne.GetSpreadFactor(sdk.Context{}), USDT, takerFeeOne, + s.PoolOneLiquidityCap(), notCosmWasmPoolCodeID, ), pools.NewRoutableResultPool( @@ -95,6 +96,7 @@ func (s *RouterTestSuite) TestPrepareResult() { poolTwo.GetSpreadFactor(sdk.Context{}), USDC, takerFeeTwo, + s.PoolTwoLiquidityCap(), notCosmWasmPoolCodeID, ), }, @@ -114,6 +116,7 @@ func (s *RouterTestSuite) TestPrepareResult() { poolThree.GetSpreadFactor(sdk.Context{}), USDC, takerFeeThree, + s.PoolThreeLiquidityCap(), notCosmWasmPoolCodeID, ), }, @@ -140,6 +143,7 @@ func (s *RouterTestSuite) TestPrepareResult() { poolOne.GetSpreadFactor(sdk.Context{}), USDT, takerFeeOne, + s.PoolOneLiquidityCap(), notCosmWasmPoolCodeID, ), pools.NewExactAmountOutRoutableResultPool( @@ -148,6 +152,7 @@ func (s *RouterTestSuite) TestPrepareResult() { poolTwo.GetSpreadFactor(sdk.Context{}), USDC, takerFeeTwo, + s.PoolTwoLiquidityCap(), notCosmWasmPoolCodeID, ), }, @@ -165,6 +170,7 @@ func (s *RouterTestSuite) TestPrepareResult() { poolThree.GetSpreadFactor(sdk.Context{}), USDC, takerFeeThree, + s.PoolThreeLiquidityCap(), notCosmWasmPoolCodeID, ), }, diff --git a/router/usecase/route/route_test.go b/router/usecase/route/route_test.go index 6cb6c2c23..1cad8da62 100644 --- a/router/usecase/route/route_test.go +++ b/router/usecase/route/route_test.go @@ -157,6 +157,7 @@ func (s *RouterTestSuite) TestPrepareResultPools() { DefaultSpreadFactor, DenomOne, DefaultTakerFee, + osmomath.NewInt(3195955), notCosmWasmPoolCodeID, ), }, @@ -183,6 +184,7 @@ func (s *RouterTestSuite) TestPrepareResultPools() { DefaultSpreadFactor, DenomOne, DefaultTakerFee, + osmomath.NewInt(515881661), notCosmWasmPoolCodeID, ), pools.NewRoutableResultPool( @@ -191,6 +193,7 @@ func (s *RouterTestSuite) TestPrepareResultPools() { DefaultSpreadFactor, DenomThree, DefaultTakerFee, + osmomath.NewInt(71519599), transmuter.GetCodeId(), ), }, diff --git a/router/usecase/routertesting/parsing/quote_amount_in_response.json b/router/usecase/routertesting/parsing/quote_amount_in_response.json index beeb74174..82c4216f4 100644 --- a/router/usecase/routertesting/parsing/quote_amount_in_response.json +++ b/router/usecase/routertesting/parsing/quote_amount_in_response.json @@ -1,50 +1,54 @@ { - "amount_in": { - "denom": "ibc/EA1D43981D5C9A1C4AAEA9C23BB1D4FA126BA9BC7020A25E0AE4AA841EA25DC5", - "amount": "10000000" - }, - "amount_out": "40000000", - "route": [ - { - "pools": [ - { - "id": 1, - "type": 0, - "balances": [], - "spread_factor": "0.010000000000000000", - "token_out_denom": "ibc/4ABBEF4C8926DDDB320AE5188CFD63267ABBCEFC0583E4AE05D6E5AA2401DDAB", - "taker_fee": "0.020000000000000000" - }, - { - "id": 2, - "type": 0, - "balances": [], - "spread_factor": "0.030000000000000000", - "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", - "taker_fee": "0.000400000000000000" - } - ], - "has-cw-pool": false, - "out_amount": "20000000", - "in_amount": "5000000" - }, - { - "pools": [ - { - "id": 3, - "type": 0, - "balances": [], - "spread_factor": "0.005000000000000000", - "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", - "taker_fee": "0.003000000000000000" - } - ], - "has-cw-pool": false, - "out_amount": "20000000", - "in_amount": "5000000" - } - ], - "effective_fee": "0.011696000000000000", - "price_impact": "-0.565353638051463862", - "in_base_out_quote_spot_price": "4.500000000000000000" + "amount_in": { + "denom": "ibc/EA1D43981D5C9A1C4AAEA9C23BB1D4FA126BA9BC7020A25E0AE4AA841EA25DC5", + "amount": "10000000" + }, + "amount_out": "40000000", + "route": [ + { + "pools": [ + { + "id": 1, + "type": 0, + "balances": [], + "spread_factor": "0.010000000000000000", + "token_out_denom": "ibc/4ABBEF4C8926DDDB320AE5188CFD63267ABBCEFC0583E4AE05D6E5AA2401DDAB", + "taker_fee": "0.020000000000000000", + "liquidity_cap": "1519153195" + }, + { + "id": 2, + "type": 0, + "balances": [], + "spread_factor": "0.030000000000000000", + "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", + "taker_fee": "0.000400000000000000", + "liquidity_cap": "85196078" + } + ], + "has-cw-pool": false, + "out_amount": "20000000", + "in_amount": "5000000" + }, + { + "pools": [ + { + "id": 3, + "type": 0, + "balances": [], + "spread_factor": "0.005000000000000000", + "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", + "taker_fee": "0.003000000000000000", + "liquidity_cap": "719951" + } + ], + "has-cw-pool": false, + "out_amount": "20000000", + "in_amount": "5000000" + } + ], + "liquidity_cap": "1605069224", + "effective_fee": "0.011696000000000000", + "price_impact": "-0.565353638051463862", + "in_base_out_quote_spot_price": "4.500000000000000000" } diff --git a/router/usecase/routertesting/parsing/quote_amount_in_response_base_fee.json b/router/usecase/routertesting/parsing/quote_amount_in_response_base_fee.json index d0e944600..c8068e184 100644 --- a/router/usecase/routertesting/parsing/quote_amount_in_response_base_fee.json +++ b/router/usecase/routertesting/parsing/quote_amount_in_response_base_fee.json @@ -1,57 +1,60 @@ { - "amount_in": { - "denom": "ibc/EA1D43981D5C9A1C4AAEA9C23BB1D4FA126BA9BC7020A25E0AE4AA841EA25DC5", - "amount": "10000000" - }, - "amount_out": "40000000", - "route": [ - { - "pools": [ - { - "id": 1, - "type": 0, - "balances": [], - "spread_factor": "0.010000000000000000", - "token_out_denom": "ibc/4ABBEF4C8926DDDB320AE5188CFD63267ABBCEFC0583E4AE05D6E5AA2401DDAB", - "taker_fee": "0.020000000000000000" - }, - { - "id": 2, - "type": 0, - "balances": [], - "spread_factor": "0.030000000000000000", - "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", - "taker_fee": "0.000400000000000000" - } - ], - "has-cw-pool": false, - "out_amount": "20000000", - "in_amount": "5000000" - }, - { - "pools": [ - { - "id": 3, - "type": 0, - "balances": [], - "spread_factor": "0.005000000000000000", - "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", - "taker_fee": "0.003000000000000000" - } - ], - "has-cw-pool": false, - "out_amount": "20000000", - "in_amount": "5000000" - } - ], - "effective_fee": "0.011696000000000000", - "price_impact": "-0.565353638051463862", - "in_base_out_quote_spot_price": "4.500000000000000000", - "price_info": { - "fee_coin": { - "amount": "0" - }, - "base_fee": "0.500000000000000000" - } - } - \ No newline at end of file + "amount_in": { + "denom": "ibc/EA1D43981D5C9A1C4AAEA9C23BB1D4FA126BA9BC7020A25E0AE4AA841EA25DC5", + "amount": "10000000" + }, + "amount_out": "40000000", + "route": [ + { + "pools": [ + { + "id": 1, + "type": 0, + "balances": [], + "spread_factor": "0.010000000000000000", + "token_out_denom": "ibc/4ABBEF4C8926DDDB320AE5188CFD63267ABBCEFC0583E4AE05D6E5AA2401DDAB", + "taker_fee": "0.020000000000000000", + "liquidity_cap": "1519153195" + }, + { + "id": 2, + "type": 0, + "balances": [], + "spread_factor": "0.030000000000000000", + "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", + "taker_fee": "0.000400000000000000", + "liquidity_cap": "85196078" + } + ], + "has-cw-pool": false, + "out_amount": "20000000", + "in_amount": "5000000" + }, + { + "pools": [ + { + "id": 3, + "type": 0, + "balances": [], + "spread_factor": "0.005000000000000000", + "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", + "taker_fee": "0.003000000000000000", + "liquidity_cap": "719951" + } + ], + "has-cw-pool": false, + "out_amount": "20000000", + "in_amount": "5000000" + } + ], + "liquidity_cap": "1605069224", + "effective_fee": "0.011696000000000000", + "price_impact": "-0.565353638051463862", + "in_base_out_quote_spot_price": "4.500000000000000000", + "price_info": { + "fee_coin": { + "amount": "0" + }, + "base_fee": "0.500000000000000000" + } +} diff --git a/router/usecase/routertesting/parsing/quote_amount_in_response_simulated.json b/router/usecase/routertesting/parsing/quote_amount_in_response_simulated.json index e034fadc6..a9d03ad53 100644 --- a/router/usecase/routertesting/parsing/quote_amount_in_response_simulated.json +++ b/router/usecase/routertesting/parsing/quote_amount_in_response_simulated.json @@ -1,58 +1,62 @@ { - "amount_in": { - "denom": "ibc/EA1D43981D5C9A1C4AAEA9C23BB1D4FA126BA9BC7020A25E0AE4AA841EA25DC5", - "amount": "10000000" - }, - "amount_out": "40000000", - "route": [ - { - "pools": [ - { - "id": 1, - "type": 0, - "balances": [], - "spread_factor": "0.010000000000000000", - "token_out_denom": "ibc/4ABBEF4C8926DDDB320AE5188CFD63267ABBCEFC0583E4AE05D6E5AA2401DDAB", - "taker_fee": "0.020000000000000000" - }, - { - "id": 2, - "type": 0, - "balances": [], - "spread_factor": "0.030000000000000000", - "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", - "taker_fee": "0.000400000000000000" - } - ], - "has-cw-pool": false, - "out_amount": "20000000", - "in_amount": "5000000" - }, - { - "pools": [ - { - "id": 3, - "type": 0, - "balances": [], - "spread_factor": "0.005000000000000000", - "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", - "taker_fee": "0.003000000000000000" - } - ], - "has-cw-pool": false, - "out_amount": "20000000", - "in_amount": "5000000" - } - ], - "effective_fee": "0.011696000000000000", - "price_impact": "-0.565353638051463862", - "in_base_out_quote_spot_price": "4.500000000000000000", - "price_info": { - "adjusted_gas_used": 1000000, - "fee_coin": { - "denom": "uosmo", - "amount": "1000" - }, - "base_fee": "0.500000000000000000" - } + "amount_in": { + "denom": "ibc/EA1D43981D5C9A1C4AAEA9C23BB1D4FA126BA9BC7020A25E0AE4AA841EA25DC5", + "amount": "10000000" + }, + "amount_out": "40000000", + "route": [ + { + "pools": [ + { + "id": 1, + "type": 0, + "balances": [], + "spread_factor": "0.010000000000000000", + "token_out_denom": "ibc/4ABBEF4C8926DDDB320AE5188CFD63267ABBCEFC0583E4AE05D6E5AA2401DDAB", + "taker_fee": "0.020000000000000000", + "liquidity_cap": "1519153195" + }, + { + "id": 2, + "type": 0, + "balances": [], + "spread_factor": "0.030000000000000000", + "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", + "taker_fee": "0.000400000000000000", + "liquidity_cap": "85196078" + } + ], + "has-cw-pool": false, + "out_amount": "20000000", + "in_amount": "5000000" + }, + { + "pools": [ + { + "id": 3, + "type": 0, + "balances": [], + "spread_factor": "0.005000000000000000", + "token_out_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", + "taker_fee": "0.003000000000000000", + "liquidity_cap": "719951" + } + ], + "has-cw-pool": false, + "out_amount": "20000000", + "in_amount": "5000000" + } + ], + "liquidity_cap": "1605069224", + "effective_fee": "0.011696000000000000", + "price_impact": "-0.565353638051463862", + "in_base_out_quote_spot_price": "4.500000000000000000", + "price_info": { + "adjusted_gas_used": 1000000, + "fee_coin": { + "denom": "uosmo", + "amount": "1000" + }, + "base_fee": "0.500000000000000000" + } } diff --git a/router/usecase/routertesting/parsing/quote_amount_out_response.json b/router/usecase/routertesting/parsing/quote_amount_out_response.json index bf873d501..bbd6e93f7 100644 --- a/router/usecase/routertesting/parsing/quote_amount_out_response.json +++ b/router/usecase/routertesting/parsing/quote_amount_out_response.json @@ -1,50 +1,54 @@ { - "amount_in": "40000000", - "amount_out": { - "denom": "ibc/EA1D43981D5C9A1C4AAEA9C23BB1D4FA126BA9BC7020A25E0AE4AA841EA25DC5", - "amount": "10000000" - }, - "route": [ - { - "pools": [ - { - "id": 1, - "type": 0, - "balances": [], - "spread_factor": "0.010000000000000000", - "token_in_denom": "ibc/4ABBEF4C8926DDDB320AE5188CFD63267ABBCEFC0583E4AE05D6E5AA2401DDAB", - "taker_fee": "0.020000000000000000" - }, - { - "id": 2, - "type": 0, - "balances": [], - "spread_factor": "0.030000000000000000", - "token_in_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", - "taker_fee": "0.000400000000000000" - } - ], - "has-cw-pool": false, - "out_amount": "5000000", - "in_amount": "13333333" - }, - { - "pools": [ - { - "id": 3, - "type": 0, - "balances": [], - "spread_factor": "0.005000000000000000", - "token_in_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", - "taker_fee": "0.003000000000000000" - } - ], - "has-cw-pool": false, - "out_amount": "2500000", - "in_amount": "8000000" - } - ], - "effective_fee": "0.010946000000000000", - "price_impact": "-0.593435820925030124", - "in_base_out_quote_spot_price": "3.500000000000000000" + "amount_in": "40000000", + "amount_out": { + "denom": "ibc/EA1D43981D5C9A1C4AAEA9C23BB1D4FA126BA9BC7020A25E0AE4AA841EA25DC5", + "amount": "10000000" + }, + "route": [ + { + "pools": [ + { + "id": 1, + "type": 0, + "balances": [], + "spread_factor": "0.010000000000000000", + "token_in_denom": "ibc/4ABBEF4C8926DDDB320AE5188CFD63267ABBCEFC0583E4AE05D6E5AA2401DDAB", + "taker_fee": "0.020000000000000000", + "liquidity_cap": "1519153195" + }, + { + "id": 2, + "type": 0, + "balances": [], + "spread_factor": "0.030000000000000000", + "token_in_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", + "taker_fee": "0.000400000000000000", + "liquidity_cap": "85196078" + } + ], + "has-cw-pool": false, + "out_amount": "5000000", + "in_amount": "13333333" + }, + { + "pools": [ + { + "id": 3, + "type": 0, + "balances": [], + "spread_factor": "0.005000000000000000", + "token_in_denom": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", + "taker_fee": "0.003000000000000000", + "liquidity_cap": "719951" + } + ], + "has-cw-pool": false, + "out_amount": "2500000", + "in_amount": "8000000" + } + ], + "liquidity_cap": "1605069224", + "effective_fee": "0.010946000000000000", + "price_impact": "-0.593435820925030124", + "in_base_out_quote_spot_price": "3.500000000000000000" } diff --git a/router/usecase/routertesting/quote.go b/router/usecase/routertesting/quote.go index 520675781..fdae38c53 100644 --- a/router/usecase/routertesting/quote.go +++ b/router/usecase/routertesting/quote.go @@ -39,12 +39,29 @@ var ( sdk.NewCoin(ETH, defaultAmount), sdk.NewCoin(USDC, defaultAmount.MulRaw(4)), ) + + poolOneLiquidityCap = osmomath.NewInt(151_9153_195) + poolTwoLiquidityCap = osmomath.NewInt(85_196_078) + poolThreeLiquidityCap = osmomath.NewInt(719_951) ) +func (s *RouterTestHelper) PoolOneLiquidityCap() osmomath.Int { + return poolOneLiquidityCap +} + +func (s *RouterTestHelper) PoolTwoLiquidityCap() osmomath.Int { + return poolTwoLiquidityCap +} + +func (s *RouterTestHelper) PoolThreeLiquidityCap() osmomath.Int { + return poolThreeLiquidityCap +} + func (s *RouterTestHelper) newRoutablePool(pool sqsdomain.PoolI, tokenOutDenom string, takerFee osmomath.Dec) domain.RoutablePool { cosmWasmPoolsParams := cosmwasmdomain.CosmWasmPoolsParams{ ScalingFactorGetterCb: domain.UnsetScalingFactorGetterCb, } + routablePool, err := pools.NewRoutablePool(pool, tokenOutDenom, takerFee, cosmWasmPoolsParams) s.Require().NoError(err) @@ -65,12 +82,12 @@ func (s *RouterTestHelper) NewExactAmountInQuote(p1, p2, p3 poolmanagertypes.Poo RouteImpl: route.RouteImpl{ Pools: []domain.RoutablePool{ s.newRoutablePool( - sqsdomain.NewPool(p1, p1.GetSpreadFactor(sdk.Context{}), poolOneBalances), + sqsdomain.NewPool(p1, p1.GetSpreadFactor(sdk.Context{}), poolOneBalances, poolOneLiquidityCap), USDT, takerFeeOne, ), s.newRoutablePool( - sqsdomain.NewPool(p2, p2.GetSpreadFactor(sdk.Context{}), poolTwoBalances), + sqsdomain.NewPool(p2, p2.GetSpreadFactor(sdk.Context{}), poolTwoBalances, poolTwoLiquidityCap), USDC, takerFeeTwo, ), @@ -86,7 +103,7 @@ func (s *RouterTestHelper) NewExactAmountInQuote(p1, p2, p3 poolmanagertypes.Poo RouteImpl: route.RouteImpl{ Pools: []domain.RoutablePool{ s.newRoutablePool( - sqsdomain.NewPool(p3, p3.GetSpreadFactor(sdk.Context{}), poolThreeBalances), + sqsdomain.NewPool(p3, p3.GetSpreadFactor(sdk.Context{}), poolThreeBalances, poolThreeLiquidityCap), USDC, takerFeeThree, ), @@ -114,12 +131,12 @@ func (s *RouterTestHelper) NewExactAmountOutQuote(p1, p2, p3 poolmanagertypes.Po RouteImpl: route.RouteImpl{ Pools: []domain.RoutablePool{ s.newRoutablePool( - sqsdomain.NewPool(p1, p1.GetSpreadFactor(sdk.Context{}), poolOneBalances), + sqsdomain.NewPool(p1, p1.GetSpreadFactor(sdk.Context{}), poolOneBalances, poolOneLiquidityCap), USDT, takerFeeOne, ), s.newRoutablePool( - sqsdomain.NewPool(p2, p2.GetSpreadFactor(sdk.Context{}), poolTwoBalances), + sqsdomain.NewPool(p2, p2.GetSpreadFactor(sdk.Context{}), poolTwoBalances, poolTwoLiquidityCap), USDC, takerFeeTwo, ), @@ -133,7 +150,7 @@ func (s *RouterTestHelper) NewExactAmountOutQuote(p1, p2, p3 poolmanagertypes.Po RouteImpl: route.RouteImpl{ Pools: []domain.RoutablePool{ s.newRoutablePool( - sqsdomain.NewPool(p3, p3.GetSpreadFactor(sdk.Context{}), poolThreeBalances), + sqsdomain.NewPool(p3, p3.GetSpreadFactor(sdk.Context{}), poolThreeBalances, poolThreeLiquidityCap), USDC, takerFeeThree, ), diff --git a/router/usecase/routertesting/suite.go b/router/usecase/routertesting/suite.go index 097bae0ea..09ddfdfd1 100644 --- a/router/usecase/routertesting/suite.go +++ b/router/usecase/routertesting/suite.go @@ -79,6 +79,7 @@ var ( DefaultCoin1 = apptesting.DefaultCoin1 DefaultLiquidityAmt = apptesting.DefaultLiquidityAmt + DefaultLiquidityCap = osmomath.NewInt(10) // router specific variables DefaultTickModel = &sqsdomain.TickModel{ diff --git a/sqsdomain/pools.go b/sqsdomain/pools.go index 6ce6b71a6..b85868467 100644 --- a/sqsdomain/pools.go +++ b/sqsdomain/pools.go @@ -99,12 +99,13 @@ type PoolWrapper struct { var _ PoolI = &PoolWrapper{} -func NewPool(model poolmanagertypes.PoolI, spreadFactor osmomath.Dec, balances sdk.Coins) PoolI { +func NewPool(model poolmanagertypes.PoolI, spreadFactor osmomath.Dec, balances sdk.Coins, liquidityCap osmomath.Int) PoolI { return &PoolWrapper{ ChainModel: model, SQSModel: SQSPool{ - SpreadFactor: spreadFactor, - Balances: balances, + SpreadFactor: spreadFactor, + Balances: balances, + PoolLiquidityCap: liquidityCap, }, } } From a6e3f3e3d6d4129d7e302fdc328bf75767ac0ffd Mon Sep 17 00:00:00 2001 From: Deividas Petraitis Date: Thu, 21 Nov 2024 15:51:41 +0200 Subject: [PATCH 3/4] BE-654 | Reuse liquidity cap in tests --- router/usecase/route/route_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/router/usecase/route/route_test.go b/router/usecase/route/route_test.go index 1cad8da62..c734e8ef3 100644 --- a/router/usecase/route/route_test.go +++ b/router/usecase/route/route_test.go @@ -157,7 +157,7 @@ func (s *RouterTestSuite) TestPrepareResultPools() { DefaultSpreadFactor, DenomOne, DefaultTakerFee, - osmomath.NewInt(3195955), + s.PoolOneLiquidityCap(), notCosmWasmPoolCodeID, ), }, @@ -184,7 +184,7 @@ func (s *RouterTestSuite) TestPrepareResultPools() { DefaultSpreadFactor, DenomOne, DefaultTakerFee, - osmomath.NewInt(515881661), + s.PoolTwoLiquidityCap(), notCosmWasmPoolCodeID, ), pools.NewRoutableResultPool( @@ -193,7 +193,7 @@ func (s *RouterTestSuite) TestPrepareResultPools() { DefaultSpreadFactor, DenomThree, DefaultTakerFee, - osmomath.NewInt(71519599), + s.PoolThreeLiquidityCap(), transmuter.GetCodeId(), ), }, From 1eb0dcc3945d4ea7dbae16efa0de5d648155b43b Mon Sep 17 00:00:00 2001 From: Deividas Petraitis Date: Thu, 21 Nov 2024 16:27:45 +0200 Subject: [PATCH 4/4] BE-654 | Add liquidity cap overflow flag --- router/usecase/quote_in_given_out.go | 2 ++ router/usecase/quote_out_given_in.go | 10 +++++++++- .../parsing/quote_amount_in_response.json | 1 + .../parsing/quote_amount_in_response_base_fee.json | 1 + .../parsing/quote_amount_in_response_simulated.json | 1 + .../parsing/quote_amount_out_response.json | 1 + 6 files changed, 15 insertions(+), 1 deletion(-) diff --git a/router/usecase/quote_in_given_out.go b/router/usecase/quote_in_given_out.go index 9d7c406a5..0a015a940 100644 --- a/router/usecase/quote_in_given_out.go +++ b/router/usecase/quote_in_given_out.go @@ -24,6 +24,7 @@ type quoteExactAmountOut struct { AmountOut sdk.Coin `json:"amount_out"` Route []domain.SplitRoute `json:"route"` LiquidityCap osmomath.Int `json:"liquidity_cap"` + LiquidityCapOverflow bool `json:"liquidity_cap_overflow"` EffectiveFee osmomath.Dec `json:"effective_fee"` PriceImpact osmomath.Dec `json:"price_impact"` InBaseOutQuoteSpotPrice osmomath.Dec `json:"in_base_out_quote_spot_price"` @@ -48,6 +49,7 @@ func (q *quoteExactAmountOut) PrepareResult(ctx context.Context, scalingFactor o q.AmountIn = q.quoteExactAmountIn.AmountOut q.Route = q.quoteExactAmountIn.Route q.LiquidityCap = q.quoteExactAmountIn.LiquidityCap + q.LiquidityCapOverflow = q.quoteExactAmountIn.LiquidityCapOverflow q.EffectiveFee = q.quoteExactAmountIn.EffectiveFee q.PriceImpact = q.quoteExactAmountIn.PriceImpact q.InBaseOutQuoteSpotPrice = q.quoteExactAmountIn.InBaseOutQuoteSpotPrice diff --git a/router/usecase/quote_out_given_in.go b/router/usecase/quote_out_given_in.go index b2efb8c7a..4ab98dd9a 100644 --- a/router/usecase/quote_out_given_in.go +++ b/router/usecase/quote_out_given_in.go @@ -40,6 +40,7 @@ type quoteExactAmountIn struct { AmountOut osmomath.Int `json:"amount_out"` Route []domain.SplitRoute `json:"route"` LiquidityCap osmomath.Int `json:"liquidity_cap"` + LiquidityCapOverflow bool `json:"liquidity_cap_overflow"` EffectiveFee osmomath.Dec `json:"effective_fee"` PriceImpact osmomath.Dec `json:"price_impact"` InBaseOutQuoteSpotPrice osmomath.Dec `json:"in_base_out_quote_spot_price"` @@ -58,6 +59,7 @@ func (q *quoteExactAmountIn) PrepareResult(ctx context.Context, scalingFactor os totalAmountIn := q.AmountIn.Amount.ToLegacyDec() totalFeeAcrossRoutes := osmomath.ZeroDec() + totalLiquidityCapOverflow := false totalLiquidityCap := osmomath.ZeroInt() totalSpotPriceInBaseOutQuote := osmomath.ZeroDec() totalEffectiveSpotPriceInBaseOutQuote := osmomath.ZeroDec() @@ -93,7 +95,12 @@ func (q *quoteExactAmountIn) PrepareResult(ctx context.Context, scalingFactor os // Calculate total liquidity cap for the route for _, pool := range newPools { if cap := pool.GetLiquidityCap(); !cap.IsNil() { - totalLiquidityCap = totalLiquidityCap.Add(pool.GetLiquidityCap()) + var err error + totalLiquidityCap, err = totalLiquidityCap.SafeAdd(pool.GetLiquidityCap()) + if err != nil { + totalLiquidityCapOverflow = true + break + } } } @@ -113,6 +120,7 @@ func (q *quoteExactAmountIn) PrepareResult(ctx context.Context, scalingFactor os } q.LiquidityCap = totalLiquidityCap + q.LiquidityCapOverflow = totalLiquidityCapOverflow q.EffectiveFee = totalFeeAcrossRoutes q.Route = resultRoutes q.InBaseOutQuoteSpotPrice = totalSpotPriceInBaseOutQuote diff --git a/router/usecase/routertesting/parsing/quote_amount_in_response.json b/router/usecase/routertesting/parsing/quote_amount_in_response.json index 82c4216f4..cf17f0ef8 100644 --- a/router/usecase/routertesting/parsing/quote_amount_in_response.json +++ b/router/usecase/routertesting/parsing/quote_amount_in_response.json @@ -48,6 +48,7 @@ } ], "liquidity_cap": "1605069224", + "liquidity_cap_overflow": false, "effective_fee": "0.011696000000000000", "price_impact": "-0.565353638051463862", "in_base_out_quote_spot_price": "4.500000000000000000" diff --git a/router/usecase/routertesting/parsing/quote_amount_in_response_base_fee.json b/router/usecase/routertesting/parsing/quote_amount_in_response_base_fee.json index c8068e184..c61e900e8 100644 --- a/router/usecase/routertesting/parsing/quote_amount_in_response_base_fee.json +++ b/router/usecase/routertesting/parsing/quote_amount_in_response_base_fee.json @@ -48,6 +48,7 @@ } ], "liquidity_cap": "1605069224", + "liquidity_cap_overflow": false, "effective_fee": "0.011696000000000000", "price_impact": "-0.565353638051463862", "in_base_out_quote_spot_price": "4.500000000000000000", diff --git a/router/usecase/routertesting/parsing/quote_amount_in_response_simulated.json b/router/usecase/routertesting/parsing/quote_amount_in_response_simulated.json index a9d03ad53..a4734e4b3 100644 --- a/router/usecase/routertesting/parsing/quote_amount_in_response_simulated.json +++ b/router/usecase/routertesting/parsing/quote_amount_in_response_simulated.json @@ -48,6 +48,7 @@ } ], "liquidity_cap": "1605069224", + "liquidity_cap_overflow": false, "effective_fee": "0.011696000000000000", "price_impact": "-0.565353638051463862", "in_base_out_quote_spot_price": "4.500000000000000000", diff --git a/router/usecase/routertesting/parsing/quote_amount_out_response.json b/router/usecase/routertesting/parsing/quote_amount_out_response.json index bbd6e93f7..e3974d576 100644 --- a/router/usecase/routertesting/parsing/quote_amount_out_response.json +++ b/router/usecase/routertesting/parsing/quote_amount_out_response.json @@ -48,6 +48,7 @@ } ], "liquidity_cap": "1605069224", + "liquidity_cap_overflow": false, "effective_fee": "0.010946000000000000", "price_impact": "-0.593435820925030124", "in_base_out_quote_spot_price": "3.500000000000000000"