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

add topN endpoint to supply module (disabled by default) #1800

Merged
merged 17 commits into from
Jan 30, 2025
Merged

Conversation

joe-bowman
Copy link
Contributor

@joe-bowman joe-bowman commented Jan 27, 2025

1. Summary

Add rest endpoint to supply module that returns topN accounts. Used by CoinmarketCap.

2.Type of change

  • New feature (non-breaking change which adds functionality)

Summary by CodeRabbit

  • New Features

    • Added a new gRPC endpoint /quicksilver/supply/v1/topn/{n} to retrieve top N accounts by balance.
    • Implemented functionality to list and rank accounts based on their token balances.
  • Technical Improvements

    • Enhanced query service with an additional method for retrieving account rankings.
    • Updated message structures to accommodate new requirements for querying top accounts.
    • Improved logic for calculating circulating supply and handling account exclusions.
  • Tests

    • Added unit tests for the new TopN functionality and various scenarios for the SupplyKeeper.

Copy link
Contributor

coderabbitai bot commented Jan 27, 2025

Walkthrough

The pull request introduces a new feature to the Quicksilver supply module that allows querying the top N accounts by balance. This involves extending the proto definitions, adding a new gRPC query method, and implementing the corresponding keeper logic. The changes include creating new message types for the top N accounts request and response, adding a new RPC method in the Query service, and implementing the backend logic to retrieve and sort accounts based on their balances.

Changes

File Change Summary
proto/quicksilver/supply/v1/query.proto - Added imports for external proto files
- Added new RPC method TopN
- Introduced new message types: QueryTopNRequest, QueryTopNResponse, and Account
- Modified QuerySupplyResponse fields to change types from uint64 to string
x/supply/keeper/grpc_query.go - Added TopN method to Querier struct
- Implements gRPC query handling for top N accounts
x/supply/keeper/keeper.go - Added TopN method to Keeper struct
- Implements logic to retrieve and sort top N accounts by balance
- Enhanced CalculateCirculatingSupply method for address matching
x/supply/types/expected_keepers.go - Added IterateAllDelegations method to StakingKeeper interface
docs/swagger.yml - Added new endpoint GET /quicksilver/supply/v1/topn/{n} with operation ID TopN
- Defined response schema and parameters for the new endpoint
x/supply/keeper/grpc_query_test.go - Added unit tests for TopN and Supply methods, including disabled feature checks
x/supply/keeper/msg_server_test.go - Enhanced test coverage for MsgIncentivePoolSpend with new scenarios

Possibly related PRs

  • Unbond recovery #1704: This PR introduces a new method TopN to the Querier struct, which is directly related to the new TopN RPC method added in the main PR, enhancing the querying capabilities for top accounts.
  • fix: use %q instead of manual \"%s\" #1723: This PR modifies the CancelRedemption and RequeueRedemption methods in the msgServer, which are relevant as they involve changes to the handling of redemption processes, similar to the enhancements made in the main PR regarding account queries.
  • use bech32 addresses for mapped address queries; resolves #1719 #1766: This PR adds a new query for inverse mapped addresses and modifies existing queries to use bech32 encoding, which relates to the overall improvements in querying capabilities introduced in the main PR.

Suggested reviewers

  • faddat
  • joe-bowman

Poem

🐰 Hop, hop, into the supply's domain,
Where accounts dance in a balance refrain!
Top N accounts, now we can see,
A rabbit's view of financial glee!
Sorted and ranked with mathematical might,
Our crypto exploration takes flight! 🚀

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

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.

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.

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

🧹 Nitpick comments (3)
x/supply/keeper/keeper.go (1)

85-122: Consider performance implications and memory usage.

The current implementation loads all accounts into memory before sorting. For chains with a large number of accounts, this could lead to high memory usage and potential performance issues.

Consider these alternatives:

  1. Implement pagination to process accounts in batches
  2. Use a min-heap to maintain top N accounts while iterating
  3. Add caching with a configurable TTL to prevent frequent recalculations

Would you like me to provide an implementation for any of these approaches?

proto/quicksilver/supply/v1/query.proto (2)

18-20: Add documentation for the TopN endpoint.

The RPC endpoint lacks documentation describing its purpose, parameters, and response format.

Add documentation comments:

+  // TopN returns the top N accounts sorted by total balance (liquid + staked).
+  // This endpoint is intended for use by CoinmarketCap.
+  // {n} parameter specifies the number of accounts to return (max: 100).
   rpc TopN(QueryTopNRequest) returns (QueryTopNResponse) {
     option (google.api.http).get = "/quicksilver/supply/v1/topn/{n}";
   }

38-40: Add field constraints and documentation.

The n field in QueryTopNRequest should have constraints and documentation.

Add field constraints:

 message QueryTopNRequest {
+  // n specifies the number of top accounts to return (max: 100)
+  uint64 n = 1 [(gogoproto.moretags) = "validate:\"required,min=1,max=100\""];
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 166c496 and 897513d.

⛔ Files ignored due to path filters (2)
  • x/supply/types/query.pb.go is excluded by !**/*.pb.go
  • x/supply/types/query.pb.gw.go is excluded by !**/*.pb.gw.go
📒 Files selected for processing (4)
  • proto/quicksilver/supply/v1/query.proto (2 hunks)
  • x/supply/keeper/grpc_query.go (1 hunks)
  • x/supply/keeper/keeper.go (2 hunks)
  • x/supply/types/expected_keepers.go (2 hunks)
🧰 Additional context used
🪛 golangci-lint (1.62.2)
x/supply/keeper/grpc_query.go

[high] 53-53: G115: integer overflow conversion uint64 -> int

(gosec)

🪛 GitHub Check: lint
x/supply/keeper/grpc_query.go

[failure] 53-53:
G115: integer overflow conversion uint64 -> int (gosec)

🪛 GitHub Actions: golangci-lint
x/supply/keeper/grpc_query.go

[error] 53-53: G115: Potential integer overflow in conversion from uint64 to int

🪛 Buf (1.47.2)
proto/quicksilver/supply/v1/query.proto

4-4: import "cosmos/base/v1beta1/coin.proto": file does not exist

(COMPILE)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: test quicksilver (darwin, arm64)
  • GitHub Check: test quicksilver (amd64, windows)
  • GitHub Check: test quicksilver (amd64, linux)
  • GitHub Check: Analyze
🔇 Additional comments (1)
x/supply/types/expected_keepers.go (1)

25-25: LGTM! Clean interface extension.

The addition of IterateAllDelegations to the StakingKeeper interface is well-defined and follows existing patterns.

x/supply/keeper/grpc_query.go Outdated Show resolved Hide resolved
x/supply/keeper/keeper.go Show resolved Hide resolved
Copy link

codecov bot commented Jan 27, 2025

Codecov Report

Attention: Patch coverage is 87.23404% with 6 lines in your changes missing coverage. Please review.

Project coverage is 63.37%. Comparing base (3b270d9) to head (28ad3b4).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
x/supply/keeper/keeper.go 83.33% 4 Missing and 2 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1800      +/-   ##
==========================================
+ Coverage   63.02%   63.37%   +0.34%     
==========================================
  Files         172      172              
  Lines       15377    15422      +45     
==========================================
+ Hits         9691     9773      +82     
+ Misses       4876     4838      -38     
- Partials      810      811       +1     
Flag Coverage Δ
unittests 63.37% <87.23%> (+0.34%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
x/supply/keeper/grpc_query.go 100.00% <100.00%> (+91.30%) ⬆️
x/supply/keeper/keeper.go 85.50% <83.33%> (+53.15%) ⬆️

... and 1 file with indirect coverage changes

arhamchordia
arhamchordia previously approved these changes Jan 28, 2025
Copy link
Contributor

@arhamchordia arhamchordia left a comment

Choose a reason for hiding this comment

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

Changes look good here.

@arhamchordia
Copy link
Contributor

Can be merged once CI passes.

x/supply/keeper/grpc_query_test.go Dismissed Show resolved Hide resolved
@joe-bowman
Copy link
Contributor Author

joe-bowman commented Jan 30, 2025 via email

Copy link
Contributor

@arhamchordia arhamchordia left a comment

Choose a reason for hiding this comment

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

Added the changes by suggestions in comments and merged them here.

@joe-bowman joe-bowman enabled auto-merge (squash) January 30, 2025 10:14
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: 2

♻️ Duplicate comments (1)
x/supply/keeper/grpc_query.go (1)

48-56: ⚠️ Potential issue

Add input validation and fix potential integer overflow.

The TopN implementation needs input validation and proper type handling:

  1. Missing input validation for req.N
  2. Potential integer overflow when using large values of N

Apply this diff to fix both issues:

 func (q Querier) TopN(c context.Context, req *types.QueryTopNRequest) (*types.QueryTopNResponse, error) {
     ctx := sdk.UnwrapSDKContext(c)
 
     if q.endpointEnabled {
+        // Validate input
+        if req.N == 0 {
+            return nil, fmt.Errorf("n must be greater than 0")
+        }
+        if req.N > 100 {
+            return nil, fmt.Errorf("n must not exceed 100")
+        }
         accounts := q.Keeper.TopN(ctx, q.stakingKeeper.BondDenom(ctx), req.N)
         return &types.QueryTopNResponse{Accounts: accounts}, nil
     }
     return nil, fmt.Errorf("endpoint disabled")
 }
🧹 Nitpick comments (2)
x/supply/keeper/grpc_query.go (1)

Line range hint 31-41: Consider moving excluded addresses to configuration.

The list of excluded addresses is hard-coded. Consider moving this to a configuration file or chain parameters for better maintainability.

x/supply/keeper/keeper.go (1)

99-99: Add documentation for the TopN method.

Consider adding documentation to describe:

  • The purpose of the method
  • The meaning of the parameters
  • The structure of the returned accounts
  • Any performance implications for large values of n
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 897513d and 28ad3b4.

⛔ Files ignored due to path filters (2)
  • go.work.sum is excluded by !**/*.sum
  • x/supply/types/query.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (7)
  • docs/swagger.yml (1 hunks)
  • proto/quicksilver/supply/v1/query.proto (2 hunks)
  • x/supply/keeper/grpc_query.go (1 hunks)
  • x/supply/keeper/grpc_query_test.go (1 hunks)
  • x/supply/keeper/keeper.go (4 hunks)
  • x/supply/keeper/msg_server_test.go (1 hunks)
  • x/supply/types/expected_keepers.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • x/supply/types/expected_keepers.go
🧰 Additional context used
📓 Learnings (1)
x/supply/keeper/grpc_query_test.go (1)
Learnt from: arhamchordia
PR: quicksilver-zone/quicksilver#1803
File: x/supply/keeper/keeper_test.go:31-66
Timestamp: 2025-01-28T19:03:57.668Z
Learning: Avoid suggesting test cases that duplicate functionality already tested in msg_server_test.go, particularly for module account operations and balance transfers. Focus on unique keeper functionality instead.
🪛 Buf (1.47.2)
proto/quicksilver/supply/v1/query.proto

4-4: import "cosmos/base/v1beta1/coin.proto": file does not exist

(COMPILE)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: test quicksilver (amd64, linux)
  • GitHub Check: Analyze
🔇 Additional comments (6)
x/supply/keeper/grpc_query_test.go (1)

1-112: LGTM! Comprehensive test coverage.

The test suite provides excellent coverage:

  • Tests both enabled and disabled states
  • Validates excluded accounts behavior
  • Verifies TopN functionality with realistic values
x/supply/keeper/msg_server_test.go (1)

48-75: LGTM! Good test coverage for invalid cases.

The additional test cases for invalid and blocked addresses enhance the robustness of the test suite.

x/supply/keeper/keeper.go (3)

68-70: LGTM!

Simple and clean implementation of the feature flag.


76-76: LGTM! Good optimization.

Using bytes.Equal for address comparison is more efficient than string comparison.


99-139: LGTM! Well-structured implementation.

The implementation is efficient and secure:

  • Uses maps for O(1) lookups
  • Properly filters module accounts
  • Includes bounds checking to prevent panic
  • Correctly aggregates balances from both direct holdings and delegations
docs/swagger.yml (1)

5249-5296: LGTM! Well-documented API specification.

The Swagger specification for the new topN endpoint is complete and follows OpenAPI conventions:

  • Clear endpoint path and method
  • Proper parameter definition with type and format
  • Well-structured response schema
  • Standard error response handling

proto/quicksilver/supply/v1/query.proto Show resolved Hide resolved
proto/quicksilver/supply/v1/query.proto Show resolved Hide resolved
@joe-bowman joe-bowman merged commit b26f4b8 into main Jan 30, 2025
17 checks passed
@joe-bowman joe-bowman deleted the topn branch January 30, 2025 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants