Skip to content

fix(tokenfactory): add pagination to DenomsFromCreator query (PLT-410)#3524

Open
amir-deris wants to merge 9 commits into
mainfrom
amir/plt-410-denoms-from-creator-pagination
Open

fix(tokenfactory): add pagination to DenomsFromCreator query (PLT-410)#3524
amir-deris wants to merge 9 commits into
mainfrom
amir/plt-410-denoms-from-creator-pagination

Conversation

@amir-deris

@amir-deris amir-deris commented May 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Changes

  • proto/tokenfactory/query.proto — added PageRequest/PageResponse pagination fields to DenomsFromCreator request and response
  • x/tokenfactory/types/query.pb.go — regenerated via scripts/protoc.sh
  • x/tokenfactory/types/query.pb.gw.go — regenerated; REST gateway now reads ?pagination.* query parameters
  • x/tokenfactory/keeper/creators.go — replaced raw unbounded iterator with query.Paginate
  • x/tokenfactory/keeper/grpc_query.go — threads pagination through the handler
  • x/tokenfactory/client/cli/query.go — exposes --page-* flags on the denoms-from-creator command
  • x/tokenfactory/keeper/grpc_query_test.go — added pagination tests (no pagination, limit, key-based cursor, offset)
  • wasmbinding/test/query_test.go — fixed assertions to compare only Denoms field since Pagination is now always non-nil in the response

Notes

  • Pagination is optional and backward-compatible — callers that omit it get DefaultLimit = 100 results
  • Hard limits (MaxLimit = 1000, MaxOffset = 10000) are enforced by query.Paginate once PLT-361 lands; this PR depends on that for the cap to be in effect

🤖 Generated with Claude Code

@cursor

cursor Bot commented May 29, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
API behavior changes for callers that omitted pagination (capped at default limit); wasm path mitigates with MaxLimit default. Query surface is widely used by contracts and indexers.

Overview
Adds Cosmos-style pagination to the tokenfactory DenomsFromCreator query so it no longer does an unbounded prefix-store scan.

The proto request/response gain PageRequest / PageResponse; the keeper switches from a full iterator to query.Paginate, and responses always include pagination metadata. CLI passes --page-* flags; REST binds pagination.* query params on denoms_from_creator/{creator}.

Wasm queries without pagination (or with limit: 0) default to query.MaxLimit so contracts that expected a single large page still get up to the paginator cap. gRPC/CLI callers that omit pagination get the standard default page size (100), not the full list—reviewers should flag any off-chain client that assumed an unbounded result set.

Reviewed by Cursor Bugbot for commit 8a7754c. Bugbot is set up for automated code reviews on this repo. Configure here.

@amir-deris amir-deris changed the title Amir/plt 410 denoms from creator pagination fix(tokenfactory): add pagination to DenomsFromCreator query (PLT-410) May 29, 2026
@github-actions

github-actions Bot commented May 29, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedJun 12, 2026, 11:35 PM

@amir-deris amir-deris requested review from bdchatham and masih May 29, 2026 22:55
@codecov

codecov Bot commented May 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 47.82609% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.35%. Comparing base (57bba16) to head (8a7754c).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
x/tokenfactory/client/cli/query.go 0.00% 6 Missing ⚠️
x/tokenfactory/client/wasm/query.go 50.00% 1 Missing and 1 partial ⚠️
x/tokenfactory/keeper/creators.go 77.77% 1 Missing and 1 partial ⚠️
x/tokenfactory/keeper/grpc_query.go 50.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3524      +/-   ##
==========================================
- Coverage   59.22%   58.35%   -0.88%     
==========================================
  Files        2214     2140      -74     
  Lines      183402   174868    -8534     
==========================================
- Hits       108619   102042    -6577     
+ Misses      64994    63733    -1261     
+ Partials     9789     9093     -696     
Flag Coverage Δ
sei-chain-pr 65.14% <47.82%> (?)
sei-db 70.41% <ø> (ø)
sei-db-state-db ?

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

Files with missing lines Coverage Δ
x/tokenfactory/client/wasm/query.go 84.61% <50.00%> (-15.39%) ⬇️
x/tokenfactory/keeper/creators.go 86.66% <77.77%> (-13.34%) ⬇️
x/tokenfactory/keeper/grpc_query.go 84.21% <50.00%> (-4.68%) ⬇️
x/tokenfactory/client/cli/query.go 0.00% <0.00%> (ø)

... and 74 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread x/tokenfactory/keeper/creators.go
@masih masih requested a review from sei-will June 10, 2026 11:14
@masih

masih commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

@claude review this pr

@masih masih left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we still have a pagination issue here? totally fine if that's going to be resolved in a follow up PR

Comment thread x/tokenfactory/client/wasm/query.go Outdated
// defaultDenomsFromCreatorLimit is the wasm query default, higher than the gRPC DefaultLimit of 100
// for backwards compatibility with contracts that expect all denoms in one response, but still
// bounded to limit DoS risk since denom creation has no fee.
const defaultDenomsFromCreatorLimit = 2000

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Does this value make sense given #3494 is open?

2K will be rejected once that PR lands. What are your thoughts in terms of coordinating the two PRs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for great feedback, that is a great point. I will modify this to reference the query.MaxLimit instead which should still work and not conflict with PR 3494

// DenomsFromCreator gRPC query.
message QueryDenomsFromCreatorResponse {
repeated string denoms = 1 [(gogoproto.moretags) = "yaml:\"denoms\""];
cosmos.base.query.v1beta1.PageResponse pagination = 2;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this would be an apphash breaking change but the PR is labeled as non-apphash breaking.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for feedback. It seems that is not the case regarding app hash breaking change, since this is a protocol buffer query and results are not part of the state. Do we have any test that would fail if this was an app hash breaking change and incorrectly labeled non-app-hash-breaking?

The app hash is the Merkle root of committed state — it only changes when something alters what gets written to the KV store during block execution (DeliverTx, BeginBlock, EndBlock, InitChain). The changes here
  are entirely in the query plane:

  - QueryDenomsFromCreatorRequest and QueryDenomsFromCreatorResponse are only used by the gRPC/REST query handler — they never touch state, never go through consensus, and are never committed.
  - query.pb.go / query.pb.gw.go regeneration only affects how query messages are serialized over the wire; it has no effect on the state machine.
  - x/tokenfactory/keeper/creators.go now calls query.Paginate instead of a raw iterator, but getDenomsFromCreator is a read-only keeper method — it doesn't write anything.

  The only thing that could make a query-proto change app-hash-breaking is if the query result were hashed into state somewhere (e.g. stored as a module param or emitted as a deterministic event used in consensus),
  which isn't the case here.```

@amir-deris

Copy link
Copy Markdown
Contributor Author

I think we still have a pagination issue here? totally fine if that's going to be resolved in a follow up PR

@masih I believe that issue is going to be resolved in this pr: #3494 so there shouldn't be any pagination issue 🤔 Please correct me if I am wrong.

Comment thread x/tokenfactory/client/wasm/query.go

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8a7754c. Configure here.

req.Pagination = &query.PageRequest{Limit: defaultDenomsFromCreatorLimit}
} else if req.Pagination.Limit == 0 {
req.Pagination.Limit = defaultDenomsFromCreatorLimit
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Wasm offset zero limit breaks

Medium Severity

When a wasm DenomsFromCreator query sets pagination.offset but leaves limit at zero, the handler replaces limit with query.MaxLimit. In query.Paginate, end is computed as offset + limit, which overflows for a large limit and an non-zero offset, so no denoms match the window and the response can be empty instead of the expected slice.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8a7754c. Configure here.

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