diff --git a/app/sidecar_query_server.go b/app/sidecar_query_server.go index da6aecd2..1f335492 100644 --- a/app/sidecar_query_server.go +++ b/app/sidecar_query_server.go @@ -173,10 +173,7 @@ func NewSideCarQueryServer(appCodec codec.Codec, config domain.Config, logger lo } // Initialized tokens usecase - tokensUseCase, err := tokensUseCase.NewTokensUsecase(timeoutContext, tokenMetadataByChainDenom) - if err != nil { - return nil, err - } + tokensUseCase := tokensUseCase.NewTokensUsecase(timeoutContext, tokenMetadataByChainDenom) // HTTP handlers poolsHttpDelivery.NewPoolsHandler(e, poolsUseCase) diff --git a/router/usecase/candidate_routes_test.go b/router/usecase/candidate_routes_test.go index 3ee9b35b..987ace64 100644 --- a/router/usecase/candidate_routes_test.go +++ b/router/usecase/candidate_routes_test.go @@ -2,12 +2,13 @@ package usecase_test import ( "github.com/osmosis-labs/sqs/domain" + "github.com/osmosis-labs/sqs/router/usecase/routertesting" "github.com/osmosis-labs/sqs/sqsdomain" ) // Validates that the router returns the correct routes for the given token pair. func (s *RouterTestSuite) TestGetCandidateRoutesBFS_OSMOATOM() { - config := defaultRouterConfig + config := routertesting.DefaultRouterConfig config.MaxPoolsPerRoute = 5 config.MaxRoutes = 10 @@ -32,7 +33,7 @@ func (s *RouterTestSuite) TestGetCandidateRoutesBFS_OSMOATOM() { // Validates that the router returns the correct routes for the given token pair. // Inverting the swap direction should return the same routes. func (s *RouterTestSuite) TestGetCandidateRoutesBFS_OSMOstOSMO() { - config := defaultRouterConfig + config := routertesting.DefaultRouterConfig config.MaxPoolsPerRoute = 5 config.MaxRoutes = 10 config.MinOSMOLiquidity = 1000 @@ -88,7 +89,7 @@ func (s *RouterTestSuite) TestGetCandidateRoutesBFS_ATOMUSDT() { // Validate that can find at least 1 route with no error for top 10 // pairs by volume. func (s *RouterTestSuite) TestGetCandidateRoutesBFS_Top10VolumePairs() { - config := defaultRouterConfig + config := routertesting.DefaultRouterConfig config.MaxPoolsPerRoute = 3 config.MaxRoutes = 10 router, _ := s.SetupMainnetRouter(config) diff --git a/router/usecase/optimized_routes_test.go b/router/usecase/optimized_routes_test.go index 94f2f06d..04673260 100644 --- a/router/usecase/optimized_routes_test.go +++ b/router/usecase/optimized_routes_test.go @@ -15,7 +15,6 @@ import ( "github.com/osmosis-labs/sqs/domain" "github.com/osmosis-labs/sqs/domain/cache" "github.com/osmosis-labs/sqs/domain/mocks" - "github.com/osmosis-labs/sqs/domain/mvc" "github.com/osmosis-labs/sqs/log" poolsusecase "github.com/osmosis-labs/sqs/pools/usecase" "github.com/osmosis-labs/sqs/router/usecase" @@ -656,7 +655,7 @@ func (s *RouterTestSuite) TestGetOptimalQuote_Mainnet() { tc := tc s.Run(name, func() { // Setup router config - config := defaultRouterConfig + config := routertesting.DefaultRouterConfig config.MaxPoolsPerRoute = tc.maxPoolsPerRoute config.MaxRoutes = tc.maxRoutes if tc.maxSplitRoutes > 0 { @@ -667,10 +666,10 @@ func (s *RouterTestSuite) TestGetOptimalQuote_Mainnet() { router, mainnetState := s.SetupMainnetRouter(config) // Mock router use case. - routerUsecase, _ := s.setupRouterAndPoolsUsecase(router, mainnetState.TickMap, mainnetState.TakerFeeMap, cache.New(), cache.NewNoOpRoutesOverwrite()) + mainnetUseCase := s.SetupRouterAndPoolsUsecase(router, mainnetState, cache.New(), cache.NewNoOpRoutesOverwrite()) // System under test - quote, err := routerUsecase.GetOptimalQuote(context.Background(), sdk.NewCoin(tc.tokenInDenom, tc.amountIn), tc.tokenOutDenom) + quote, err := mainnetUseCase.Router.GetOptimalQuote(context.Background(), sdk.NewCoin(tc.tokenInDenom, tc.amountIn), tc.tokenOutDenom) // We only validate that error does not occur without actually validating the quote. s.Require().NoError(err) @@ -689,7 +688,7 @@ func (s *RouterTestSuite) TestGetOptimalQuote_Mainnet() { // That is, with the given pool ID, we expect the quote to be routed through the route // that matches these pool IDs. Errors otherwise. func (s *RouterTestSuite) TestGetCustomQuote_GetCustomDirectQuote_Mainnet_UOSMOUION() { - config := defaultRouterConfig + config := routertesting.DefaultRouterConfig config.MaxPoolsPerRoute = 5 config.MaxRoutes = 10 @@ -738,38 +737,18 @@ func (s *RouterTestSuite) TestGetCustomQuote_GetCustomDirectQuote_Mainnet_UOSMOU // - setting the pool use case on the router (called during GetCandidateRoutes() method) // - converting candidate routes to routes with all the necessary data. // COTRACT: router is initialized with setupMainnetRouter(...) or setupDefaultMainnetRouter(...) -func (s *RouterTestSuite) constructRoutesFromMainnetPools(router *routerusecase.Router, tokenInDenom, tokenOutDenom string, tickMap map[uint64]sqsdomain.TickModel, takerFeeMap sqsdomain.TakerFeeMap) []route.RouteImpl { - _, poolsUsecase := s.setupRouterAndPoolsUsecase(router, tickMap, takerFeeMap, cache.New(), cache.NewNoOpRoutesOverwrite()) +func (s *RouterTestSuite) constructRoutesFromMainnetPools(router *routerusecase.Router, tokenInDenom, tokenOutDenom string, mainnetState routertesting.MockMainnetState) []route.RouteImpl { + mainnetUseCase := s.SetupRouterAndPoolsUsecase(router, mainnetState, cache.New(), cache.NewNoOpRoutesOverwrite()) candidateRoutes, err := router.GetCandidateRoutes(tokenInDenom, tokenOutDenom) s.Require().NoError(err) - routes, err := poolsUsecase.GetRoutesFromCandidates(context.Background(), candidateRoutes, takerFeeMap, tokenInDenom, tokenOutDenom) + routes, err := mainnetUseCase.Pools.GetRoutesFromCandidates(context.Background(), candidateRoutes, mainnetState.TakerFeeMap, tokenInDenom, tokenOutDenom) s.Require().NoError(err) return routes } -// Sets up and returns usecases for router and pools by mocking the mainnet data -// from json files. -func (s *RouterTestSuite) setupRouterAndPoolsUsecase(router *routerusecase.Router, tickMap map[uint64]sqsdomain.TickModel, takerFeeMap sqsdomain.TakerFeeMap, rankedRoutesCache *cache.Cache, routesOverwrite *cache.RoutesOverwrite) (mvc.RouterUsecase, mvc.PoolsUsecase) { - // Setup router repository mock - routerRepositoryMock := sqsdomainmocks.RedisRouterRepositoryMock{} - routerusecase.WithRouterRepository(router, &routerRepositoryMock) - - // Setup pools usecase mock. - poolsRepositoryMock := sqsdomainmocks.RedisPoolsRepositoryMock{ - Pools: router.GetSortedPools(), - TickModel: tickMap, - } - poolsUsecase := poolsusecase.NewPoolsUsecase(time.Hour, &poolsRepositoryMock, nil, &domain.PoolsConfig{}, "node-uri-placeholder") - routerusecase.WithPoolsUsecase(router, poolsUsecase) - - routerUsecase := usecase.NewRouterUsecase(time.Hour, &routerRepositoryMock, poolsUsecase, defaultRouterConfig, &log.NoOpLogger{}, rankedRoutesCache, routesOverwrite) - - return routerUsecase, poolsUsecase -} - // validates that the given quote has one route with one hop and the expected pool ID. func (s *RouterTestSuite) validateExpectedPoolIDOneRouteOneHopQuote(quote domain.Quote, expectedPoolID uint64) { routes := quote.GetRoute() diff --git a/router/usecase/router_test.go b/router/usecase/router_test.go index ada84851..15851d3c 100644 --- a/router/usecase/router_test.go +++ b/router/usecase/router_test.go @@ -5,7 +5,6 @@ import ( "github.com/stretchr/testify/suite" - "github.com/osmosis-labs/sqs/domain" "github.com/osmosis-labs/sqs/log" "github.com/osmosis-labs/sqs/router/usecase" routerusecase "github.com/osmosis-labs/sqs/router/usecase" @@ -20,17 +19,6 @@ type RouterTestSuite struct { routertesting.RouterTestHelper } -var defaultRouterConfig = domain.RouterConfig{ - PreferredPoolIDs: []uint64{}, - MaxRoutes: 4, - MaxPoolsPerRoute: 4, - MaxSplitRoutes: 4, - MaxSplitIterations: 10, - MinOSMOLiquidity: 20000, - RouteUpdateHeightInterval: 0, - RouteCacheEnabled: false, -} - func TestRouterTestSuite(t *testing.T) { suite.Run(t, new(RouterTestSuite)) } diff --git a/router/usecase/router_usecase_test.go b/router/usecase/router_usecase_test.go index e51f2d4b..726b615e 100644 --- a/router/usecase/router_usecase_test.go +++ b/router/usecase/router_usecase_test.go @@ -14,6 +14,7 @@ import ( "github.com/osmosis-labs/sqs/log" "github.com/osmosis-labs/sqs/router/usecase" "github.com/osmosis-labs/sqs/router/usecase/route" + "github.com/osmosis-labs/sqs/router/usecase/routertesting" "github.com/osmosis-labs/sqs/sqsdomain" sqsdomainmocks "github.com/osmosis-labs/sqs/sqsdomain/mocks" @@ -582,7 +583,7 @@ func (s *RouterTestSuite) TestGetOptimalQuote_Cache_Overwrites() { tc := tc s.Run(name, func() { // Setup router config - config := defaultRouterConfig + config := routertesting.DefaultRouterConfig // Note that we set one max route for ease of testing caching specifically. config.MaxRoutes = 1 @@ -601,10 +602,10 @@ func (s *RouterTestSuite) TestGetOptimalQuote_Cache_Overwrites() { } // Mock router use case. - routerUsecase, _ := s.setupRouterAndPoolsUsecase(router, mainnetState.TickMap, mainnetState.TakerFeeMap, rankedRouteCache, routesOverwrite) + mainnetUseCase := s.SetupRouterAndPoolsUsecase(router, mainnetState, rankedRouteCache, routesOverwrite) // System under test - quote, err := routerUsecase.GetOptimalQuote(context.Background(), sdk.NewCoin(defaultTokenInDenom, tc.amountIn), defaultTokenOutDenom) + quote, err := mainnetUseCase.Router.GetOptimalQuote(context.Background(), sdk.NewCoin(defaultTokenInDenom, tc.amountIn), defaultTokenOutDenom) // We only validate that error does not occur without actually validating the quote. s.Require().NoError(err) @@ -643,7 +644,7 @@ func (s *RouterTestSuite) TestOverwriteRoutes_LoadOverwriteRoutes() { s.Setup() // Setup router config - config := defaultRouterConfig + config := routertesting.DefaultRouterConfig // Note that we set one max route for ease of testing caching specifically. config.MaxRoutes = 1 @@ -651,8 +652,8 @@ func (s *RouterTestSuite) TestOverwriteRoutes_LoadOverwriteRoutes() { router, mainnetState := s.SetupMainnetRouter(config) // Mock router use case. - routerUsecase, _ := s.setupRouterAndPoolsUsecase(router, mainnetState.TickMap, mainnetState.TakerFeeMap, cache.New(), cache.NewRoutesOverwrite()) - routerUsecase = usecase.WithOverwriteRoutesPath(routerUsecase, tempPath) + mainnetUsecase := s.SetupRouterAndPoolsUsecase(router, mainnetState, cache.New(), cache.NewRoutesOverwrite()) + routerUsecase := usecase.WithOverwriteRoutesPath(mainnetUsecase.Router, tempPath) // Without overwrite this is the pool ID we expect given the amount in. s.validatePoolIDInRoute(routerUsecase, sdk.NewCoin(UOSMO, defaultAmountInCache), ATOM, poolID1400Concentrated) @@ -678,8 +679,8 @@ func (s *RouterTestSuite) TestOverwriteRoutes_LoadOverwriteRoutes() { s.validatePoolIDInRoute(routerUsecase, sdk.NewCoin(UOSMO, defaultAmountInCache), ATOM, poolID1135Concentrated) // Now, drop the original use case and create a new one - routerUsecase, _ = s.setupRouterAndPoolsUsecase(router, mainnetState.TickMap, mainnetState.TakerFeeMap, cache.New(), cache.NewRoutesOverwrite()) - routerUsecase = usecase.WithOverwriteRoutesPath(routerUsecase, tempPath) + mainnetUsecase = s.SetupRouterAndPoolsUsecase(router, mainnetState, cache.New(), cache.NewRoutesOverwrite()) + routerUsecase = usecase.WithOverwriteRoutesPath(mainnetUsecase.Router, tempPath) // // Without overwrite this is the pool ID we expect given the amount in. s.validatePoolIDInRoute(routerUsecase, sdk.NewCoin(UOSMO, defaultAmountInCache), ATOM, poolID1400Concentrated) diff --git a/router/usecase/routertesting/suite.go b/router/usecase/routertesting/suite.go index 2194dab8..0fc8e456 100644 --- a/router/usecase/routertesting/suite.go +++ b/router/usecase/routertesting/suite.go @@ -4,16 +4,22 @@ import ( "fmt" "os" "path/filepath" + "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/osmosis-labs/sqs/domain" + "github.com/osmosis-labs/sqs/domain/cache" "github.com/osmosis-labs/sqs/domain/mocks" + "github.com/osmosis-labs/sqs/domain/mvc" "github.com/osmosis-labs/sqs/log" - "github.com/osmosis-labs/sqs/router/usecase" + poolsusecase "github.com/osmosis-labs/sqs/pools/usecase" + routerusecase "github.com/osmosis-labs/sqs/router/usecase" "github.com/osmosis-labs/sqs/router/usecase/route" "github.com/osmosis-labs/sqs/router/usecase/routertesting/parsing" "github.com/osmosis-labs/sqs/sqsdomain" + sqsdomainmocks "github.com/osmosis-labs/sqs/sqsdomain/mocks" + tokensusecase "github.com/osmosis-labs/sqs/tokens/usecase" "github.com/osmosis-labs/osmosis/osmomath" "github.com/osmosis-labs/osmosis/v23/app/apptesting" @@ -31,6 +37,12 @@ type MockMainnetState struct { TokensMetadata map[string]domain.Token } +type MockMainnetUsecase struct { + Pools mvc.PoolsUsecase + Router mvc.RouterUsecase + Tokens mvc.TokensUsecase +} + const ( DefaultPoolID = uint64(1) @@ -106,6 +118,17 @@ var ( // The files below are set in init() projectRoot = "" absolutePathToStateFiles = "" + + DefaultRouterConfig = domain.RouterConfig{ + PreferredPoolIDs: []uint64{}, + MaxRoutes: 4, + MaxPoolsPerRoute: 4, + MaxSplitRoutes: 4, + MaxSplitIterations: 10, + MinOSMOLiquidity: 20000, + RouteUpdateHeightInterval: 0, + RouteCacheEnabled: false, + } ) func init() { @@ -200,7 +223,7 @@ func (s *RouterTestHelper) ValidateRoutePools(expectedPools []sqsdomain.Routable } } -func (s *RouterTestHelper) SetupDefaultMainnetRouter() (*usecase.Router, MockMainnetState) { +func (s *RouterTestHelper) SetupDefaultMainnetRouter() (*routerusecase.Router, MockMainnetState) { routerConfig := domain.RouterConfig{ PreferredPoolIDs: []uint64{}, MaxRoutes: 4, @@ -214,7 +237,7 @@ func (s *RouterTestHelper) SetupDefaultMainnetRouter() (*usecase.Router, MockMai return s.SetupMainnetRouter(routerConfig) } -func (s *RouterTestHelper) SetupMainnetRouter(config domain.RouterConfig) (*usecase.Router, MockMainnetState) { +func (s *RouterTestHelper) SetupMainnetRouter(config domain.RouterConfig) (*routerusecase.Router, MockMainnetState) { pools, tickMap, err := parsing.ReadPools(absolutePathToStateFiles + poolsFileName) s.Require().NoError(err) @@ -226,8 +249,8 @@ func (s *RouterTestHelper) SetupMainnetRouter(config domain.RouterConfig) (*usec logger, err := log.NewLogger(false, "", "info") s.Require().NoError(err) - router := usecase.NewRouter(config.PreferredPoolIDs, config.MaxPoolsPerRoute, config.MaxRoutes, config.MaxSplitRoutes, config.MaxSplitIterations, config.MinOSMOLiquidity, logger) - router = usecase.WithSortedPools(router, pools) + router := routerusecase.NewRouter(config.PreferredPoolIDs, config.MaxPoolsPerRoute, config.MaxRoutes, config.MaxSplitRoutes, config.MaxSplitIterations, config.MinOSMOLiquidity, logger) + router = routerusecase.WithSortedPools(router, pools) return router, MockMainnetState{ TickMap: tickMap, @@ -235,3 +258,29 @@ func (s *RouterTestHelper) SetupMainnetRouter(config domain.RouterConfig) (*usec TokensMetadata: tokensMetadata, } } + +// Sets up and returns usecases for router and pools by mocking the mainnet data +// from json files. +func (s *RouterTestHelper) SetupRouterAndPoolsUsecase(router *routerusecase.Router, mainnetState MockMainnetState, rankedRoutesCache *cache.Cache, routesOverwrite *cache.RoutesOverwrite) MockMainnetUsecase { + // Setup router repository mock + routerRepositoryMock := sqsdomainmocks.RedisRouterRepositoryMock{} + routerusecase.WithRouterRepository(router, &routerRepositoryMock) + + // Setup pools usecase mock. + poolsRepositoryMock := sqsdomainmocks.RedisPoolsRepositoryMock{ + Pools: router.GetSortedPools(), + TickModel: mainnetState.TickMap, + } + poolsUsecase := poolsusecase.NewPoolsUsecase(time.Hour, &poolsRepositoryMock, nil, &domain.PoolsConfig{}, "node-uri-placeholder") + routerusecase.WithPoolsUsecase(router, poolsUsecase) + + routerUsecase := routerusecase.NewRouterUsecase(time.Hour, &routerRepositoryMock, poolsUsecase, DefaultRouterConfig, &log.NoOpLogger{}, rankedRoutesCache, routesOverwrite) + + tokensUsecase := tokensusecase.NewTokensUsecase(time.Hour, mainnetState.TokensMetadata) + + return MockMainnetUsecase{ + Pools: poolsUsecase, + Router: routerUsecase, + Tokens: tokensUsecase, + } +} diff --git a/tokens/usecase/tokens_usecase.go b/tokens/usecase/tokens_usecase.go index 9612076b..c50dbd87 100644 --- a/tokens/usecase/tokens_usecase.go +++ b/tokens/usecase/tokens_usecase.go @@ -57,7 +57,7 @@ var ( ) // NewTokensUsecase will create a new tokens use case object -func NewTokensUsecase(timeout time.Duration, tokenMetadataByChainDenom map[string]domain.Token) (mvc.TokensUsecase, error) { +func NewTokensUsecase(timeout time.Duration, tokenMetadataByChainDenom map[string]domain.Token) mvc.TokensUsecase { // Create human denom to chain denom map humanToChainDenomMap := make(map[string]string, len(tokenMetadataByChainDenom)) uniquePrecisionMap := make(map[int]struct{}, 0) @@ -86,7 +86,7 @@ func NewTokensUsecase(timeout time.Duration, tokenMetadataByChainDenom map[strin metadataMapMu: sync.RWMutex{}, denomMapMu: sync.RWMutex{}, - }, nil + } } // GetChainDenom implements mvc.TokensUsecase. diff --git a/tokens/usecase/tokens_usecase_test.go b/tokens/usecase/tokens_usecase_test.go index 04dd5168..44da4190 100644 --- a/tokens/usecase/tokens_usecase_test.go +++ b/tokens/usecase/tokens_usecase_test.go @@ -5,8 +5,9 @@ import ( "github.com/stretchr/testify/suite" + "github.com/osmosis-labs/sqs/domain/cache" "github.com/osmosis-labs/sqs/router/usecase/routertesting" - "github.com/osmosis-labs/sqs/tokens/usecase" + tokensusecase "github.com/osmosis-labs/sqs/tokens/usecase" ) type TokensUseCaseTestSuite struct { @@ -42,7 +43,7 @@ func (s *TokensUseCaseTestSuite) TestParseExponents() { s.T().Skip("skip the test that does network call and is used for debugging") const () - tokensMap, err := usecase.GetTokensFromChainRegistry(mainnetAssetListFileURL) + tokensMap, err := tokensusecase.GetTokensFromChainRegistry(mainnetAssetListFileURL) s.Require().NoError(err) s.Require().NotEmpty(tokensMap) @@ -70,7 +71,7 @@ func (s *TokensUseCaseTestSuite) TestParseExponents_Testnet() { const ( testnetAssetListFileURL = "https://raw.githubusercontent.com/osmosis-labs/assetlists/main/osmo-test-5/osmo-test-5.assetlist.json" ) - tokensMap, err := usecase.GetTokensFromChainRegistry(testnetAssetListFileURL) + tokensMap, err := tokensusecase.GetTokensFromChainRegistry(testnetAssetListFileURL) s.Require().NoError(err) s.Require().NotEmpty(tokensMap) @@ -81,7 +82,13 @@ func (s *TokensUseCaseTestSuite) TestParseExponents_Testnet() { } func (s *TokensUseCaseTestSuite) TestGetPrices() { - _, _ = s.SetupDefaultMainnetRouter() + router, mainnetState := s.SetupDefaultMainnetRouter() + + // mock + + s.SetupRouterAndPoolsUsecase(router, mainnetState, cache.New(), cache.NewNoOpRoutesOverwrite()) + + // routerusecase.NewRouterUsecase(time.Second) // usecase.NewTokensUsecase(time.Second) }