Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TestGetOptimalQuoteInGivenOut: Tests #399

Closed
wants to merge 18 commits into from

Conversation

deividaspetraitis
Copy link
Collaborator

@deividaspetraitis deividaspetraitis commented Jul 24, 2024

This PR covers TestGetOptimalQuoteInGivenOut with tests.

As a side effect GetOptimalQuote method is broken is smaller parts to in order to be able to mock it. Such approach allows to tests smaller units indepently as well.

I have tested indroduced changes with Unit tests and integration tests:

============================================= short test summary info ==============================================
FAILED tests/test_candidate_routes.py::TestCandidateRoutes::test_all_valid_tokens[http://localhost:9092-ibc/0F9E9277
B61A78CB31014D541ACA5BF6AB06DFC4524C4C836490B131DAAECD78] - AssertionError: Error: no routes found for token in ibc/
0F9E9277B61A78CB31014D541ACA5BF6AB06DFC4524C4C836490B13...
FAILED tests/test_pools.py::TestPools::test_canonical_orderbook[http://localhost:9092] - AssertionError: Canonical o
rderbooks are None
FAILED tests/test_tokens_prices.py::TestTokensPrices::test_low_liq_token_prices[http://localhost:9092-ibc/56C276FC13
6E239449DCE664292DBEEF5795C4EF4B5B35DB98BD1C0948274867] - AssertionError: ibc/56C276FC136E239449DCE664292DBEEF5795C4
EF4B5B35DB98BD1C0948274867, SQS price is zero
==================================== 3 failed, 1490 passed, 8 skipped in 31.31s ====================================

This PR will be merged is DATA-276 branch.

Summary by CodeRabbit

  • New Features

    • Introduced new parameters for token transactions, enhancing API flexibility.
    • Added methods for managing token denominations in various pools.
    • Implemented new quote retrieval methods for improved routing functionality.
  • Bug Fixes

    • Refined error handling across the router, improving clarity and maintainability.
  • Documentation

    • Updated API documentation to reflect changes in query parameters and error handling.
  • Tests

    • Expanded test suite for the Router functionality, including new test cases for optimal quote retrieval.
  • Chores

    • Enhanced code readability and organization across multiple files.

Copy link
Contributor

coderabbitai bot commented Jul 24, 2024

Walkthrough

The changes entail modifications to various files within the routing functionality of a decentralized finance application. Key updates include enhancements to API documentation, introduction of new parameters for token transactions, restructuring of quote handling logic, and improvements in error management. Additionally, new test cases and utility functions have been added to bolster the testing framework. The modifications reflect a comprehensive update to the routing and quoting mechanisms, enhancing overall functionality and usability.

Changes

Files Change Summary
.gitignore Added patterns to exclude Vim-related backup and swap files.
docs/docs.go, docs/swagger.json, docs/swagger.yaml Removed required attributes from certain parameters and added new optional parameters related to token transactions in API documentation.
domain/mocks/pool_mock.go, domain/mocks/router_usecase_mock.go Added new methods and fields for managing token denominations in mock structs.
domain/mvc/router.go, domain/routable_pool.go Introduced new methods for managing token denominations in interfaces and structs.
domain/tokens.go Introduced a new enumeration type TokenSwapMethod with associated constants for token swapping methods.
router/delivery/http/http.go, router/delivery/http/router_handler.go Added functionality for unmarshalling HTTP requests and significant refactoring of routing logic and error handling.
router/types/errors.go, router/types/request.go Defined new error types and structured request handling for swap quote requests.
router/usecase/*.go Various changes including new methods for optimal quote retrieval, restructuring quote types, and enhancements to quote processing logic.
routertesting/*.go, routertesting/parsing/*.json Introduced utility functions for testing, created JSON response structures for quotes, and added functions for managing liquidity pools for testing scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant RouterHandler
    participant QuoteService
    participant PoolManager

    User->>RouterHandler: Request optimal quote
    RouterHandler->>QuoteService: GetOptimalQuoteInGivenOut()
    QuoteService->>PoolManager: Retrieve available pools
    PoolManager-->>QuoteService: Return pool data
    QuoteService-->>RouterHandler: Return quote details
    RouterHandler-->>User: Respond with quote
Loading

🐰 "In the meadow where bunnies play,
New routes and quotes are here to stay.
With tokens hopping, swift and bright,
We celebrate changes, a joyful sight!
So gather 'round, both near and far,
For every hop, we raise the bar!" 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@deividaspetraitis
Copy link
Collaborator Author

Linter is complaining about following which stems from original DATA-276 branch. I will resolve it there:

Error: `(*RouterTestHelper).newRoutablePool` - `cosmWasmConfig` always receives `domain.CosmWasmPoolRouterConfig{}` (`nil`) (unparam)

@deividaspetraitis deividaspetraitis changed the title Feat: swap Exact Amount Out, SQS Routing and API changes TestGetOptimalQuoteInGivenOut: Tests Jul 24, 2024
Copy link
Member

@p0mvn p0mvn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for separating this into a separate PR for ease of review.

What do you think about setting up our "mainnet state mock" test suite that creates a mock test environment from mainnet state rather than wiring a mock for GetOptimalQuote?

I know some time has been spent on the GetOptimalQuote mock but I'm not sure how I'm feeling about it due to the added wiring complexity to the core codebase while covering a few branches

Similar to this test. Note these lines that set up a mainnet environment.

In fact, it seems that your test already leverages a helper that sets up a router use case with the mainnet state. With the approach I suggest, we will not be able to cover this branch. However, that is acceptable because we will benefit from deeper functional testing while reducing complexity from not having to monkey-patch GetOptimalQuote

Let me know what you think

router/usecase/routertesting/quote.go Outdated Show resolved Hide resolved
@deividaspetraitis
Copy link
Collaborator Author

deividaspetraitis commented Jul 25, 2024

Thanks for taking your time to review and sharing thoughts!

While this PR touches core logic and changes wiring I believe it will support long term project testability strategy, goals and general code base maintainability:

  • Other methods and funcs benefits from this change by allowing us to test and mock many other methods independently, both public for example GetCachedRankedRoutes and private rankRoutesByDirectQuote.
  • Testing specific part(s) while ignoring other parts would allow us to write more focused and indpedendent tests with no side effects
  • Tests execution will be faster, since each test tests only specific code piece
  • Decoupling allows wore isolated changes

For example, for TestGetOptimalQuote_Mainnet it makes sense as it is done currently, for TestGetOptimalQuoteInGivenOut method GetOptimalQuote is a depedency that is already cover with tests that's why I think points above makes more sense in this case.

Please let me know if you still think we should go for TestGetOptimalQuote_Mainnet approach and I will implement it! 🙏

Cover `TestGetOptimalQuoteInGivenOut` with tests: requested changes
@p0mvn
Copy link
Member

p0mvn commented Jul 26, 2024

@deividaspetraitis let's brainstorm this change sync sometime next week and align on direction.

I think TestGetOptimalQuote_Mainnet would still be beneficial since it would be a functional test relying on mainnet state, asserting invariants more comprehensively.

I propose kicking off a separate PR with the mainnet state test.

Let me know what you think

@deividaspetraitis
Copy link
Collaborator Author

@deividaspetraitis let's brainstorm this change sync sometime next week and align on direction.

I think TestGetOptimalQuote_Mainnet would still be beneficial since it would be a functional test relying on mainnet state, asserting invariants more comprehensively.

I propose kicking off a separate PR with the mainnet state test.

Let me know what you think

I have created separate PR with the mainnet state test #403 🚀

@deividaspetraitis deividaspetraitis self-assigned this Jul 29, 2024
Base automatically changed from DATA-276 to v25.x July 31, 2024 09:06
@PaddyMc PaddyMc added the A:backport/v26.x backport patches to v26.x branch label Aug 26, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Outside diff range, codebase verification and nitpick comments (1)
router/usecase/routertesting/file.go (1)

5-10: Enhance error handling with additional context.

While the function correctly handles errors, providing additional context in the error message can be helpful for debugging. Consider including the file path in the error message.

 func (s *RouterTestHelper) MustReadFile(path string) string {
   b, err := os.ReadFile(path)
-  s.Require().NoError(err)
+  s.Require().NoError(err, "failed to read file: %s", path)
   return string(b)
 }
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 5c0b4c4 and 1f24263.

Files selected for processing (39)
  • .gitignore (1 hunks)
  • docs/docs.go (1 hunks)
  • docs/swagger.json (1 hunks)
  • docs/swagger.yaml (1 hunks)
  • domain/mocks/pool_mock.go (2 hunks)
  • domain/mocks/router_usecase_mock.go (2 hunks)
  • domain/mvc/router.go (1 hunks)
  • domain/routable_pool.go (1 hunks)
  • domain/router.go (2 hunks)
  • domain/tokens.go (1 hunks)
  • pools/usecase/export_test.go (1 hunks)
  • router/delivery/http/http.go (1 hunks)
  • router/delivery/http/router_handler.go (10 hunks)
  • router/delivery/http/router_handler_test.go (4 hunks)
  • router/types/errors.go (1 hunks)
  • router/types/request.go (1 hunks)
  • router/types/request_test.go (1 hunks)
  • router/usecase/dynamic_splits.go (2 hunks)
  • router/usecase/export_test.go (3 hunks)
  • router/usecase/optimized_routes.go (1 hunks)
  • router/usecase/optimized_routes_test.go (1 hunks)
  • router/usecase/pools/routable_balancer_pool.go (3 hunks)
  • router/usecase/pools/routable_concentrated_pool.go (3 hunks)
  • router/usecase/pools/routable_cw_alloy_transmuter_pool.go (3 hunks)
  • router/usecase/pools/routable_cw_orderbook_pool.go (3 hunks)
  • router/usecase/pools/routable_cw_pool.go (2 hunks)
  • router/usecase/pools/routable_cw_transmuter_pool.go (3 hunks)
  • router/usecase/pools/routable_result_pool.go (5 hunks)
  • router/usecase/pools/routable_stableswap_pool.go (2 hunks)
  • router/usecase/quote_in_given_out.go (5 hunks)
  • router/usecase/quote_out_given_in.go (1 hunks)
  • router/usecase/quote_test.go (2 hunks)
  • router/usecase/router_usecase.go (21 hunks)
  • router/usecase/router_usecase_test.go (4 hunks)
  • router/usecase/routertesting/file.go (1 hunks)
  • router/usecase/routertesting/parsing/quote_amount_in_response.json (1 hunks)
  • router/usecase/routertesting/parsing/quote_amount_out_response.json (1 hunks)
  • router/usecase/routertesting/pool.go (1 hunks)
  • router/usecase/routertesting/quote.go (1 hunks)
Files skipped from review due to trivial changes (3)
  • .gitignore
  • pools/usecase/export_test.go
  • router/usecase/optimized_routes_test.go
Additional context used
GitHub Check: Run linter
router/usecase/routertesting/quote.go

[failure] 44-44:
(*RouterTestHelper).newRoutablePool - cosmWasmConfig always receives domain.CosmWasmPoolRouterConfig{} (nil) (unparam)

Additional comments not posted (110)
router/delivery/http/http.go (2)

7-10: LGTM!

The interface is correctly defined and follows Go's interface design principles.

The code changes are approved.


12-15: LGTM!

The function is correctly implemented and leverages the interface method appropriately.

The code changes are approved.

router/types/errors.go (9)

7-7: LGTM!

The error message is clear and descriptive.

The code changes are approved.


8-8: LGTM!

The error message is clear and descriptive.

The code changes are approved.


9-9: LGTM!

The error message is clear and descriptive.

The code changes are approved.


10-10: LGTM!

The error message is clear and descriptive.

The code changes are approved.


11-11: LGTM!

The error message is clear and descriptive.

The code changes are approved.


12-12: LGTM!

The error message is clear and descriptive.

The code changes are approved.


13-13: LGTM!

The error message is clear and descriptive.

The code changes are approved.


14-14: LGTM!

The error message is clear and descriptive.

The code changes are approved.


15-15: LGTM!

The error message is clear and descriptive.

The code changes are approved.

router/usecase/routertesting/parsing/quote_amount_out_response.json (1)

1-50: LGTM!

The JSON structure is well-formed and consistent with the expected format for a quote amount out response.

The code changes are approved.

router/usecase/routertesting/parsing/quote_amount_in_response.json (1)

1-50: LGTM!

The JSON structure is well-formed and consistent with the expected format for a quote amount in response.

The code changes are approved.

domain/routable_pool.go (3)

54-54: LGTM!

The method SetTokenOutDenom(denom string) enhances the flexibility of the RoutablePool interface by allowing the setting of the token out denomination.

The code changes are approved.


56-56: LGTM!

The method GetTokenInDenom() enhances the functionality of the RoutablePool interface by allowing the retrieval of the token in denomination.

The code changes are approved.


57-57: LGTM!

The method SetTokenInDenom(denom string) enhances the flexibility of the RoutablePool interface by allowing the setting of the token in denomination.

The code changes are approved.

domain/tokens.go (1)

56-69: LGTM!

The new enumeration type TokenSwapMethod and its constants are well-defined and enhance the functionality related to token management.

The code changes are approved.

router/usecase/quote_out_given_in.go (1)

18-28: LGTM!

The quoteExactAmountOut struct is well-defined and includes necessary fields for exact out quotes.

The code changes are approved.

router/types/request.go (2)

61-78: LGTM!

The function is correctly implemented and handles the logic well.

The code changes are approved.


80-101: LGTM!

The function is correctly implemented and handles the validation well.

The code changes are approved.

router/usecase/export_test.go (4)

18-18: LGTM!

The alias change reflects a shift in the underlying implementation or intended use of the quote functionality.

The code changes are approved.


32-33: LGTM!

The function implementation has been updated to enhance the routing logic by leveraging additional configuration and caching mechanisms.

The code changes are approved.


35-40: LGTM!

The addition enhances the testability of the routerUseCaseImpl by providing a mechanism to control the behavior of quote retrieval during tests.

The code changes are approved.


76-76: LGTM!

The function implementation has been updated to improve the efficiency or accuracy of the ranking process by utilizing the poolsUsecase directly.

The code changes are approved.

router/usecase/pools/routable_balancer_pool.go (3)

23-24: LGTM!

The addition of new fields enhances the struct's capability to manage multiple token denominations.

The code changes are approved.


44-46: LGTM!

The function is correctly implemented and provides the necessary functionality.

The code changes are approved.


66-68: LGTM!

The function is correctly implemented and provides the necessary functionality.

The code changes are approved.

router/usecase/pools/routable_stableswap_pool.go (2)

23-24: LGTM!

The addition of TokenInDenom and the update to TokenOutDenom with the omitempty JSON tag are appropriate and enhance the flexibility of the struct.

The code changes are approved.


60-68: LGTM!

The addition of GetTokenInDenom and SetTokenInDenom methods is consistent with the existing method structure and enhances the functionality of the struct.

The code changes are approved.

router/usecase/quote_in_given_out.go (11)

26-28: LGTM!

The replacement of quoteImpl with QuoteExactAmountOut and QuoteExactAmountIn enhances clarity by explicitly distinguishing between the two quote types.

The code changes are approved.


30-34: LGTM!

The NewQuoteExactAmountOut function correctly initializes and returns a quoteExactAmountOut instance.

The code changes are approved.


Line range hint 36-43: LGTM!

The quoteExactAmountIn struct is well-defined and includes fields necessary for handling quotes with exact amounts in.

The code changes are approved.


Line range hint 54-110: LGTM!

The PrepareResult method is well-implemented, preparing the quote for output, stripping unnecessary fields, and computing the effective spread factor.

The code changes are approved.


112-113: LGTM!

The GetAmountIn method correctly returns the AmountIn field.

The code changes are approved.


117-118: LGTM!

The GetAmountOut method correctly returns the AmountOut field.

The code changes are approved.


122-123: LGTM!

The GetRoute method correctly returns the Route field.

The code changes are approved.


127-128: LGTM!

The GetEffectiveFee method correctly returns the EffectiveFee field.

The code changes are approved.


Line range hint 132-142: LGTM!

The String method provides a useful string representation of the quote for debugging and logging.

The code changes are approved.


145-146: LGTM!

The GetPriceImpact method correctly returns the PriceImpact field.

The code changes are approved.


150-152: LGTM!

The GetInBaseOutQuoteSpotPrice method correctly returns the InBaseOutQuoteSpotPrice field.

The code changes are approved.

router/usecase/pools/routable_cw_transmuter_pool.go (2)

23-24: LGTM!

The addition of TokenInDenom and the update to TokenOutDenom with the omitempty JSON tag are appropriate and enhance the flexibility of the struct.

The code changes are approved.


81-84: LGTM!

The addition of GetTokenInDenom and SetTokenInDenom methods is consistent with the existing method structure and enhances the functionality of the struct.

The code changes are approved.

Also applies to: 117-120

router/usecase/routertesting/quote.go (4)

16-21: LGTM!

The variables are correctly initialized with appropriate values.

The code changes are approved.


23-42: LGTM!

The variables are correctly initialized with appropriate values.

The code changes are approved.


56-108: LGTM!

The function is correctly implemented and uses helper functions and variables appropriately.

The code changes are approved.


110-158: LGTM!

The function is correctly implemented and uses helper functions and variables appropriately.

The code changes are approved.

domain/mvc/router.go (1)

62-64: LGTM!

The method is correctly added to the interface and enhances the functionality.

The code changes are approved.

router/usecase/pools/routable_result_pool.go (6)

32-32: LGTM!

The update to include the omitempty JSON tag is appropriate and allows the field to be omitted from JSON output if it is empty.

The code changes are approved.


33-33: LGTM!

The addition of the field with the omitempty JSON tag is appropriate and allows the field to be serialized conditionally.

The code changes are approved.


43-46: LGTM!

The method is correctly implemented and enhances the mutability of the struct.

The code changes are approved.


48-51: LGTM!

The method is correctly implemented and enhances the mutability of the struct.

The code changes are approved.


65-75: LGTM!

The method is correctly implemented and expands the instantiation options for users of the struct.

The code changes are approved.


136-139: LGTM!

The method is correctly implemented and ensures that the new field is accessible through the public interface of the struct.

The code changes are approved.

domain/mocks/router_usecase_mock.go (1)

68-73: LGTM!

The function is correctly implemented with a panic for unimplemented cases.

The code changes are approved.

router/usecase/optimized_routes.go (1)

74-74: Verify the correctness of the new type.

The finalQuote variable type has been changed from quoteImpl to quoteExactAmountIn. Ensure that the new type is correct and compatible with the rest of the code.

Run the following script to verify the usage of quoteExactAmountIn:

Verification successful

The new type quoteExactAmountIn is correct and well-integrated.

The quoteExactAmountIn type is extensively used across the codebase and is validated through unit tests. It implements the necessary methods and interfaces, indicating that the change from quoteImpl to quoteExactAmountIn is correct and compatible with the rest of the code.

  • Verified in router/usecase/router_usecase.go
  • Verified in router/usecase/quote_in_given_out.go
  • Verified in router/usecase/dynamic_splits.go
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of `quoteExactAmountIn`.

# Test: Search for the usage of `quoteExactAmountIn`. Expect: Correct usage and compatibility.
rg --type go -A 5 $'quoteExactAmountIn'

Length of output: 9753

router/usecase/pools/routable_cw_alloy_transmuter_pool.go (2)

87-90: LGTM!

The function is correctly implemented and follows the pattern of other getter functions in the struct.

The code changes are approved.


109-112: LGTM!

The function is correctly implemented and follows the pattern of other setter functions in the struct.

The code changes are approved.

domain/mocks/pool_mock.go (3)

27-27: LGTM!

The addition of the TokenInDenom field is consistent with the existing structure.

The code changes are approved.


130-133: LGTM!

The GetTokenInDenom method correctly retrieves the TokenInDenom value.

The code changes are approved.


135-138: LGTM!

The SetTokenInDenom method correctly sets the TokenInDenom value.

The code changes are approved.

router/usecase/dynamic_splits.go (2)

Line range hint 40-47: LGTM!

The change in the quote variable type from quoteImpl to quoteExactAmountIn is consistent with the new logic.

The code changes are approved.


Line range hint 173-179: LGTM!

The change in the quote variable type from quoteImpl to quoteExactAmountIn is consistent with the new logic.

The code changes are approved.

router/usecase/pools/routable_cw_pool.go (5)

33-33: LGTM!

The addition of the omitempty JSON tag to the TokenOutDenom field enhances the flexibility of the struct.

The code changes are approved.


34-34: LGTM!

The addition of the TokenInDenom field with the omitempty JSON tag is consistent with the existing structure.

The code changes are approved.


118-121: LGTM!

The SetTokenInDenom method correctly sets the TokenInDenom value.

The code changes are approved.


123-126: LGTM!

The SetTokenOutDenom method correctly sets the TokenOutDenom value.

The code changes are approved.


128-131: LGTM!

The GetTokenInDenom method correctly retrieves the TokenInDenom value.

The code changes are approved.

router/delivery/http/router_handler_test.go (1)

107-109: LGTM!

The error handling modifications enhance the clarity and specificity of error reporting.

The code changes are approved.

Also applies to: 119-121, 131-133

domain/router.go (2)

25-27: LGTM!

The new method CalculateTokenOutByTokenIn enhances the functionality of the Route interface.

The code changes are approved.

Also applies to: 29-29


59-59: LGTM!

The new method GetInBaseOutQuoteSpotPrice enhances the functionality of the Quote interface.

The code changes are approved.

router/types/request_test.go (3)

18-126: LGTM!

The test function is well-structured and covers various scenarios.

The code changes are approved.


129-189: LGTM!

The test function is well-structured and covers various scenarios.

The code changes are approved.


191-260: LGTM!

The test function is well-structured and covers various scenarios.

The code changes are approved.

router/usecase/pools/routable_cw_orderbook_pool.go (4)

27-27: LGTM!

The addition of the TokenInDenom field with the omitempty JSON tag is appropriate for flexible serialization.

The code changes are approved.


28-28: LGTM!

The addition of the omitempty JSON tag to the TokenOutDenom field is appropriate for flexible serialization.

The code changes are approved.


152-154: LGTM!

The function correctly retrieves the TokenInDenom field.

The code changes are approved.


174-176: LGTM!

The function correctly sets the TokenInDenom field.

The code changes are approved.

router/usecase/pools/routable_concentrated_pool.go (4)

29-29: LGTM!

The addition of the TokenInDenom field with the omitempty JSON tag is appropriate for flexible serialization.

The code changes are approved.


30-30: LGTM!

The addition of the omitempty JSON tag to the TokenOutDenom field is appropriate for flexible serialization.

The code changes are approved.


202-204: LGTM!

The function correctly retrieves the TokenInDenom field.

The code changes are approved.


220-222: LGTM!

The function correctly sets the TokenInDenom field.

The code changes are approved.

router/usecase/quote_test.go (1)

Line range hint 5-200: LGTM!

The refactoring of the TestPrepareResult function to use helper methods for pool preparation and the table-driven format improves readability and maintainability.

The code changes are approved.

docs/swagger.yaml (3)

167-167: LGTM!

Making tokenIn optional adds flexibility to the API.

The code changes are approved.


168-171: LGTM!

Adding tokenInDenom enhances the API's ability to handle input tokens more precisely.

The code changes are approved.


172-174: LGTM!

Adding tokenOut enhances the API's ability to handle output tokens more precisely.

The code changes are approved.

router/delivery/http/router_handler.go (8)

19-19: LGTM!

Importing the types package is necessary for the new error handling mechanism.

The code changes are approved.


Line range hint 61-131: LGTM!

The refactoring of GetOptimalQuote to use a structured request object and new error handling improves maintainability and clarity.

The code changes are approved.


84-86: LGTM!

The removal of getValidRoutingParameters is consistent with the shift towards a more encapsulated and request-driven approach.

The code changes are approved.


316-316: LGTM!

Using the new error types from the types package aligns with the new error handling mechanism.

The code changes are approved.


338-338: LGTM!

Using the new error types from the types package aligns with the new error handling mechanism.

The code changes are approved.


353-353: LGTM!

Using the new error types from the types package aligns with the new error handling mechanism.

The code changes are approved.


401-401: LGTM!

Using the new error types from the types package aligns with the new error handling mechanism.

The code changes are approved.


401-401: LGTM!

Using the new error types from the types package aligns with the new error handling mechanism.

The code changes are approved.

docs/swagger.json (4)

150-150: LGTM!

Making tokenIn optional adds flexibility to the API.

The code changes are approved.


156-157: LGTM!

Making tokenOutDenom optional adds flexibility to the API.

The code changes are approved.


158-163: LGTM!

Adding tokenInDenom enhances the API's ability to handle input tokens more precisely.

The code changes are approved.


164-168: LGTM!

Adding tokenOut enhances the API's ability to handle output tokens more precisely.

The code changes are approved.

docs/docs.go (1)

159-177: LGTM!

The changes enhance the flexibility of the API by allowing queries to be executed without specifying the tokenIn and tokenOutDenom parameters. The addition of new parameters provides additional context for the tokens involved in the transaction.

The code changes are approved.

router/usecase/router_usecase.go (10)

110-128: LGTM!

The introduction of the GetOptimalQuoteFunc type alias and the getOptimalQuoteFunc variable enhances the flexibility and testability of the code.

The code changes are approved.


142-155: LGTM!

The refactoring of the GetOptimalQuote method enhances the clarity of the code and separates the concerns of quote retrieval from the router use case implementation.

The code changes are approved.


Line range hint 157-272: LGTM!

The introduction of the getOptimalQuote function centralizes the logic for obtaining optimal quotes, improving maintainability and readability.

The code changes are approved.


281-297: LGTM!

The new GetOptimalQuoteInGivenOut method wraps the existing GetOptimalQuote functionality, ensuring that the underlying logic remains consistent while offering a new interface for users.

The code changes are approved.


412-428: LGTM!

The changes to the rankRoutesByDirectQuote function streamline its operation and reduce dependencies on the routerUseCaseImpl instance.

The code changes are approved.


Line range hint 443-506: LGTM!

The changes to the computeAndRankRoutesByDirectQuote function streamline its operation and reduce dependencies on the routerUseCaseImpl instance.

The code changes are approved.


749-795: LGTM!

The changes to the handleCandidateRoutes function streamline its operation and reduce dependencies on the routerUseCaseImpl instance.

The code changes are approved.


Line range hint 668-686: LGTM!

The changes to the getCachedCandidateRoutes function streamline its operation and reduce dependencies on the routerUseCaseImpl instance.

The code changes are approved.


Line range hint 712-724: LGTM!

The changes to the getCachedRankedRoutes function streamline its operation and reduce dependencies on the routerUseCaseImpl instance.

The code changes are approved.


930-936: LGTM!

The new convertMinTokensPoolLiquidityCapToFilter function provides a utility for converting the minimum tokens pool liquidity cap to a filter value, improving the flexibility of the code.

The code changes are approved.

router/usecase/router_usecase_test.go (2)

627-644: LGTM!

The function is correctly implemented and facilitates flexible testing.

The code changes are approved.


646-717: LGTM!

The test method is well-structured and covers various scenarios effectively.

The code changes are approved.

Comment on lines +55 to +73
func (s *RouterTestHelper) PoolThree() (uint64, poolmanagertypes.PoolI) {
poolIDThree := s.PrepareCustomBalancerPool([]balancer.PoolAsset{
{
Token: sdk.NewCoin(ETH, DefaultAmount),
Weight: sdk.NewInt(100),
},
{
Token: sdk.NewCoin(USDC, DefaultAmount.MulRaw(4)),
Weight: sdk.NewInt(100),
},
}, balancer.PoolParams{
SwapFee: sdk.NewDecWithPrec(5, 3),
ExitFee: osmomath.ZeroDec(),
})

poolThree, err := s.App.PoolManagerKeeper.GetPool(s.Ctx, poolIDThree)
s.Require().NoError(err)

return poolIDThree, poolThree
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error handling for pool creation.

The function lacks error handling for the pool creation process. Consider adding error handling to ensure robustness.

 poolIDThree := s.PrepareCustomBalancerPool([]balancer.PoolAsset{
   // existing code
 })
+if poolIDThree == 0 {
+  return 0, nil, errors.New("failed to create pool")
+}

Committable suggestion was skipped due to low confidence.

Comment on lines +11 to +29
func (s *RouterTestHelper) PoolOne() (uint64, poolmanagertypes.PoolI) {
poolIDOne := s.PrepareCustomBalancerPool([]balancer.PoolAsset{
{
Token: sdk.NewCoin(USDT, DefaultAmount.MulRaw(5)),
Weight: sdk.NewInt(100),
},
{
Token: sdk.NewCoin(ETH, DefaultAmount),
Weight: sdk.NewInt(100),
},
}, balancer.PoolParams{
SwapFee: sdk.NewDecWithPrec(1, 2),
ExitFee: osmomath.ZeroDec(),
})

poolOne, err := s.App.PoolManagerKeeper.GetPool(s.Ctx, poolIDOne)
s.Require().NoError(err)

return poolIDOne, poolOne
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error handling for pool creation.

The function lacks error handling for the pool creation process. Consider adding error handling to ensure robustness.

 poolIDOne := s.PrepareCustomBalancerPool([]balancer.PoolAsset{
   // existing code
 })
+if poolIDOne == 0 {
+  return 0, nil, errors.New("failed to create pool")
+}

Committable suggestion was skipped due to low confidence.

Comment on lines +33 to +51
func (s *RouterTestHelper) PoolTwo() (uint64, poolmanagertypes.PoolI) {
poolIDTwo := s.PrepareCustomBalancerPool([]balancer.PoolAsset{
{
Token: sdk.NewCoin(USDC, DefaultAmount),
Weight: sdk.NewInt(100),
},
{
Token: sdk.NewCoin(USDT, DefaultAmount),
Weight: sdk.NewInt(100),
},
}, balancer.PoolParams{
SwapFee: sdk.NewDecWithPrec(3, 2),
ExitFee: osmomath.ZeroDec(),
})

poolTwo, err := s.App.PoolManagerKeeper.GetPool(s.Ctx, poolIDTwo)
s.Require().NoError(err)

return poolIDTwo, poolTwo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error handling for pool creation.

The function lacks error handling for the pool creation process. Consider adding error handling to ensure robustness.

 poolIDTwo := s.PrepareCustomBalancerPool([]balancer.PoolAsset{
   // existing code
 })
+if poolIDTwo == 0 {
+  return 0, nil, errors.New("failed to create pool")
+}

Committable suggestion was skipped due to low confidence.

Comment on lines +30 to +70
// PrepareResult implements domain.Quote.
// PrepareResult mutates the quote to prepare
// it with the data formatted for output to the client.
// Specifically:
// It strips away unnecessary fields from each pool in the route.
// Computes an effective spread factor from all routes.
//
// Returns the updated route and the effective spread factor.
func (q *quoteExactAmountOut) PrepareResult(ctx context.Context, scalingFactor osmomath.Dec) ([]domain.SplitRoute, osmomath.Dec, error) {
// Prepare exact out in the quote for inputs inversion
if _, _, err := q.quoteExactAmountIn.PrepareResult(ctx, scalingFactor); err != nil {
return nil, osmomath.Dec{}, err
}

// Assign the inverted values to the quote
q.AmountOut = q.quoteExactAmountIn.AmountIn
q.AmountIn = q.quoteExactAmountIn.AmountOut
q.Route = q.quoteExactAmountIn.Route
q.EffectiveFee = q.quoteExactAmountIn.EffectiveFee
q.PriceImpact = q.quoteExactAmountIn.PriceImpact
q.InBaseOutQuoteSpotPrice = q.quoteExactAmountIn.InBaseOutQuoteSpotPrice

for i, route := range q.Route {
route, ok := route.(*RouteWithOutAmount)
if !ok {
return nil, osmomath.Dec{}, types.ErrInvalidRouteType
}

// invert the in and out amounts
route.InAmount, route.OutAmount = route.OutAmount, route.InAmount

q.Route[i] = route

// invert the in and out amounts for each pool
for _, p := range route.GetPools() {
p.SetTokenInDenom(p.GetTokenOutDenom())
p.SetTokenOutDenom("")
}
}

return q.Route, q.EffectiveFee, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error handling for route type conversion.

The method lacks error handling for the route type conversion. Consider adding error handling to ensure robustness.

 for i, route := range q.Route {
   route, ok := route.(*RouteWithOutAmount)
   if !ok {
-    return nil, osmomath.Dec{}, types.ErrInvalidRouteType
+    return nil, osmomath.Dec{}, fmt.Errorf("invalid route type: %T", route)
   }
   // existing code
 }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// PrepareResult implements domain.Quote.
// PrepareResult mutates the quote to prepare
// it with the data formatted for output to the client.
// Specifically:
// It strips away unnecessary fields from each pool in the route.
// Computes an effective spread factor from all routes.
//
// Returns the updated route and the effective spread factor.
func (q *quoteExactAmountOut) PrepareResult(ctx context.Context, scalingFactor osmomath.Dec) ([]domain.SplitRoute, osmomath.Dec, error) {
// Prepare exact out in the quote for inputs inversion
if _, _, err := q.quoteExactAmountIn.PrepareResult(ctx, scalingFactor); err != nil {
return nil, osmomath.Dec{}, err
}
// Assign the inverted values to the quote
q.AmountOut = q.quoteExactAmountIn.AmountIn
q.AmountIn = q.quoteExactAmountIn.AmountOut
q.Route = q.quoteExactAmountIn.Route
q.EffectiveFee = q.quoteExactAmountIn.EffectiveFee
q.PriceImpact = q.quoteExactAmountIn.PriceImpact
q.InBaseOutQuoteSpotPrice = q.quoteExactAmountIn.InBaseOutQuoteSpotPrice
for i, route := range q.Route {
route, ok := route.(*RouteWithOutAmount)
if !ok {
return nil, osmomath.Dec{}, types.ErrInvalidRouteType
}
// invert the in and out amounts
route.InAmount, route.OutAmount = route.OutAmount, route.InAmount
q.Route[i] = route
// invert the in and out amounts for each pool
for _, p := range route.GetPools() {
p.SetTokenInDenom(p.GetTokenOutDenom())
p.SetTokenOutDenom("")
}
}
return q.Route, q.EffectiveFee, nil
for i, route := range q.Route {
route, ok := route.(*RouteWithOutAmount)
if !ok {
return nil, osmomath.Dec{}, fmt.Errorf("invalid route type: %T", route)
}
// invert the in and out amounts
route.InAmount, route.OutAmount = route.OutAmount, route.InAmount
q.Route[i] = route
// invert the in and out amounts for each pool
for _, p := range route.GetPools() {
p.SetTokenInDenom(p.GetTokenOutDenom())
p.SetTokenOutDenom("")
}
}
return q.Route, q.EffectiveFee, nil

Comment on lines +25 to +57
func (r *GetQuoteRequest) UnmarshalHTTPRequest(c echo.Context) error {
var err error
r.SingleRoute, err = domain.ParseBooleanQueryParam(c, "singleRoute")
if err != nil {
return c.JSON(domain.GetStatusCode(err), domain.ResponseError{Message: err.Error()})
}

r.ApplyExponents, err = domain.ParseBooleanQueryParam(c, "applyExponents")
if err != nil {
return c.JSON(domain.GetStatusCode(err), domain.ResponseError{Message: err.Error()})
}

if tokenIn := c.QueryParam("tokenIn"); tokenIn != "" {
tokenInCoin, err := sdk.ParseCoinNormalized(tokenIn)
if err != nil {
return ErrTokenInNotValid
}
r.TokenIn = &tokenInCoin
}

if tokenOut := c.QueryParam("tokenOut"); tokenOut != "" {
tokenOutCoin, err := sdk.ParseCoinNormalized(tokenOut)
if err != nil {
return ErrTokenOutNotValid
}
r.TokenOut = &tokenOutCoin
}

r.TokenInDenom = c.QueryParam("tokenInDenom")
r.TokenOutDenom = c.QueryParam("tokenOutDenom")

return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure consistent error handling.

The function currently has inconsistent error handling: some errors return a JSON response, others return an error directly. Consider standardizing the error handling approach.

Apply this diff to standardize the error handling:

 func (r *GetQuoteRequest) UnmarshalHTTPRequest(c echo.Context) error {
 	var err error
 	r.SingleRoute, err = domain.ParseBooleanQueryParam(c, "singleRoute")
 	if err != nil {
-		return c.JSON(domain.GetStatusCode(err), domain.ResponseError{Message: err.Error()})
+		return err
 	}

 	r.ApplyExponents, err = domain.ParseBooleanQueryParam(c, "applyExponents")
 	if err != nil {
-		return c.JSON(domain.GetStatusCode(err), domain.ResponseError{Message: err.Error()})
+		return err
 	}

 	if tokenIn := c.QueryParam("tokenIn"); tokenIn != "" {
 		tokenInCoin, err := sdk.ParseCoinNormalized(tokenIn)
 		if err != nil {
-			return ErrTokenInNotValid
+			return fmt.Errorf("invalid tokenIn: %w", err)
 		}
 		r.TokenIn = &tokenInCoin
 	}

 	if tokenOut := c.QueryParam("tokenOut"); tokenOut != "" {
 		tokenOutCoin, err := sdk.ParseCoinNormalized(tokenOut)
 		if err != nil {
-			return ErrTokenOutNotValid
+			return fmt.Errorf("invalid tokenOut: %w", err)
 		}
 		r.TokenOut = &tokenOutCoin
 	}

 	r.TokenInDenom = c.QueryParam("tokenInDenom")
 	r.TokenOutDenom = c.QueryParam("tokenOutDenom")

 	return nil
 }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (r *GetQuoteRequest) UnmarshalHTTPRequest(c echo.Context) error {
var err error
r.SingleRoute, err = domain.ParseBooleanQueryParam(c, "singleRoute")
if err != nil {
return c.JSON(domain.GetStatusCode(err), domain.ResponseError{Message: err.Error()})
}
r.ApplyExponents, err = domain.ParseBooleanQueryParam(c, "applyExponents")
if err != nil {
return c.JSON(domain.GetStatusCode(err), domain.ResponseError{Message: err.Error()})
}
if tokenIn := c.QueryParam("tokenIn"); tokenIn != "" {
tokenInCoin, err := sdk.ParseCoinNormalized(tokenIn)
if err != nil {
return ErrTokenInNotValid
}
r.TokenIn = &tokenInCoin
}
if tokenOut := c.QueryParam("tokenOut"); tokenOut != "" {
tokenOutCoin, err := sdk.ParseCoinNormalized(tokenOut)
if err != nil {
return ErrTokenOutNotValid
}
r.TokenOut = &tokenOutCoin
}
r.TokenInDenom = c.QueryParam("tokenInDenom")
r.TokenOutDenom = c.QueryParam("tokenOutDenom")
return nil
}
func (r *GetQuoteRequest) UnmarshalHTTPRequest(c echo.Context) error {
var err error
r.SingleRoute, err = domain.ParseBooleanQueryParam(c, "singleRoute")
if err != nil {
return err
}
r.ApplyExponents, err = domain.ParseBooleanQueryParam(c, "applyExponents")
if err != nil {
return err
}
if tokenIn := c.QueryParam("tokenIn"); tokenIn != "" {
tokenInCoin, err := sdk.ParseCoinNormalized(tokenIn)
if err != nil {
return fmt.Errorf("invalid tokenIn: %w", err)
}
r.TokenIn = &tokenInCoin
}
if tokenOut := c.QueryParam("tokenOut"); tokenOut != "" {
tokenOutCoin, err := sdk.ParseCoinNormalized(tokenOut)
if err != nil {
return fmt.Errorf("invalid tokenOut: %w", err)
}
r.TokenOut = &tokenOutCoin
}
r.TokenInDenom = c.QueryParam("tokenInDenom")
r.TokenOutDenom = c.QueryParam("tokenOutDenom")
return nil
}

Comment on lines +44 to +54
func (s *RouterTestHelper) newRoutablePool(pool sqsdomain.PoolI, tokenOutDenom string, takerFee osmomath.Dec, cosmWasmConfig domain.CosmWasmPoolRouterConfig) domain.RoutablePool {
cosmWasmPoolsParams := pools.CosmWasmPoolsParams{
Config: cosmWasmConfig,
ScalingFactorGetterCb: domain.UnsetScalingFactorGetterCb,
}
routablePool, err := pools.NewRoutablePool(pool, tokenOutDenom, takerFee, cosmWasmPoolsParams)

s.Require().NoError(err)

return routablePool
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Address the linter issue.

The cosmWasmConfig parameter always receives a nil value. Consider removing the parameter if it is not needed or ensure it receives a valid value.

The linter issue needs to be addressed.

Tools
GitHub Check: Run linter

[failure] 44-44:
(*RouterTestHelper).newRoutablePool - cosmWasmConfig always receives domain.CosmWasmPoolRouterConfig{} (nil) (unparam)

Comment on lines +36 to +167
},
},
},
expectedStatusCode: http.StatusOK,
expectedResponse: s.MustReadFile("../../usecase/routertesting/parsing/quote_amount_in_response.json"),
expectedError: nil,
},
{
name: "valid exact out request",
queryParams: map[string]string{
"tokenOut": "1000ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4",
"tokenInDenom": "ibc/EA1D43981D5C9A1C4AAEA9C23BB1D4FA126BA9BC7020A25E0AE4AA841EA25DC5",
"singleRoute": "true",
"applyExponents": "true",
},
handler: &routerdelivery.RouterHandler{
TUsecase: &mocks.TokensUsecaseMock{
IsValidChainDenomFunc: func(chainDenom string) bool {
return true
},
},
RUsecase: &mocks.RouterUsecaseMock{
GetOptimalQuoteInGivenOutFunc: func(ctx context.Context, tokenIn sdk.Coin, tokenOutDenom string, opts ...domain.RouterOption) (domain.Quote, error) {
return s.NewExactAmountOutQuote(poolOne, poolTwo, poolThree), nil
},
},
},
expectedStatusCode: http.StatusOK,
expectedResponse: s.MustReadFile("../../usecase/routertesting/parsing/quote_amount_out_response.json"),
expectedError: nil,
},
{
name: "invalid swap method request",
queryParams: map[string]string{
"tokenIn": "1000ust",
"tokenOut": "1000usdc",
"singleRoute": "true",
"applyExponents": "true",
},
expectedStatusCode: http.StatusInternalServerError,
expectedResponse: `{"message": "swap method is invalid - must be either swap exact amount in or swap exact amount out"}`,
expectedError: routertypes.ErrSwapMethodNotValid,
},
{
name: "invalid tokenIn format",
queryParams: map[string]string{
"tokenIn": "invalid_denom",
"tokenOutDenom": "usdc",
"singleRoute": "true",
"applyExponents": "true",
},
expectedStatusCode: http.StatusInternalServerError,
expectedResponse: `{"message": "tokenIn is invalid - must be in the format amountDenom"}`,
expectedError: routertypes.ErrTokenInNotValid,
},
{
name: "invalid tokenOut format",
queryParams: map[string]string{
"tokenInDenom": "ust",
"tokenOut": "invalid_denom",
"singleRoute": "true",
"applyExponents": "true",
},
expectedStatusCode: http.StatusInternalServerError,
expectedResponse: `{"message": "tokenOut is invalid - must be in the format amountDenom"}`,
expectedError: routertypes.ErrTokenOutNotValid,
},
}
for _, tc := range testcases {
s.Run(tc.name, func() {
e := echo.New()
req := httptest.NewRequest(echo.POST, "/", nil)
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
q := req.URL.Query()
for k, v := range tc.queryParams {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)

err := tc.handler.GetOptimalQuote(c)

if tc.expectedError != nil {
s.Assert().Error(err)
s.Assert().Equal(tc.expectedError, err)
s.Assert().Equal(tc.expectedStatusCode, rec.Code)
s.Assert().JSONEq(tc.expectedResponse, rec.Body.String())
return
}

s.Assert().NoError(err)
s.Assert().Equal(tc.expectedStatusCode, rec.Code)
s.Assert().JSONEq(
strings.TrimSpace(tc.expectedResponse),
strings.TrimSpace(rec.Body.String()),
)
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhance test coverage and verify pool creation.

The function is well-structured and covers various scenarios. However, consider adding more edge cases and verifying the pool creation process to ensure comprehensive test coverage.

  • Add more edge cases, such as invalid pool IDs and edge cases for token amounts.
  • Verify the pool creation process to ensure pools are created correctly before running the tests.

@deividaspetraitis
Copy link
Collaborator Author

While I still believe that merging suggestions introduced in this PR would be beneficial, however due working on more high priority tasks it would be hard to allocate time for further discussions, thus I am cllosing this for now. We can always get back to it in the future. cc @p0mvn

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A:backport/v26.x backport patches to v26.x branch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants