diff --git a/domain/mocks/chain_pool_mock.go b/domain/mocks/chain_pool_mock.go new file mode 100644 index 000000000..eb056878a --- /dev/null +++ b/domain/mocks/chain_pool_mock.go @@ -0,0 +1,70 @@ +package mocks + +import ( + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/types" + "github.com/osmosis-labs/osmosis/osmomath" + poolmanagertypes "github.com/osmosis-labs/osmosis/v25/x/poolmanager/types" +) + +type ChainPoolMock struct { + ID uint64 + Type poolmanagertypes.PoolType +} + +// AsSerializablePool implements types.PoolI. +func (c *ChainPoolMock) AsSerializablePool() poolmanagertypes.PoolI { + panic("unimplemented") +} + +// GetAddress implements types.PoolI. +func (c *ChainPoolMock) GetAddress() types.AccAddress { + panic("unimplemented") +} + +// GetId implements types.PoolI. +func (c *ChainPoolMock) GetId() uint64 { + return c.ID +} + +// GetPoolDenoms implements types.PoolI. +func (c *ChainPoolMock) GetPoolDenoms(types.Context) []string { + panic("unimplemented") +} + +// GetSpreadFactor implements types.PoolI. +func (c *ChainPoolMock) GetSpreadFactor(ctx types.Context) math.LegacyDec { + panic("unimplemented") +} + +// GetType implements types.PoolI. +func (c *ChainPoolMock) GetType() poolmanagertypes.PoolType { + return c.Type +} + +// IsActive implements types.PoolI. +func (c *ChainPoolMock) IsActive(ctx types.Context) bool { + panic("unimplemented") +} + +// ProtoMessage implements types.PoolI. +func (c *ChainPoolMock) ProtoMessage() { + panic("unimplemented") +} + +// Reset implements types.PoolI. +func (c *ChainPoolMock) Reset() { + panic("unimplemented") +} + +// SpotPrice implements types.PoolI. +func (c *ChainPoolMock) SpotPrice(ctx types.Context, quoteAssetDenom string, baseAssetDenom string) (osmomath.BigDec, error) { + panic("unimplemented") +} + +// String implements types.PoolI. +func (c *ChainPoolMock) String() string { + panic("unimplemented") +} + +var _ poolmanagertypes.PoolI = &ChainPoolMock{} diff --git a/router/usecase/router.go b/router/usecase/router.go index 77e1c1e42..47a923c16 100644 --- a/router/usecase/router.go +++ b/router/usecase/router.go @@ -138,20 +138,22 @@ func sortPools(pools []sqsdomain.PoolI, transmuterCodeIDs map[uint64]struct{}, t // Transmuter pools get a boost equal to 3/2 of total value locked across all pools if pool.GetType() == poolmanagertypes.CosmWasm { - cosmWasmPool, ok := pool.GetUnderlyingPool().(cosmwasmpooltypes.CosmWasmExtension) - if !ok { - logger.Debug("failed to cast a cosm wasm pool, skip silently", zap.Uint64("pool_id", pool.GetId())) - continue - } - _, isTransmuter := transmuterCodeIDs[cosmWasmPool.GetCodeId()] - if isTransmuter { - rating += totalTVLFloat * 1.5 - } - // Grant additional rating to alloyed transmuter. cosmWasmPoolModel := pool.GetSQSPoolModel().CosmWasmPoolModel if cosmWasmPoolModel != nil && cosmWasmPoolModel.IsAlloyTransmuter() { + // Grant additional rating if alloyed transmuter. rating += totalTVLFloat * 1.5 + } else { + // Grant additional rating if transmuter. + cosmWasmPool, ok := pool.GetUnderlyingPool().(cosmwasmpooltypes.CosmWasmExtension) + if !ok { + logger.Debug("failed to cast a cosm wasm pool, skip silently", zap.Uint64("pool_id", pool.GetId())) + continue + } + _, isTransmuter := transmuterCodeIDs[cosmWasmPool.GetCodeId()] + if isTransmuter { + rating += totalTVLFloat * 1.5 + } } } diff --git a/router/usecase/router_test.go b/router/usecase/router_test.go index 2393afddc..e3e0357de 100644 --- a/router/usecase/router_test.go +++ b/router/usecase/router_test.go @@ -13,6 +13,8 @@ import ( "github.com/osmosis-labs/sqs/sqsdomain" "github.com/osmosis-labs/osmosis/osmomath" + poolmanagertypes "github.com/osmosis-labs/osmosis/v25/x/poolmanager/types" + "github.com/osmosis-labs/sqs/domain/mocks" ) type RouterTestSuite struct { @@ -72,6 +74,8 @@ func (s *RouterTestSuite) TestRouterSorting() { secondBalancerPoolPoolID = s.PrepareBalancerPool() thirdBalancerPoolID = s.PrepareBalancerPool() + alloyedPoolID = thirdBalancerPoolID + 1 + // Note that these default denoms might not actually match the pool denoms for simplicity. defaultDenoms = []string{"foo", "bar"} ) @@ -145,6 +149,19 @@ func (s *RouterTestSuite) TestRouterSorting() { PoolDenoms: defaultDenoms, }, }, + &sqsdomain.PoolWrapper{ + ChainModel: &mocks.ChainPoolMock{ID: alloyedPoolID, Type: poolmanagertypes.CosmWasm}, + SQSModel: sqsdomain.SQSPool{ + PoolLiquidityCap: osmomath.NewInt(3*OsmoPrecisionMultiplier - 1), // 3 * precision - 1 + PoolDenoms: defaultDenoms, + CosmWasmPoolModel: &sqsdomain.CosmWasmPoolModel{ + ContractInfo: sqsdomain.ContractInfo{ + Contract: sqsdomain.AlloyTranmuterName, + Version: sqsdomain.AlloyTransmuterMinVersion, + }, + }, + }, + }, // Note that the pools below have higher TVL. // However, since they have TVL error flag set, they @@ -173,6 +190,10 @@ func (s *RouterTestSuite) TestRouterSorting() { // Transmuter pool is first due to no slippage swaps allPool.CosmWasmPoolID, + // Alloyed is second since it has the same bonus as transmuter but lower + // liquidity cap. + alloyedPoolID, + // Balancer is above concentrated pool due to being preferred allPool.BalancerPoolID, diff --git a/sqsdomain/cw_pool.go b/sqsdomain/cw_pool.go index ba7f163d5..878b6433f 100644 --- a/sqsdomain/cw_pool.go +++ b/sqsdomain/cw_pool.go @@ -11,6 +11,13 @@ type ContractInfo struct { Version string `json:"version"` } +const ( + AlloyTranmuterName = "crates.io:transmuter" + AlloyTransmuterMinVersion = "3.0.0" + + alloyTransmuterMinVersionStr = ">= " + AlloyTransmuterMinVersion +) + // Check if the contract info matches the given contract and version constrains func (ci *ContractInfo) Matches(contract string, versionConstrains *semver.Constraints) bool { version, err := semver.NewVersion(ci.Version) @@ -51,15 +58,12 @@ func NewCWPoolModel(contract string, version string, data CWPoolData) *CosmWasmP } func (model *CosmWasmPoolModel) IsAlloyTransmuter() bool { - name := "crates.io:transmuter" - version := ">= 3.0.0" - - constraints, err := semver.NewConstraint(version) + constraints, err := semver.NewConstraint(alloyTransmuterMinVersionStr) // this must never panic if err != nil { panic(err) } - return model.ContractInfo.Matches(name, constraints) + return model.ContractInfo.Matches(AlloyTranmuterName, constraints) } // === custom cw pool data ===