Skip to main content
CosmJS uses the query extension pattern to expose typed query methods on the client. Each extension wraps a protobuf QueryClientImpl generated from your module’s .proto files and attaches its methods to a shared QueryClient.

The Extension Pattern

An extension is a function that takes a QueryClient and returns an object with your query methods, namespaced under a key that represents your module:
The three layers work together:
  1. createProtobufRpcClient wraps the QueryClient into a protobuf-compatible RPC transport
  2. QueryClientImpl (generated from your .proto files) provides typed query methods over that transport
  3. Your extension function maps those raw RPC calls into a developer-friendly API
The outer key (blog above) namespaces your methods on the query client. Choose a name that matches your module to avoid collisions with other extensions.

Composing Extensions

Use QueryClient.withExtensions to combine your extension with built-in ones:
QueryClient.withExtensions supports up to 18 extensions, which is enough for even the most feature-rich chains. The resulting client is fully typed — TypeScript knows about all the query namespaces you’ve composed.

Using QueryClientImpl Directly

If you only need a quick one-off query without composing extensions, use the generated query service directly:
This approach skips the extension boilerplate and is useful for scripts, debugging, or when you only query a single module.

Handling Pagination

Many Cosmos SDK queries return paginated results. Pass PageRequest to control pagination and iterate through all pages:
Iterate through all pages:

Next Steps

Custom Protobuf Types

Register message types in the Registry for signing transactions.

Custom Modules

Combine query extensions with types and Amino converters into a complete module.

Code Generation

Generate QueryClientImpl and message codecs from protobuf definitions.