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

BE-632 | Include limit order balances in passthrough/portfolio-assets #552

Open
wants to merge 13 commits into
base: v27.x
Choose a base branch
from

Conversation

deividaspetraitis
Copy link
Collaborator

@deividaspetraitis deividaspetraitis commented Nov 6, 2024

This PR introduces changes to include limit order balances in total balance for passthrough/portfolio-assets endpoint. As a side effect changes includes cleaning up hardcoded order direction strings in some places.

Consider we have ask order where we sell 0.1 OSMO and want to receive 1 USD. Order is 50% filled of which 25% is already claimed, that would result in following properties of the order:

  • Filled USD = 1 USD * 50% = 1 * 0.5 = 0.5 USD
  • Filled OSMO = 0.1 OSMO * 50% = 0.005
  • Claimed USD = 0.5 USD * 25% = 0.5 * 0.25 = 0.125 USD
  • Remaining Claimable USD = 0.5 USD - 0.125 USD = 0.375 USD

Introduced changes adds limit-orders section that contains unclaimed balances, as per example above such section would look like:

  "limit-orders": {
     "capitalization": "0.375", // USD
     "is_best_effort": false
   },

Second change is that unclaimed coins will appear under total-assets section in account_coins_result, for example:

   "total-assets": {
      "capitalization": "93.999502000156560410",
      "account_coins_result": [
        {
          "coin": {
            "denom": "USD",
            "amount": "0.375"
          },
          "cap_value": "0.375"
        },
      ],
      "is_best_effort": false
    },

At the moment I am opening this PR I am not 100% sure I have addressed the problem correctly because due following questions:

  1. When I placed above order from my account disappeared 0.1 OSMO, after it's filled 50% I still own 0.05, but where it's reflected?
  2. I am not sure I understand all of the sections of the output of this endpoint, for example user-balances vs account_coins_result.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced order book functionality integrated into the server, allowing for improved management of limit orders.
    • New methods added to handle order directions and calculate fillable amounts for limit orders.
    • The passthrough use case now supports fetching limit order coins alongside other asset types.
  • Bug Fixes

    • Improved error handling in order processing methods, ensuring clearer feedback on failures.
  • Documentation

    • Updated comments for clarity on method behaviors and structures related to order management.

deividaspetraitis and others added 7 commits October 31, 2024 14:07
adding backport mergify action and created A:backport/v27.x label
* BE-586 | Claimbot prototype

Init

* BE-586 | WIP

* BE-586 | WIP

* BE-595 | Clean up

* BE-586 | Add docs

* BE-586 | Clean up

* BE-586 | Add docs

* BE-596 | Tests init

* BE-586 | Add tests for slices, orderbook packages

* BE-586 | claimbot/tx tests

* BE-586 | claimbot/order.go tests

* BE-586 | Requested changes

* BE-586 | Process block orderbooks, tests

* BE-586 | Requested changes

* BE-586 | Config update

* BE-586 | OrderBookClient use slices.Split for pagination

Cleans up OrderBookClient by reusing slices.Split instead of duplicating
splitting slices into chunks logic in some of the methods.

* BE-586 | Clean up

* BE-586 | Fix fillbot docker-compose

Fixes errors running fillbot via docker-compose

* BE-586 | Docs, docker compose fixes

* BE-586 | Run fillbot via docker-compose

* BE-586 | Run claimbot via docker-compose, clean up

* BE-586 | Cleanup

* BE-586 | Named logger

* BE-586 | Requested changes

* BE-586 | Logging failing tx

* BE-586 | Increase gas adjustment

* BE-586 | Error logging fix

* BE-586 | Trace name update

* BE-586 | Requested changes #1

* BE-586 | Requested changes #2

* BE-586 | Sequence number update

* BE-586 | added tests

* BE-586 | Suggested improvements
* refactor: gas estimation APIs

* changelog

* lint
* feat: simulate swap as part of quotes

* try adding e2e test

* updates

* lint

* fix test

* swagger

* attempt fix grpc wiring

* fix e2e sim test

* updates
Includes limit order balances in total balance for passthrough/portfolio-assets
@deividaspetraitis deividaspetraitis self-assigned this Nov 6, 2024
@deividaspetraitis deividaspetraitis added the A:backport/v27.x Backport to v27.x branch label Nov 6, 2024
Copy link
Contributor

coderabbitai bot commented Nov 6, 2024

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 golangci-lint (1.62.2)

level=warning msg="The linter 'exportloopref' is deprecated (since v1.60.2) due to: Since Go1.22 (loopvar) this linter is no longer relevant. Replaced by copyloopvar."

Walkthrough

The pull request introduces significant enhancements to the order book functionality within the application. Key changes include the integration of a new orderBookUseCase into the passthroughUseCase, modifications to the NewSideCarQueryServer function for improved initialization, and the introduction of a new OrderDirection type to enhance type safety. Additionally, updates to various methods and structures reflect a more structured approach to handling order directions and fetching limit orders, thereby improving the overall architecture and maintainability of the code.

Changes

File Path Change Summary
app/sidecar_query_server.go - Added initialization for wasmQueryClient, orderBookAPIClient, orderBookRepository, and orderBookUseCase.
- Updated passthroughUseCase initialization to include orderBookUseCase.
- Modified HTTP handler to integrate orderBookUseCase.
domain/mvc/orderbook.go - Updated GetActiveOrders method signature to include an error return value and added a comment clarifying its behavior during errors.
domain/orderbook/order.go - Introduced OrderDirection type with associated methods and constants.
- Updated Order and LimitOrder structs to use OrderDirection instead of string.
- Added new methods for LimitOrder to calculate fillable amounts.
orderbook/usecase/orderbook_usecase.go - Replaced string comparisons for order directions with orderbookdomain.NewDirection method calls.
- Updated CreateFormattedLimitOrder and getClaimableOrdersForTick methods to utilize the new direction checks.
passthrough/usecase/passthrough_usecase.go - Added orderbookUseCase field to passthroughUseCase struct.
- Updated constructor to accept orderbookUseCase parameter.
- Introduced limitOrdersCategoryName constant and modified job fetching logic to include limit orders.

Suggested reviewers

  • p0mvn
  • PaddyMc

Poem

🐇 In the meadow where orders flow,
A new direction helps them grow.
With cases passed and orders set,
Our server's ready, no need to fret!
Fetching coins with a hop and a skip,
A world of trades at our fingertips! 🌼

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


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>, please review it.
    • 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @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 using 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 generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

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.

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: 4

🧹 Outside diff range and nitpick comments (8)
domain/mvc/orderbook.go (1)

20-20: Enhance error documentation clarity.

While the added documentation explains the boolean return value, it could be more explicit about the relationship between the error and boolean returns.

Consider this improved documentation:

-// If there was an error fetching the orders, the second return value will be true indicating best effort.
+// Returns (orders, bestEffort, error) where bestEffort is true if some orders were retrieved despite errors.
domain/orderbook/order.go (2)

101-106: Refactor OrderByDirection to handle OrderDirection consistently.

The method is using NewDirection to convert the string field from Order struct, which is a workaround for the inconsistent type usage. This could be simplified once the Order struct is updated to use the OrderDirection type.

func (o Orders) OrderByDirection(direction OrderDirection) Orders {
	var result Orders
	for _, v := range o {
-		if NewDirection(v.OrderDirection).Is(direction) {
+		if v.OrderDirection.Is(direction) {
			result = append(result, v)
		}
	}
	return result
}

146-159: Enhance documentation for calculation methods.

While the implementation looks correct, the methods would benefit from more detailed documentation explaining:

  • The business logic behind each calculation
  • The units/denomination of the returned values
  • Example scenarios showing how these calculations are used
-// ClaimableAmountOfOSMO calculates the claimable amount of base asset
+// ClaimableAmount calculates the remaining claimable amount from filled orders
+// that haven't been claimed yet.
+// For example, if an order is 80% filled and 30% claimed:
+// - TotalFilled = 0.8
+// - PercentClaimed = 0.3
+// - ClaimableAmount = 0.8 - (0.8 * 0.3) = 0.56
 func (o LimitOrder) ClaimableAmount() osmomath.Dec {

-// GetQuoteFillableAmount calculates the amount of quote asset left to be filled
+// QuoteAssetFillableAmount calculates the remaining quote asset amount that can still
+// be filled for this order. This represents the difference between the initially
+// placed quantity and the amount that has been filled so far.
 func (o LimitOrder) QuoteAssetFillableAmount() osmomath.Dec {

-// GetBaseAssetFillableAmount calculates the amount of base asset left to be filled
+// BaseAssetFillableAmount calculates the remaining base asset amount that can still
+// be filled for this order. This represents the difference between the initial
+// quantity and the total amount that has been filled so far.
 func (o LimitOrder) BaseAssetFillableAmount() osmomath.Dec {
orderbook/usecase/orderbook_usecase.go (2)

487-487: Consider caching the direction conversion

While the type-safe direction handling is good, NewDirection is called twice for each order - once during direction checking and again when creating the LimitOrder struct. Consider caching the result of the first conversion to avoid redundant processing.

- OrderDirection:   orderbookdomain.NewDirection(order.OrderDirection),
+ direction := orderbookdomain.NewDirection(order.OrderDirection)
// Use direction in the checks above and here
+ OrderDirection:   direction,

542-547: Consider pre-allocating the result slice

The append operation in the return statement might cause unnecessary slice reallocations. Consider pre-allocating the result slice with an estimated capacity based on the lengths of askClaimable and bidClaimable.

- return append(askClaimable, bidClaimable...), nil
+ result := make([]orderbookdomain.ClaimableOrder, 0, len(askClaimable)+len(bidClaimable))
+ result = append(result, askClaimable...)
+ result = append(result, bidClaimable...)
+ return result, nil
passthrough/usecase/passthrough_usecase.go (1)

90-92: Document the reasoning behind job count constants.

Consider adding comments to explain how these numbers are calculated:

-const (
-  numFinalResultJobs = 8
-  totalAssetCompositionNumJobs = 7
+// Constants for job counts
+const (
+  // Total number of final result jobs:
+  // 1. User balances
+  // 2. Total assets
+  // 3. Unstaking
+  // 4. Staked
+  // 5. Unclaimed rewards
+  // 6. Pooled
+  // 7. In-locks
+  // 8. Limit orders
+  numFinalResultJobs = 8
+
+  // Total number of jobs for asset composition:
+  // 1. User balances
+  // 2. Unstaking
+  // 3. Staked
+  // 4. In-locks
+  // 5. Unclaimed rewards
+  // 6. Pooled
+  // 7. Limit orders
+  totalAssetCompositionNumJobs = 7
app/sidecar_query_server.go (2)

188-191: Ensure Proper Error Handling During Initialization

While initializing wasmQueryClient, orderBookAPIClient, orderBookRepository, and orderBookUseCase, there is no error handling in place. If any of these initializations fail internally, it could lead to runtime panics or unexpected behavior.

Consider adding error checks if these functions can return errors. For example, if orderbookusecase.New returns an error:

orderBookUseCase, err := orderbookusecase.New(orderBookRepository, orderBookAPIClient, poolsUseCase, tokensUseCase, logger)
if err != nil {
    return nil, err
}

Ensure that you handle errors appropriately to maintain robustness.


188-194: Improve Code Readability by Renaming Local Variables

The variable passthroughUseCase is used both as a package name (import alias) and as a local variable. This can lead to confusion and reduce code readability.

Consider renaming the local variable to avoid shadowing the package name:

-passthroughUseCase := passthroughUseCase.NewPassThroughUsecase(...)
+passThroughUC := passthroughUseCase.NewPassThroughUsecase(...)

This change clarifies the distinction between the package and the variable, improving maintainability.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between fcbf7b6 and 0e45457.

⛔ Files ignored due to path filters (3)
  • domain/orderbook/order_test.go is excluded by !**/*_test.go
  • passthrough/usecase/export_test.go is excluded by !**/*_test.go
  • passthrough/usecase/passthrough_usecase_test.go is excluded by !**/*_test.go
📒 Files selected for processing (5)
  • app/sidecar_query_server.go (1 hunks)
  • domain/mvc/orderbook.go (1 hunks)
  • domain/orderbook/order.go (5 hunks)
  • orderbook/usecase/orderbook_usecase.go (4 hunks)
  • passthrough/usecase/passthrough_usecase.go (7 hunks)
🔇 Additional comments (7)
domain/mvc/orderbook.go (1)

21-21: Verify implementation of updated GetActiveOrders signature.

The addition of the error return value is a good practice for explicit error handling. However, we should verify that all implementations of this interface have been updated accordingly.

✅ Verification successful

Let me gather more information to verify the implementation details.


All implementations correctly handle the error return value

Based on the code analysis:

  • The interface implementation in OrderbookUseCaseImpl.GetActiveOrders returns ([]orderbookdomain.LimitOrder, bool, error)
  • The gRPC client implementation in orderbookClientImpl.GetActiveOrders returns (orderbookdomain.Orders, uint64, error)
  • All callers properly handle the error:
    • passthrough_usecase.go checks and handles the error
    • passthrough_handler.go checks error and returns appropriate HTTP response
    • orderbook_usecase.go propagates the error with proper error wrapping
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all implementations of GetActiveOrders to verify they match the new signature

# Search for interface implementations
ast-grep --pattern 'type $_ struct {
  $$$
}

func ($_ $_) GetActiveOrders(ctx context.Context, address string) $$$'

# Search for any direct calls to GetActiveOrders to ensure they handle the new error return
rg -A 2 'GetActiveOrders\(ctx,'

Length of output: 1356


Script:

#!/bin/bash
# Search for the interface definition and any other struct implementations
ast-grep --pattern 'type $_ interface {
  $$$
  GetActiveOrders(ctx context.Context, address string) $$$
}'

# Search for the orderBookClient implementation
ast-grep --pattern 'func ($_ $_) GetActiveOrders(ctx context.Context, $_, $_ string) $$$'

# Look for the actual implementation in the repository
rg -A 5 'func.*GetActiveOrders.*\('

Length of output: 8915

domain/orderbook/order.go (1)

146-149: LGTM: Changes align well with PR objectives.

The new calculation methods directly support the PR's goal of including limit order balances in portfolio assets by providing precise calculations for:

  • Claimable amounts from filled orders
  • Remaining fillable amounts in both quote and base assets

Also applies to: 151-154, 156-159

orderbook/usecase/orderbook_usecase.go (2)

391-392: Great improvement in order direction handling!

The replacement of string literals with orderbookdomain.NewDirection(order.OrderDirection).Is() checks enhances type safety and reduces the risk of errors from typos in string literals. This change aligns well with the PR's goal of cleaning up hardcoded order direction strings.

Also applies to: 464-465


Line range hint 464-471: Verify balance calculation for partially filled orders

Given the PR's focus on limit order balances and the uncertainty about remaining balances after partial fills, please verify that the output calculation correctly handles partially filled orders:

  1. For bid orders: output = placedQuantity.Quo(price.Dec())
  2. For ask orders: output = placedQuantity.Mul(price.Dec())

The calculation uses placedQuantity instead of the remaining quantity (quantity). This might need adjustment depending on whether we want to show the total original balance or just the remaining claimable balance.

✅ Verification successful

Let me gather more information about the balance calculation logic.


Based on the code analysis, I can now provide a final response about the balance calculation logic.

Balance calculation for partially filled orders is correct

The implementation correctly uses placedQuantity for balance calculation as it represents the total order size, which is the right approach for showing claimable balances:

  1. For bid orders: output = placedQuantity.Quo(price.Dec()) - Correctly calculates the total base asset amount that can be claimed
  2. For ask orders: output = placedQuantity.Mul(price.Dec()) - Correctly calculates the total quote asset amount that can be claimed

The code also properly tracks:

  • Remaining quantity through quantity
  • Fill status via percentFilled = totalFilled.Quo(placedQuantity)
  • Claim status via percentClaimed = placedQuantity.Sub(quantity).Quo(placedQuantity)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for tests verifying partial fill scenarios
rg -A 10 "TestPartialFill|partial.*fill" --type go

Length of output: 3769


Script:

#!/bin/bash
# Search for order placement and balance calculation logic
ast-grep --pattern 'func $_($$$) {
  $$$
  placedQuantity := $$$
  $$$
}'

# Search for quantity-related fields and methods
rg -A 5 "Quantity|quantity" --type go orderbook/

Length of output: 18749

passthrough/usecase/passthrough_usecase.go (3)

20-25: LGTM: Clean dependency injection implementation.

The addition of orderbookUseCase follows good practices by using interface type and maintaining consistency with existing field patterns.


289-292: LGTM: Clean integration of limit orders processing.

The limit orders job is properly integrated into the existing concurrent processing pipeline, maintaining consistency with the established pattern.

Also applies to: 400-400


248-258: Verify order direction handling.

The PR objectives mention cleaning up hardcoded order direction strings, but the current implementation doesn't show explicit handling of order directions. Let's verify the order direction handling in the codebase:

✅ Verification successful

Let me gather more information about the OrderDirection type and its usage in the codebase.


Let me search for more specific information about how order directions are handled in the active orders context.


Based on the comprehensive search results, I can now generate the final response:

Order direction handling is properly implemented and not hardcoded

The codebase shows a well-structured implementation of order directions:

  • Order directions are defined as constants (DirectionBid and DirectionAsk) in domain/orderbook/order.go
  • The OrderDirection type is properly typed as a string with validation methods
  • The GetActiveOrders implementation handles orders regardless of their direction
  • Test cases cover both bid and ask directions with proper type checking

The PR's objective of cleaning up hardcoded order direction strings has been achieved through:

  1. Using typed constants instead of raw strings
  2. Proper encapsulation in the domain model
  3. Consistent usage across the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for hardcoded order direction strings that might need cleanup
echo "Searching for hardcoded order direction strings..."
rg -i "\"(buy|sell|ask|bid)\"" --type go

# Search for order direction type usage
echo "Searching for OrderDirection type usage..."
ast-grep --pattern 'type OrderDirection'

Length of output: 6160


Script:

#!/bin/bash
# Search for OrderDirection type definition and its usage
echo "Searching for OrderDirection type and its usage..."
rg -A 5 "type OrderDirection" --type go

# Search for GetActiveOrders implementation to understand order direction handling
echo "Searching for GetActiveOrders implementation..."
ast-grep --pattern 'GetActiveOrders($$$) {
  $$$
}'

Length of output: 655


Script:

#!/bin/bash
# Search for GetActiveOrders implementation with more context
echo "Searching for GetActiveOrders usage and implementation..."
rg -A 10 "GetActiveOrders" --type go

# Search for order direction handling in the orderbook usecase
echo "Searching for order direction handling in orderbook..."
rg -A 5 "OrderDirection" --type go --type-add go:*.{go,proto} --no-filename

Length of output: 53037

domain/orderbook/order.go Show resolved Hide resolved
domain/orderbook/order.go Outdated Show resolved Hide resolved
passthrough/usecase/passthrough_usecase.go Outdated Show resolved Hide resolved
app/sidecar_query_server.go Outdated Show resolved Hide resolved
Copy link
Contributor

coderabbitai bot commented Nov 6, 2024

Walkthrough

The pull request introduces several enhancements to the order book functionality within the application. Key modifications include the integration of new components related to order book operations in the sidecar_query_server.go, updates to method signatures and error handling in the OrderBookUsecase interface, and the introduction of a new OrderDirection type in the orderbook domain. Additionally, the passthroughUseCase is updated to manage limit orders, reflecting a broader scope of functionality. Overall, these changes enhance the server's capabilities and improve the structure and clarity of the order book management.

Changes

File Change Summary
app/sidecar_query_server.go - Added initialization for wasmQueryClient, orderBookAPIClient, orderBookRepository, and orderBookUseCase in NewSideCarQueryServer.
- Updated passthroughUseCase to include orderBookUseCase as a parameter.
domain/mvc/orderbook.go - Updated GetActiveOrders method signature to include an error return value.
- Added comments clarifying method behavior on errors.
domain/orderbook/order.go - Introduced OrderDirection type and associated methods/constants.
- Updated Order struct to use OrderDirection instead of string.
- Added methods to LimitOrder for calculating fillable amounts.
orderbook/usecase/orderbook_usecase.go - Updated methods in OrderbookUseCaseImpl to utilize OrderDirection instead of string literals for order direction handling.
passthrough/usecase/passthrough_usecase.go - Modified NewPassThroughUsecase to accept orderbookUseCase.
- Added getLimitOrderCoins method for fetching limit order coins.
- Introduced limitOrdersCategoryName constant.

Possibly related PRs

Suggested reviewers

  • p0mvn
  • cryptomatictrader

Poem

🐇 In the server's heart, a change so bright,
Order books dancing in the digital light.
With new directions and limits in tow,
The passthrough hops where the data flows.
Fetching coins with a joyful cheer,
Enhancements abound, the future is near! 🌟


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>, please review it.
    • 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @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 using 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.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

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.

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: 6

🧹 Outside diff range and nitpick comments (5)
domain/orderbook/order.go (2)

9-31: LGTM! Consider adding validation in NewDirection.

The introduction of OrderDirection type improves type safety and maintainability. The implementation is clean and well-documented.

Consider adding validation in NewDirection to ensure only valid directions are created:

func NewDirection(direction string) OrderDirection {
+    switch direction {
+    case string(DirectionBid), string(DirectionAsk):
+        return OrderDirection(direction)
+    default:
+        panic(fmt.Sprintf("invalid order direction: %s", direction))
+    }
-    return OrderDirection(direction)
}

119-137: LGTM! Consider adding field documentation.

The LimitOrder struct fields are well-organized and cover all necessary data for limit order processing. However, some fields lack documentation explaining their purpose and units.

Consider adding documentation for fields like PercentClaimed, TotalFilled, Output, etc., to clarify their purpose and units.

orderbook/usecase/orderbook_usecase.go (3)

391-391: Remove unnecessary empty line.

This empty line doesn't serve any purpose and can be removed to maintain code cleanliness.


Line range hint 391-503: Consider breaking down CreateFormattedLimitOrder into smaller functions.

The CreateFormattedLimitOrder method is quite long and handles multiple responsibilities:

  • Asset metadata retrieval
  • Tick processing
  • Quantity calculations
  • Price normalization
  • Status determination

Consider extracting some of these responsibilities into helper functions to improve readability and maintainability.


Line range hint 464-469: Add inline documentation for price calculations.

The price and output calculations are complex and would benefit from inline documentation explaining:

  • The relationship between price and direction
  • Why the calculations differ for bid vs ask orders
  • The significance of normalization
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between fcbf7b6 and 0e45457.

⛔ Files ignored due to path filters (3)
  • domain/orderbook/order_test.go is excluded by !**/*_test.go
  • passthrough/usecase/export_test.go is excluded by !**/*_test.go
  • passthrough/usecase/passthrough_usecase_test.go is excluded by !**/*_test.go
📒 Files selected for processing (5)
  • app/sidecar_query_server.go (1 hunks)
  • domain/mvc/orderbook.go (1 hunks)
  • domain/orderbook/order.go (5 hunks)
  • orderbook/usecase/orderbook_usecase.go (4 hunks)
  • passthrough/usecase/passthrough_usecase.go (7 hunks)
🔇 Additional comments (13)
domain/mvc/orderbook.go (2)

20-21: LGTM! Clear documentation of error handling behavior.

The added comment clearly documents the meaning of the boolean return value, which is crucial for understanding the best-effort nature of the operation.


20-21: Verify error handling in implementations.

The addition of the error return parameter is a good practice for proper error propagation. However, we should ensure all implementations handle errors consistently.

✅ Verification successful

Based on the search results, I can now generate the final response as we have found the implementation and test cases showing error handling.

Error handling is properly implemented across the codebase

The implementation in orderbook/usecase/orderbook_usecase.go correctly handles and propagates errors:

  • Returns errors with proper wrapping (e.g., types.FailedGetAllCanonicalOrderbookPoolIDsError)
  • Maintains the contract of returning ([]orderbookdomain.LimitOrder, bool, error)

Test cases in passthrough/delivery/http/passthrough_handler_test.go verify both success and error scenarios:

  • Success case returns orders with false for best effort and nil error
  • Error case properly propagates the error and returns nil orders
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all implementations of GetActiveOrders to verify error handling
# Test: Search for implementations of GetActiveOrders. Expect: All implementations should handle and return errors properly

# Find all implementations
ast-grep --pattern 'func ($struct $_) GetActiveOrders(ctx context.Context, address string) ([]orderbookdomain.LimitOrder, bool, error) {
  $$$
}'

# Find any old implementations that might need updating
ast-grep --pattern 'func ($struct $_) GetActiveOrders(ctx context.Context, address string) ([]orderbookdomain.LimitOrder, bool) {
  $$$
}'

Length of output: 288


Script:

#!/bin/bash
# Let's try a different approach using ripgrep to find implementations
rg "GetActiveOrders.*\(ctx context\.Context, address string\)" -A 10

# Also search for the interface definition to understand the contract
rg "type.*interface.*{" -A 20 "orderbook.go"

Length of output: 11206

orderbook/usecase/orderbook_usecase.go (2)

392-392: LGTM! Improved type safety with NewDirection.

The consistent use of orderbookdomain.NewDirection() instead of string comparisons enhances type safety and reduces the likelihood of errors. This change aligns well with the PR's objective of cleaning up hardcoded order direction strings.

Also applies to: 464-464, 487-487


542-547: LGTM! Consistent use of direction constants.

The use of orderbookdomain.DirectionAsk and orderbookdomain.DirectionBid constants is consistent with the improved type safety approach.

Given the PR objectives to include limit order balances in portfolio assets, let's verify the balance calculations:

app/sidecar_query_server.go (1)

188-192: Initialization of order book components looks good

The initialization of wasmQueryClient, orderBookAPIClient, orderBookRepository, and orderBookUseCase is correct and enhances the server's capabilities to manage order book operations.

passthrough/usecase/passthrough_usecase.go (8)

22-22: Addition of orderbookUseCase to passthroughUseCase struct

The orderbookUseCase field has been added to the passthroughUseCase struct, aligning with the integration of limit order functionalities.


37-37: Definition of limitOrdersCategoryName constant

Defining limitOrdersCategoryName as "limit-orders" ensures consistency when referencing this category throughout the codebase.


90-92: Verify the correctness of job count constants

The constants have been updated:

  • numFinalResultJobs set to 8
  • totalAssetCompositionNumJobs set to 7

Please confirm that these constants accurately reflect the updated number of jobs after including limit orders. This ensures proper synchronization and prevents potential issues with job handling.


109-117: Expansion of NewPassThroughUsecase constructor

The constructor now includes the orderbookUseCase parameter, and it is appropriately assigned within the passthroughUseCase struct.


120-125: Correct assignment of new dependencies

All new parameters, including orderbookUseCase, are correctly assigned to the struct fields, ensuring proper initialization.


248-259: Validate order.BaseAsset.Symbol for correctness

Ensure that order.BaseAsset.Symbol corresponds to a valid denomination recognized by the system. Incorrect or unrecognized symbols may cause issues in downstream processing.

Please verify that order.BaseAsset.Symbol consistently represents a valid denom and consider adding validation or mapping if necessary.


289-292: Inclusion of limit-orders category in fetch jobs

Adding the limit-orders category to fetchJobs ensures that limit order balances are fetched and included in the portfolio assets.


400-400: Update to include limit orders in the final job aggregation

The comment now reflects the addition of the limit orders category:

 // 7. In-locks
-// 8. [placeholder for future categories]
+// 8. Limit orders

domain/orderbook/order.go Outdated Show resolved Hide resolved
domain/orderbook/order.go Show resolved Hide resolved
Comment on lines +146 to +159
// ClaimableAmountOfOSMO calculates the claimable amount of base asset
func (o LimitOrder) ClaimableAmount() osmomath.Dec {
return o.TotalFilled.Sub(o.TotalFilled.Mul(o.PercentClaimed))
}

// GetQuoteFillableAmount calculates the amount of quote asset left to be filled
func (o LimitOrder) QuoteAssetFillableAmount() osmomath.Dec {
return o.PlacedQuantity.Sub(o.Output.Mul(o.PercentFilled))
}

// GetBaseAssetFillableAmount calculates the amount of base asset left to be filled
func (o LimitOrder) BaseAssetFillableAmount() osmomath.Dec {
return o.Quantity.Sub(o.TotalFilled)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Missing test coverage for fillable amount calculations

While ClaimableAmount() is well-tested with various scenarios, the QuoteAssetFillableAmount() and BaseAssetFillableAmount() methods lack test coverage. These methods perform critical calculations for determining remaining fillable amounts and should be thoroughly tested:

  • QuoteAssetFillableAmount: Calculates remaining quote asset using PlacedQuantity.Sub(o.Output.Mul(o.PercentFilled))
  • BaseAssetFillableAmount: Calculates remaining base asset using Quantity.Sub(o.TotalFilled)
🔗 Analysis chain

Verify calculation methods against requirements.

The calculation methods look correct and align with the PR objectives. For example, ClaimableAmount correctly calculates the remaining claimable amount as demonstrated in the PR description (e.g., 0.5 USD - 0.125 USD = 0.375 USD).

Let's verify the usage of these calculation methods:


Let me verify the test coverage to ensure these calculation methods are properly tested.


Let me check for tests of the remaining two calculation methods.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of the new calculation methods to ensure they're used correctly
# in the portfolio assets endpoint

rg -A 5 "ClaimableAmount|QuoteAssetFillableAmount|BaseAssetFillableAmount" --type go

Length of output: 2115


Script:

#!/bin/bash
# Check test coverage for these calculation methods
cat domain/orderbook/order_test.go

Length of output: 7545


Script:

#!/bin/bash
# Search for tests of QuoteAssetFillableAmount and BaseAssetFillableAmount
ast-grep --pattern 'func Test$_(t *testing.T) {
  $$$
  QuoteAssetFillableAmount()
  $$$
}'

ast-grep --pattern 'func Test$_(t *testing.T) {
  $$$
  BaseAssetFillableAmount()
  $$$
}'

Length of output: 186

app/sidecar_query_server.go Show resolved Hide resolved
passthrough/usecase/passthrough_usecase.go Outdated Show resolved Hide resolved
passthrough/usecase/passthrough_usecase.go Outdated Show resolved Hide resolved
passthrough/usecase/passthrough_usecase.go Outdated Show resolved Hide resolved
passthrough/usecase/passthrough_usecase.go Outdated Show resolved Hide resolved
passthrough/usecase/passthrough_usecase.go Outdated Show resolved Hide resolved
@p0mvn
Copy link
Member

p0mvn commented Nov 12, 2024

When I placed above order from my account disappeared 0.1 OSMO, after it's filled 50% I still own 0.05, but where it's reflected?

I don't fully understand what happened here - could you elaborate?

@p0mvn
Copy link
Member

p0mvn commented Nov 12, 2024

I am not sure I understand all of the sections of the output of this endpoint, for example user-balances vs account_coins_result.

User balances only contain the user balances while the latter contains all of the value from pools, unclaimed rewards etc

@p0mvn
Copy link
Member

p0mvn commented Nov 12, 2024

Do you mind please updating the docs with the limit order data too please?

### Portfolio Assets
#### Locks
Can be locked or unlocking. Can be regular token, gamm share or CL share.
If CL share, we want to skip because we get CL value from positions.
For token and gamm shares, there is no overlap with pooled assets or user-balances. As a result,
we count them as its own contribution to total assets.
#### Pooled Assets
Stem from concentrated liquidity positions and unlocked gamm shares from bank balances.
#### User Balances
Individual coins from bank balances, excluding gamm shares.
#### Staked
Staked value from delegator delegations chain query.
#### Unstaking
Unstaking value from delegator undelegating chain query.
#### Unclaimed Rewards
Unclaimed rewards from concentrated liquidity positions and unclaimed rewards from staking rewards.

@p0mvn
Copy link
Member

p0mvn commented Nov 12, 2024

Let's also extend this test:

def run_test_portfolio_assets(environment_url):

Copy link

sonarcloud bot commented Nov 21, 2024

@deividaspetraitis deividaspetraitis changed the base branch from v26.x to v27.x December 9, 2024 10:02
@deividaspetraitis deividaspetraitis added A:backport/v28.x Backport to v28.x branch and removed A:backport/v27.x Backport to v27.x branch labels Dec 9, 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: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0e45457 and a019f5a.

📒 Files selected for processing (3)
  • app/sidecar_query_server.go (1 hunks)
  • orderbook/usecase/orderbook_usecase.go (3 hunks)
  • passthrough/usecase/passthrough_usecase.go (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • orderbook/usecase/orderbook_usecase.go
🔇 Additional comments (8)
app/sidecar_query_server.go (2)

196-199: LGTM! Clean initialization of order book components.

The initialization sequence follows clean architecture patterns with proper dependency injection.


202-202: Remove unnecessary error check after NewPassThroughUsecase.

The function does not return an error, but the code might be checking err afterward.

passthrough/usecase/passthrough_usecase.go (6)

20-22: LGTM! Clean addition of order book use case field.

The field is properly placed and correctly typed.


37-37: LGTM! Consistent constant naming.

The constant follows the established naming pattern.


90-92: LGTM! Job counts properly updated.

Constants correctly reflect the addition of limit orders category.


109-125: LGTM! Constructor properly updated.

The constructor signature and implementation correctly handle the new dependency.


294-297: LGTM! Fetch job properly configured.

The limit orders fetch job follows the established pattern.


405-405: LGTM! Comment updated to include limit orders.

Documentation accurately reflects the addition of limit orders.

Comment on lines 248 to 263
getLimitOrderCoins := func(ctx context.Context, address string) (sdk.Coins, error) {
orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
if err != nil {
return nil, err
}

var limitOrdersCoins sdk.Coins
for _, order := range orders {
limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
Denom: order.BaseAsset.Symbol,
Amount: order.ClaimableAmount().TruncateInt(),
})
}

return limitOrdersCoins, err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix error return in getLimitOrderCoins.

The function returns err on line 262, but this variable was already checked and handled. The function should return nil as the error.

Apply this diff:

-		return limitOrdersCoins, err
+		return limitOrdersCoins, 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
getLimitOrderCoins := func(ctx context.Context, address string) (sdk.Coins, error) {
orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
if err != nil {
return nil, err
}
var limitOrdersCoins sdk.Coins
for _, order := range orders {
limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
Denom: order.BaseAsset.Symbol,
Amount: order.ClaimableAmount().TruncateInt(),
})
}
return limitOrdersCoins, err
}
getLimitOrderCoins := func(ctx context.Context, address string) (sdk.Coins, error) {
orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
if err != nil {
return nil, err
}
var limitOrdersCoins sdk.Coins
for _, order := range orders {
limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
Denom: order.BaseAsset.Symbol,
Amount: order.ClaimableAmount().TruncateInt(),
})
}
return limitOrdersCoins, nil
}

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: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a019f5a and b918fb3.

📒 Files selected for processing (2)
  • domain/orderbook/order.go (5 hunks)
  • passthrough/usecase/passthrough_usecase.go (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • domain/orderbook/order.go
🔇 Additional comments (4)
passthrough/usecase/passthrough_usecase.go (4)

15-15: LGTM: Clean integration of orderbook functionality

The import and struct field additions are well-organized and follow Go conventions.

Also applies to: 21-23


110-126: LGTM: Constructor updated correctly

The constructor signature and implementation are properly updated to include the new orderbook use case.


310-313: LGTM: Job configuration properly updated

The limit orders job is correctly integrated into the existing job configuration structure.


91-93: Verify constant values consistency

The incremented values for numFinalResultJobs and totalAssetCompositionNumJobs need verification to ensure they match the actual number of jobs after adding limit orders support.

✅ Verification successful

Let me gather more information to verify the job counts accurately.


Based on the code analysis, I can now provide the final response:

Constants correctly reflect the number of jobs

The constant values are accurate:

  • numFinalResultJobs = 8 matches the 8 categories being processed:

    1. User balances
    2. Total assets
    3. Pooled
    4. Staked
    5. Unclaimed rewards
    6. Pooled
    7. In-locks
    8. Limit orders
  • totalAssetCompositionNumJobs = 7 matches the number of jobs that contribute to total assets composition, as commented in the code:

    1. User balances
    2. Pooled
    3. In-locks
    4. Staked
    5. Unclaimed rewards
    6. Pooled
    7. Limit orders
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Count the actual number of jobs in the code
echo "Checking job counts..."
rg -U "fetchJobs.*\[\]fetchBalancesPortfolioAssetsJob.*\{(?s:.)*?\}" | grep -c "name:"

Length of output: 143


Script:

#!/bin/bash
# Search for all job-related constants and their usage
echo "Searching for job-related code..."
rg "Job" -A 5 -B 5 passthrough/usecase/passthrough_usecase.go

# Search for any job creation or initialization
echo -e "\nSearching for job initialization..."
rg "jobs\s*:=\s*\[" -A 20 passthrough/usecase/passthrough_usecase.go

# Look for any job type definitions
echo -e "\nSearching for job type definitions..."
ast-grep --pattern 'type $_Job struct {
  $$$
}'

Length of output: 7291

Comment on lines 249 to 279
getLimitOrderCoins := func(ctx context.Context, address string) (sdk.Coins, error) {
orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
if err != nil {
return nil, err
}

var limitOrdersCoins sdk.Coins
for _, order := range orders {
denom, err := func() (string, error) {
switch order.OrderDirection {
case orderbookdomain.DirectionAsk:
return order.BaseAsset.Symbol, nil
case orderbookdomain.DirectionBid:
return order.QuoteAsset.Symbol, nil
default:
return "", fmt.Errorf("unknown order direction: %s", order.OrderDirection)
}
}()
if err != nil {
p.logger.Error("unable to get denom for limit order", zap.Error(err))
continue
}

limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
Denom: denom,
Amount: order.Quantity.TruncateInt(),
})
}

return limitOrdersCoins, err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Multiple improvements needed for getLimitOrderCoins

  1. Error handling issue on line 278
  2. Performance optimization opportunity
  3. Missing function documentation

Apply these improvements:

+// getLimitOrderCoins returns the total coins from active limit orders for the given address.
+// For ask orders, it returns the base asset quantity, and for bid orders, it returns the quote asset quantity.
 getLimitOrderCoins := func(ctx context.Context, address string) (sdk.Coins, error) {
     orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
     if err != nil {
         return nil, err
     }

-    var limitOrdersCoins sdk.Coins
+    // Preallocate slice with capacity of orders
+    limitOrdersCoins := make(sdk.Coins, 0, len(orders))
     for _, order := range orders {
         denom, err := func() (string, error) {
             switch order.OrderDirection {
             case orderbookdomain.DirectionAsk:
                 return order.BaseAsset.Symbol, nil
             case orderbookdomain.DirectionBid:
                 return order.QuoteAsset.Symbol, nil
             default:
                 return "", fmt.Errorf("unknown order direction: %s", order.OrderDirection)
             }
         }()
         if err != nil {
             p.logger.Error("unable to get denom for limit order", zap.Error(err))
             continue
         }

         limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
             Denom:  denom,
             Amount: order.Quantity.TruncateInt(),
         })
     }

-    return limitOrdersCoins, err
+    return limitOrdersCoins, 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
getLimitOrderCoins := func(ctx context.Context, address string) (sdk.Coins, error) {
orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
if err != nil {
return nil, err
}
var limitOrdersCoins sdk.Coins
for _, order := range orders {
denom, err := func() (string, error) {
switch order.OrderDirection {
case orderbookdomain.DirectionAsk:
return order.BaseAsset.Symbol, nil
case orderbookdomain.DirectionBid:
return order.QuoteAsset.Symbol, nil
default:
return "", fmt.Errorf("unknown order direction: %s", order.OrderDirection)
}
}()
if err != nil {
p.logger.Error("unable to get denom for limit order", zap.Error(err))
continue
}
limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
Denom: denom,
Amount: order.Quantity.TruncateInt(),
})
}
return limitOrdersCoins, err
}
// getLimitOrderCoins returns the total coins from active limit orders for the given address.
// For ask orders, it returns the base asset quantity, and for bid orders, it returns the quote asset quantity.
getLimitOrderCoins := func(ctx context.Context, address string) (sdk.Coins, error) {
orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
if err != nil {
return nil, err
}
// Preallocate slice with capacity of orders
limitOrdersCoins := make(sdk.Coins, 0, len(orders))
for _, order := range orders {
denom, err := func() (string, error) {
switch order.OrderDirection {
case orderbookdomain.DirectionAsk:
return order.BaseAsset.Symbol, nil
case orderbookdomain.DirectionBid:
return order.QuoteAsset.Symbol, nil
default:
return "", fmt.Errorf("unknown order direction: %s", order.OrderDirection)
}
}()
if err != nil {
p.logger.Error("unable to get denom for limit order", zap.Error(err))
continue
}
limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
Denom: denom,
Amount: order.Quantity.TruncateInt(),
})
}
return limitOrdersCoins, nil
}

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: 1

🧹 Outside diff range and nitpick comments (2)
passthrough/usecase/passthrough_usecase.go (2)

110-126: Consider using a config struct for constructor parameters

The constructor's parameter list is growing long. Consider introducing a config struct to improve maintainability and make future additions easier.

+type PassThroughConfig struct {
+    PassthroughGRPCClient passthroughdomain.PassthroughGRPCClient
+    PoolsUseCase          mvc.PoolsUsecase
+    TokensUseCase         mvc.TokensUsecase
+    OrderbookUseCase      mvc.OrderBookUsecase
+    LiquidityPricer       domain.LiquidityPricer
+    DefaultQuoteDenom     string
+    Logger                log.Logger
+}

-func NewPassThroughUsecase(
-    passthroughGRPCClient passthroughdomain.PassthroughGRPCClient,
-    poolsUseCase mvc.PoolsUsecase,
-    tokensUseCase mvc.TokensUsecase,
-    orderbookUseCase mvc.OrderBookUsecase,
-    liquidityPricer domain.LiquidityPricer,
-    defaultQuoteDenom string,
-    logger log.Logger,
-) *passthroughUseCase {
+func NewPassThroughUsecase(config PassThroughConfig) *passthroughUseCase {
     return &passthroughUseCase{
-        passthroughGRPCClient: passthroughGRPCClient,
-        poolsUseCase:          poolsUseCase,
-        tokensUseCase:         tokensUseCase,
-        orderbookUseCase:      orderbookUseCase,
-        defaultQuoteDenom:     defaultQuoteDenom,
-        liquidityPricer:       liquidityPricer,
-        logger:                logger,
+        passthroughGRPCClient: config.PassthroughGRPCClient,
+        poolsUseCase:          config.PoolsUseCase,
+        tokensUseCase:         config.TokensUseCase,
+        orderbookUseCase:      config.OrderbookUseCase,
+        defaultQuoteDenom:     config.DefaultQuoteDenom,
+        liquidityPricer:       config.LiquidityPricer,
+        logger:                config.Logger,
     }
}

260-264: Consider a more concise implementation

The callback function can be simplified since it's just forwarding the channel results.

-getLimitOrderCoins := func(ctx context.Context, address string) (sdk.Coins, error) {
-    limitOrdersResult := <-limitOrdersChan
-    return limitOrdersResult.coins, limitOrdersResult.err
-}
+getLimitOrderCoins := func(ctx context.Context, address string) (result coinsResult) {
+    return <-limitOrdersChan
+}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between b918fb3 and e6d95de.

📒 Files selected for processing (1)
  • passthrough/usecase/passthrough_usecase.go (10 hunks)
🔇 Additional comments (4)
passthrough/usecase/passthrough_usecase.go (4)

15-15: LGTM: Clean integration of orderbook functionality

The orderbook integration follows the existing pattern and maintains consistency with the codebase structure.

Also applies to: 23-23


145-147: LGTM: Clean channel setup

The limit orders channel setup follows the existing patterns and includes proper cleanup.


193-200: LGTM: Clean goroutine implementation

The goroutine follows the established pattern and correctly handles the channel communication.


294-297: LGTM: Clean fetch job addition

The limit orders fetch job is correctly integrated into the existing jobs slice.

Comment on lines +567 to +600
// getLimitOrderCoins returns the user's limit order coins
func (p *passthroughUseCase) getLimitOrderCoins(ctx context.Context, address string) (sdk.Coins, error) {
var err error
orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
if err != nil {
return nil, err
}

var limitOrdersCoins sdk.Coins
for _, order := range orders {
denom, derr := func() (string, error) {
switch order.OrderDirection {
case orderbookdomain.DirectionAsk:
return order.BaseAsset.Symbol, nil
case orderbookdomain.DirectionBid:
return order.QuoteAsset.Symbol, nil
default:
return "", fmt.Errorf("unknown order direction: %s", order.OrderDirection)
}
}()
if err != nil {
err = derr // update error
p.logger.Error("unable to get denom for limit order", zap.Error(err))
continue
}

limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
Denom: denom,
Amount: order.Quantity.TruncateInt(),
})
}

return limitOrdersCoins, err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Multiple improvements needed for getLimitOrderCoins

  1. Remove the redundant error variable declaration
  2. Fix error handling to avoid shadowing
  3. Add function documentation

Apply these improvements:

+// getLimitOrderCoins returns the user's limit order coins.
+// For ask orders, it returns the base asset quantity.
+// For bid orders, it returns the quote asset quantity.
+// Returns error if fails to get active orders or if an unknown order direction is encountered.
 func (p *passthroughUseCase) getLimitOrderCoins(ctx context.Context, address string) (sdk.Coins, error) {
-    var err error
     orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
     if err != nil {
         return nil, err
     }

     var limitOrdersCoins sdk.Coins
     for _, order := range orders {
         denom, derr := func() (string, error) {
             switch order.OrderDirection {
             case orderbookdomain.DirectionAsk:
                 return order.BaseAsset.Symbol, nil
             case orderbookdomain.DirectionBid:
                 return order.QuoteAsset.Symbol, nil
             default:
                 return "", fmt.Errorf("unknown order direction: %s", order.OrderDirection)
             }
         }()
-        if err != nil {
-            err = derr
+        if derr != nil {
             p.logger.Error("unable to get denom for limit order", zap.Error(err))
             continue
         }

         limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
             Denom:  denom,
             Amount: order.Quantity.TruncateInt(),
         })
     }

-    return limitOrdersCoins, err
+    return limitOrdersCoins, 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
// getLimitOrderCoins returns the user's limit order coins
func (p *passthroughUseCase) getLimitOrderCoins(ctx context.Context, address string) (sdk.Coins, error) {
var err error
orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
if err != nil {
return nil, err
}
var limitOrdersCoins sdk.Coins
for _, order := range orders {
denom, derr := func() (string, error) {
switch order.OrderDirection {
case orderbookdomain.DirectionAsk:
return order.BaseAsset.Symbol, nil
case orderbookdomain.DirectionBid:
return order.QuoteAsset.Symbol, nil
default:
return "", fmt.Errorf("unknown order direction: %s", order.OrderDirection)
}
}()
if err != nil {
err = derr // update error
p.logger.Error("unable to get denom for limit order", zap.Error(err))
continue
}
limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
Denom: denom,
Amount: order.Quantity.TruncateInt(),
})
}
return limitOrdersCoins, err
}
// getLimitOrderCoins returns the user's limit order coins.
// For ask orders, it returns the base asset quantity.
// For bid orders, it returns the quote asset quantity.
// Returns error if fails to get active orders or if an unknown order direction is encountered.
func (p *passthroughUseCase) getLimitOrderCoins(ctx context.Context, address string) (sdk.Coins, error) {
orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
if err != nil {
return nil, err
}
var limitOrdersCoins sdk.Coins
for _, order := range orders {
denom, derr := func() (string, error) {
switch order.OrderDirection {
case orderbookdomain.DirectionAsk:
return order.BaseAsset.Symbol, nil
case orderbookdomain.DirectionBid:
return order.QuoteAsset.Symbol, nil
default:
return "", fmt.Errorf("unknown order direction: %s", order.OrderDirection)
}
}()
if derr != nil {
p.logger.Error("unable to get denom for limit order", zap.Error(err))
continue
}
limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
Denom: denom,
Amount: order.Quantity.TruncateInt(),
})
}
return limitOrdersCoins, nil
}

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: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6d95de and 8f939b0.

📒 Files selected for processing (1)
  • passthrough/usecase/passthrough_usecase.go (15 hunks)
🔇 Additional comments (4)
passthrough/usecase/passthrough_usecase.go (4)

15-15: LGTM: Clean structural changes

The additions maintain consistency with the existing codebase patterns.

Also applies to: 24-24, 39-39


111-127: LGTM: Clean constructor update

The constructor properly handles the new dependency injection for orderBookUseCase.


146-148: LGTM: Clean limit orders channel setup

The limit orders channel is properly initialized and managed.

Also applies to: 194-201


618-651: 🛠️ Refactor suggestion

Multiple improvements needed for getLimitOrderCoins

  1. Error handling issue on line 638
  2. Unnecessary error variable declaration
  3. Missing function documentation

Apply these improvements:

+// getLimitOrderCoins returns the user's limit order coins.
+// For ask orders, it returns the base asset quantity.
+// For bid orders, it returns the quote asset quantity.
+// Returns error if fails to get active orders or if an unknown order direction is encountered.
 func (p *passthroughUseCase) getLimitOrderCoins(ctx context.Context, address string) (sdk.Coins, error) {
-    var err error
     orders, _, err := p.orderbookUseCase.GetActiveOrders(ctx, address)
     if err != nil {
         return nil, err
     }

     var limitOrdersCoins sdk.Coins
     for _, order := range orders {
         denom, derr := func() (string, error) {
             switch order.OrderDirection {
             case orderbookdomain.DirectionAsk:
                 return order.BaseAsset.Symbol, nil
             case orderbookdomain.DirectionBid:
                 return order.QuoteAsset.Symbol, nil
             default:
                 return "", fmt.Errorf("unknown order direction: %s", order.OrderDirection)
             }
         }()
-        if err != nil {
-            err = derr
+        if derr != nil {
             p.logger.Error("unable to get denom for limit order", zap.Error(err))
             continue
         }

         limitOrdersCoins = limitOrdersCoins.Add(sdk.Coin{
             Denom:  denom,
             Amount: order.Quantity.TruncateInt(),
         })
     }

-    return limitOrdersCoins, err
+    return limitOrdersCoins, nil
}

Likely invalid or redundant comment.

Comment on lines +376 to +378
_, totalAssetsCap, err := p.computeCapitalizationForCoins(ctx, job.coins)
p.logger.Info("total assets composition", zap.String("totalAssetsCategoryName", job.name), zap.Any("Capitalization", totalAssetsCap), zap.Error(err))

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix error variable shadowing in logging statement

The error from computeCapitalizationForCoins shadows the outer error variable, which could lead to incorrect error reporting.

Apply this diff:

-            _, totalAssetsCap, err := p.computeCapitalizationForCoins(ctx, job.coins)
+            _, totalAssetsCap, capErr := p.computeCapitalizationForCoins(ctx, job.coins)
-            p.logger.Info("total assets composition", zap.String("totalAssetsCategoryName", job.name), zap.Any("Capitalization", totalAssetsCap), zap.Error(err))
+            p.logger.Info("total assets composition", zap.String("totalAssetsCategoryName", job.name), zap.Any("Capitalization", totalAssetsCap), zap.Error(capErr))
📝 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
_, totalAssetsCap, err := p.computeCapitalizationForCoins(ctx, job.coins)
p.logger.Info("total assets composition", zap.String("totalAssetsCategoryName", job.name), zap.Any("Capitalization", totalAssetsCap), zap.Error(err))
_, totalAssetsCap, capErr := p.computeCapitalizationForCoins(ctx, job.coins)
p.logger.Info("total assets composition", zap.String("totalAssetsCategoryName", job.name), zap.Any("Capitalization", totalAssetsCap), zap.Error(capErr))

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

Successfully merging this pull request may close these issues.

2 participants