# Create Custom CosmJS Interfaces
In this section, you will:
- Create custom CosmJS interfaces to connect to custom Cosmos SDK modules.
- Define custom interfaces with Protobuf.
- Define custom types and messages.
- Integrate with Ignite - previously known as Starport.
CosmJS comes out of the box with interfaces that connect with the standard Cosmos modules such as
gov and understand the way their state is serialized. Since your own blockchain's modules are unique, they need custom CosmJS interfaces. That process consists of several steps:
- Creating the Protobuf objects and clients in TypeScript.
- Creating extensions that facilitate the use of the above clients.
- Any further level of abstraction that you deem useful for integration.
This section assumes that you have a working Cosmos blockchain with its own modules. It is based on CosmJS version
v0.28.3 (opens new window).
# Compiling the Protobuf objects and clients
cosmjs-types (opens new window) do is a good choice.
This exercise assumes that:
- Your Protobuf definition files are in
- You want to compile them into TypeScript in
protoc and its TypeScript plugin:
You can confirm the version you received. The executable is located in
This returns something like:
Create the target folder if it does not exist yet:
# Getting third party files
You need to get the imports that appear in your
.proto files. Usually you can find the following in
query.proto (opens new window):
You need local copies of the right file versions in the right locations. Pay particular attention to Cosmos SDK's version of your project. You can check by running:
This returns something like:
Use this version as a tag on Github. One way to retrieve the pagination file (opens new window) is:
You can do the same for the others, found in the
third_party folder (opens new window) under the same version:
You can now compile the Protobuf files. To avoid adding all the
.proto files manually to the command, use
--proto_path is only
./proto so that your imports (such as
import "cosmos/base...) can be found.
You should now see your files compiled into TypeScript. They have been correctly filed under their respective folders and contain both types and services definitions. It also created the compiled versions of your third party imports.
# A note about the result
tx.proto file may have contained the following:
If so, you find its service declaration in the compiled
It also appears in the default implementation:
The important points to remember from this are:
rpc: RPCis an instance of a Protobuf RPC client that is given to you by CosmJS. Although the interface appears to be declared locally (opens new window), this is the same interface found throughout CosmJS (opens new window). It is given to you on construction (opens new window). At this point you do not need an implementation for it.
- You can see
decodein action. Notice the
.finish()that flushes the Protobuf writer buffer.
rpc.requestmakes calls that are correctly understood by the Protobuf compiled server on the other side.
You can find the same structure in
query.ts (opens new window).
# Proper saving
Commit the extra
.proto files as well as the compiled ones to your repository so you do not need to recreate them.
Take inspiration from
codegen.sh (opens new window):
- Create a script file named
ts-proto.shwith the previous command.
- Add an npm run target (opens new window) with it, to keep track of how this was done and easily reproduce it in the future when you update a Protobuf file.
# Add convenience with types
CosmJS provides an interface to which all the created types conform,
TsProtoGeneratedType (opens new window), which is itself a sub-type of
GeneratedType (opens new window). In the same file, note the definition:
typeUrl is the identifier by which Protobuf identifies the type of the data to serialize or deserialize. It is composed of the type's package and its name. For instance (and see also here (opens new window)):
In this case, the
MsgSend's type URL is
"/cosmos.bank.v1beta1.MsgSend" (opens new window).
Each of your types is associated like this. You can declare each string as a constant value, such as:
Save those along with
# For messages
Messages, sub-types of
Msg, are assembled into transactions that are then sent to Tendermint. CosmJS types already include types for transactions (opens new window). These are assembled, signed, and sent by the
SigningStargateClient (opens new window) of CosmJS.
Msg kind also needs to be added to a registry. To facilitate that, you should prepare them in a nested array:
Add child types to
In the previous code, you cannot reuse your
msgSendTypeUrl because it is a value not a type. You can add a type helper, which is useful in an
if else situation:
# For queries
Unlike transactions, which are sent to Tendermint, queries are sent to the application. Queries have very different types of calls. It makes sense to organize them in one place, called an extension. For example:
Note that there is a key
bank: inside it. This becomes important later on when you add it to Stargate.
- Create an extension interface for your module using function names and parameters that satisfy your needs.
- It is recommended to make sure that the key is unique and does not overlap with any other modules of your application.
- Create a factory for its implementation copying the model here (opens new window). Remember that the
QueryClientImpl(opens new window) implementation must come from your own compiled Protobuf query service.
# Integration with Stargate
SigningStargateClient are typically the ultimate abstractions that facilitate the querying and sending of transactions. You are now ready to add your own elements to them. The easiest way is to inherit from them and expose the extra functions you require.
If your extra functions map one-for-one with those of your own extension, then you can publicly expose the extension itself to minimize duplication in
StargateClient (opens new window) and
SigningStargateClient (opens new window).
For example, if you have your
interface MyExtension with a
myKey key and you are creating
You can extend
StargateClientOptions (opens new window) if your own client can receive further options.
You also need to inform
MySigningStargateClient about the extra encodable types it should be able to handle. The list is defined in a registry that you can pass as options (opens new window).
Take inspiration from the
SigningStargateClient source code (opens new window) itself. Collect your new types into an array:
Taking inspiration from the same place (opens new window), add the registry creator:
Now you are ready to combine this into your own
MySigningStargateClient. It still takes an optional registry, but if that is missing it adds your newly defined default one:
You can optionally add dedicated functions that use your own types, modeled on:
You are ready to import and use this in a server script or a GUI.
To summarize, this section has explored:
- How CosmJS's out-of-the-box interfaces understand how the state of standard Cosmos modules is serialized, meaning that your unique modules will require custom CosmJS interfaces of their own.
- How to create the necessary Protobuf objects and clients in Typescript, the extensions that facilitate the use of these clients, and any further level of abstraction that you deem useful for integration.
- How to integrate CosmJS with Ignite's client and signing client, which are typically the ultimate abstractions that facilitate the querying and sending of transactions.
# What next?The Cosmos is vast, with lots of projects, people and concepts to discover:
- Reach out to the community.
- Contribute to the Cosmos SDK, IBC, and Tendermint BFT consensus development.
- Get support for enterprise solutions which you are developing.
Head to the What's Next section to find useful information to launch your journey into the Cosmos universe.